forked from TrueCloudLab/neoneo-go
Merge pull request #920 from nspcc-dev/neo3/transaction/cosigners
core: implement cosigners mechanism
This commit is contained in:
commit
ec6ade4c9b
30 changed files with 420 additions and 158 deletions
|
@ -79,16 +79,12 @@ func getTX(t *testing.B, wif *keys.WIF) *transaction.Transaction {
|
|||
|
||||
tx := transaction.NewInvocationTX([]byte{0x51}, 1)
|
||||
tx.Version = 0
|
||||
tx.Sender = fromAddressHash
|
||||
tx.Attributes = append(tx.Attributes,
|
||||
transaction.Attribute{
|
||||
Usage: transaction.Description,
|
||||
Data: []byte(randString(10)),
|
||||
})
|
||||
tx.Attributes = append(tx.Attributes,
|
||||
transaction.Attribute{
|
||||
Usage: transaction.Script,
|
||||
Data: fromAddressHash.BytesBE(),
|
||||
})
|
||||
return tx
|
||||
}
|
||||
|
||||
|
|
|
@ -1548,17 +1548,6 @@ func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([
|
|||
for i := range references {
|
||||
hashes[references[i].Out.ScriptHash] = true
|
||||
}
|
||||
for _, a := range t.Attributes {
|
||||
if a.Usage == transaction.Script {
|
||||
h, err := util.Uint160DecodeBytesBE(a.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := hashes[h]; !ok {
|
||||
hashes[h] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for a, outputs := range t.GroupOutputByAssetID() {
|
||||
as := bc.GetAssetState(a)
|
||||
|
@ -1575,6 +1564,9 @@ func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([
|
|||
}
|
||||
}
|
||||
hashes[t.Sender] = true
|
||||
for _, c := range t.Cosigners {
|
||||
hashes[c.Account] = true
|
||||
}
|
||||
switch t.Type {
|
||||
case transaction.ClaimType:
|
||||
claim := t.Data.(*transaction.ClaimTX)
|
||||
|
|
|
@ -2,6 +2,7 @@ package runtime
|
|||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
|
@ -10,7 +11,12 @@ import (
|
|||
|
||||
// CheckHashedWitness checks given hash against current list of script hashes
|
||||
// for verifying in the interop context.
|
||||
func CheckHashedWitness(ic *interop.Context, hash util.Uint160) (bool, error) {
|
||||
func CheckHashedWitness(ic *interop.Context, v vm.ScriptHashGetter, hash util.Uint160) (bool, error) {
|
||||
if tx, ok := ic.Container.(*transaction.Transaction); ok {
|
||||
return checkScope(tx, v, hash)
|
||||
}
|
||||
|
||||
// only for non-Transaction types (Block, etc.)
|
||||
hashes, err := ic.Chain.GetScriptHashesForVerifying(ic.Tx)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "failed to get script hashes")
|
||||
|
@ -23,10 +29,57 @@ func CheckHashedWitness(ic *interop.Context, hash util.Uint160) (bool, error) {
|
|||
return false, nil
|
||||
}
|
||||
|
||||
func checkScope(tx *transaction.Transaction, v vm.ScriptHashGetter, hash util.Uint160) (bool, error) {
|
||||
for _, c := range tx.Cosigners {
|
||||
if c.Account == hash {
|
||||
if c.Scopes == transaction.Global {
|
||||
return true, nil
|
||||
}
|
||||
if c.Scopes&transaction.CalledByEntry != 0 {
|
||||
callingScriptHash := v.GetCallingScriptHash()
|
||||
entryScriptHash := v.GetEntryScriptHash()
|
||||
if callingScriptHash == entryScriptHash {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
if c.Scopes&transaction.CustomContracts != 0 {
|
||||
currentScriptHash := v.GetCurrentScriptHash()
|
||||
for _, allowedContract := range c.AllowedContracts {
|
||||
if allowedContract == currentScriptHash {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if c.Scopes&transaction.CustomGroups != 0 {
|
||||
return true, nil
|
||||
// TODO: we don't currently have Manifest field in ContractState
|
||||
/*callingScriptHash := v.GetCallingScriptHash()
|
||||
if callingScriptHash.Equals(util.Uint160{}){
|
||||
return false, nil
|
||||
}
|
||||
cs, err := ic.DAO.GetContractState(callingScriptHash)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
// check if the current group is the required one
|
||||
for _, allowedGroup := range c.AllowedGroups {
|
||||
for _, group := range cs.Manifest.Groups {
|
||||
if group.PublicKey.Equal(allowedGroup) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// CheckKeyedWitness checks hash of signature check contract with a given public
|
||||
// key against current list of script hashes for verifying in the interop context.
|
||||
func CheckKeyedWitness(ic *interop.Context, key *keys.PublicKey) (bool, error) {
|
||||
return CheckHashedWitness(ic, key.GetScriptHash())
|
||||
func CheckKeyedWitness(ic *interop.Context, v vm.ScriptHashGetter, key *keys.PublicKey) (bool, error) {
|
||||
return CheckHashedWitness(ic, v, key.GetScriptHash())
|
||||
}
|
||||
|
||||
// CheckWitness checks witnesses.
|
||||
|
@ -42,9 +95,9 @@ func CheckWitness(ic *interop.Context, v *vm.VM) error {
|
|||
if err != nil {
|
||||
return errors.New("parameter given is neither a key nor a hash")
|
||||
}
|
||||
res, err = CheckKeyedWitness(ic, key)
|
||||
res, err = CheckKeyedWitness(ic, v, key)
|
||||
} else {
|
||||
res, err = CheckHashedWitness(ic, hash)
|
||||
res, err = CheckHashedWitness(ic, v, hash)
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to check")
|
||||
|
|
|
@ -540,7 +540,7 @@ func contractMigrate(ic *interop.Context, v *vm.VM) error {
|
|||
return err
|
||||
}
|
||||
if contract.HasStorage() {
|
||||
hash := v.GetContextScriptHash(0)
|
||||
hash := v.GetCurrentScriptHash()
|
||||
siMap, err := ic.DAO.GetStorageItems(hash)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -601,7 +601,7 @@ func assetCreate(ic *interop.Context, v *vm.VM) error {
|
|||
if owner.IsInfinity() {
|
||||
return errors.New("can't have infinity as an owner key")
|
||||
}
|
||||
witnessOk, err := runtime.CheckKeyedWitness(ic, owner)
|
||||
witnessOk, err := runtime.CheckKeyedWitness(ic, v, owner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -292,7 +292,7 @@ func runtimeNotify(ic *interop.Context, v *vm.VM) error {
|
|||
if err != nil {
|
||||
item = vm.NewByteArrayItem([]byte(fmt.Sprintf("bad notification: %v", err)))
|
||||
}
|
||||
ne := state.NotificationEvent{ScriptHash: v.GetContextScriptHash(0), Item: item}
|
||||
ne := state.NotificationEvent{ScriptHash: v.GetCurrentScriptHash(), Item: item}
|
||||
ic.Notifications = append(ic.Notifications, ne)
|
||||
return nil
|
||||
}
|
||||
|
@ -301,7 +301,7 @@ func runtimeNotify(ic *interop.Context, v *vm.VM) error {
|
|||
func runtimeLog(ic *interop.Context, v *vm.VM) error {
|
||||
msg := fmt.Sprintf("%q", v.Estack().Pop().Bytes())
|
||||
ic.Log.Info("runtime log",
|
||||
zap.Stringer("script", v.GetContextScriptHash(0)),
|
||||
zap.Stringer("script", v.GetCurrentScriptHash()),
|
||||
zap.String("logs", msg))
|
||||
return nil
|
||||
}
|
||||
|
@ -383,7 +383,7 @@ func storageGet(ic *interop.Context, v *vm.VM) error {
|
|||
// storageGetContext returns storage context (scripthash).
|
||||
func storageGetContext(ic *interop.Context, v *vm.VM) error {
|
||||
sc := &StorageContext{
|
||||
ScriptHash: v.GetContextScriptHash(0),
|
||||
ScriptHash: v.GetCurrentScriptHash(),
|
||||
ReadOnly: false,
|
||||
}
|
||||
v.Estack().PushVal(vm.NewInteropItem(sc))
|
||||
|
@ -393,7 +393,7 @@ func storageGetContext(ic *interop.Context, v *vm.VM) error {
|
|||
// storageGetReadOnlyContext returns read-only context (scripthash).
|
||||
func storageGetReadOnlyContext(ic *interop.Context, v *vm.VM) error {
|
||||
sc := &StorageContext{
|
||||
ScriptHash: v.GetContextScriptHash(0),
|
||||
ScriptHash: v.GetCurrentScriptHash(),
|
||||
ReadOnly: true,
|
||||
}
|
||||
v.Estack().PushVal(vm.NewInteropItem(sc))
|
||||
|
@ -475,7 +475,7 @@ func contractDestroy(ic *interop.Context, v *vm.VM) error {
|
|||
if ic.Trigger != trigger.Application {
|
||||
return errors.New("can't destroy contract when not triggered by application")
|
||||
}
|
||||
hash := v.GetContextScriptHash(0)
|
||||
hash := v.GetCurrentScriptHash()
|
||||
cs, err := ic.DAO.GetContractState(hash)
|
||||
if err != nil {
|
||||
return nil
|
||||
|
|
|
@ -69,7 +69,7 @@ func (cs *Contracts) GetNativeInterop(ic *interop.Context) func(uint32) *vm.Inte
|
|||
// getNativeInterop returns native contract interop.
|
||||
func getNativeInterop(ic *interop.Context, c interop.Contract) func(v *vm.VM) error {
|
||||
return func(v *vm.VM) error {
|
||||
h := v.GetContextScriptHash(0)
|
||||
h := v.GetCurrentScriptHash()
|
||||
if !h.Equals(c.Metadata().Hash) {
|
||||
return errors.New("invalid hash")
|
||||
}
|
||||
|
|
|
@ -251,7 +251,7 @@ func (n *NEO) vote(ic *interop.Context, args []vm.StackItem) vm.StackItem {
|
|||
|
||||
// VoteInternal votes from account h for validarors specified in pubs.
|
||||
func (n *NEO) VoteInternal(ic *interop.Context, h util.Uint160, pubs keys.PublicKeys) error {
|
||||
ok, err := runtime.CheckHashedWitness(ic, h)
|
||||
ok, err := runtime.CheckHashedWitness(ic, neoScriptHash{hash: n.Hash}, h)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !ok {
|
||||
|
@ -479,3 +479,24 @@ func toPublicKey(s vm.StackItem) *keys.PublicKey {
|
|||
}
|
||||
return pub
|
||||
}
|
||||
|
||||
// scriptHash is an auxiliary structure which implements ScriptHashGetter
|
||||
// interface over NEO native contract and is used for runtime.CheckHashedWitness
|
||||
type neoScriptHash struct {
|
||||
hash util.Uint160
|
||||
}
|
||||
|
||||
// GetCallingScriptHash implements ScriptHashGetter interface
|
||||
func (s neoScriptHash) GetCallingScriptHash() util.Uint160 {
|
||||
return util.Uint160{}
|
||||
}
|
||||
|
||||
// GetEntryScriptHash implements ScriptHashGetter interface
|
||||
func (s neoScriptHash) GetEntryScriptHash() util.Uint160 {
|
||||
return s.hash
|
||||
}
|
||||
|
||||
// GetCurrentScriptHash implements ScriptHashGetter interface
|
||||
func (s neoScriptHash) GetCurrentScriptHash() util.Uint160 {
|
||||
return s.hash
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ func NewAccount(scriptHash util.Uint160) *Account {
|
|||
// DecodeBinary decodes Account from the given BinReader.
|
||||
func (s *Account) DecodeBinary(br *io.BinReader) {
|
||||
s.Version = uint8(br.ReadB())
|
||||
br.ReadBytes(s.ScriptHash[:])
|
||||
s.ScriptHash.DecodeBinary(br)
|
||||
s.IsFrozen = br.ReadBool()
|
||||
|
||||
s.Balances = make(map[util.Uint256][]UnspentBalance)
|
||||
|
@ -73,7 +73,7 @@ func (s *Account) DecodeBinary(br *io.BinReader) {
|
|||
// EncodeBinary encodes Account to the given BinWriter.
|
||||
func (s *Account) EncodeBinary(bw *io.BinWriter) {
|
||||
bw.WriteB(byte(s.Version))
|
||||
bw.WriteBytes(s.ScriptHash[:])
|
||||
s.ScriptHash.EncodeBinary(bw)
|
||||
bw.WriteBool(s.IsFrozen)
|
||||
|
||||
bw.WriteVarUint(uint64(len(s.Balances)))
|
||||
|
|
|
@ -37,11 +37,11 @@ func (a *Asset) DecodeBinary(br *io.BinReader) {
|
|||
a.Available.DecodeBinary(br)
|
||||
a.Precision = uint8(br.ReadB())
|
||||
a.FeeMode = uint8(br.ReadB())
|
||||
br.ReadBytes(a.FeeAddress[:])
|
||||
a.FeeAddress.DecodeBinary(br)
|
||||
|
||||
a.Owner.DecodeBinary(br)
|
||||
br.ReadBytes(a.Admin[:])
|
||||
br.ReadBytes(a.Issuer[:])
|
||||
a.Admin.DecodeBinary(br)
|
||||
a.Issuer.DecodeBinary(br)
|
||||
a.Expiration = br.ReadU32LE()
|
||||
a.IsFrozen = br.ReadBool()
|
||||
}
|
||||
|
@ -55,12 +55,12 @@ func (a *Asset) EncodeBinary(bw *io.BinWriter) {
|
|||
a.Available.EncodeBinary(bw)
|
||||
bw.WriteB(byte(a.Precision))
|
||||
bw.WriteB(byte(a.FeeMode))
|
||||
bw.WriteBytes(a.FeeAddress[:])
|
||||
a.FeeAddress.EncodeBinary(bw)
|
||||
|
||||
a.Owner.EncodeBinary(bw)
|
||||
|
||||
bw.WriteBytes(a.Admin[:])
|
||||
bw.WriteBytes(a.Issuer[:])
|
||||
a.Admin.EncodeBinary(bw)
|
||||
a.Issuer.EncodeBinary(bw)
|
||||
bw.WriteU32LE(a.Expiration)
|
||||
bw.WriteBool(a.IsFrozen)
|
||||
}
|
||||
|
|
|
@ -28,13 +28,13 @@ type AppExecResult struct {
|
|||
|
||||
// EncodeBinary implements the Serializable interface.
|
||||
func (ne *NotificationEvent) EncodeBinary(w *io.BinWriter) {
|
||||
w.WriteBytes(ne.ScriptHash[:])
|
||||
ne.ScriptHash.EncodeBinary(w)
|
||||
vm.EncodeBinaryStackItem(ne.Item, w)
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Serializable interface.
|
||||
func (ne *NotificationEvent) DecodeBinary(r *io.BinReader) {
|
||||
r.ReadBytes(ne.ScriptHash[:])
|
||||
ne.ScriptHash.DecodeBinary(r)
|
||||
ne.Item = vm.DecodeBinaryStackItem(r)
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ const (
|
|||
ContractHash AttrUsage = 0x00
|
||||
ECDH02 AttrUsage = 0x02
|
||||
ECDH03 AttrUsage = 0x03
|
||||
Script AttrUsage = 0x20
|
||||
Vote AttrUsage = 0x30
|
||||
CertURL AttrUsage = 0x80
|
||||
DescriptionURL AttrUsage = 0x81
|
||||
|
|
|
@ -31,8 +31,6 @@ func (attr *Attribute) DecodeBinary(br *io.BinReader) {
|
|||
Hash6, Hash7, Hash8, Hash9, Hash10, Hash11, Hash12, Hash13,
|
||||
Hash14, Hash15:
|
||||
datasize = 32
|
||||
case Script:
|
||||
datasize = 20
|
||||
case DescriptionURL:
|
||||
// It's not VarUint as per C# implementation, dunno why
|
||||
var urllen = br.ReadB()
|
||||
|
@ -62,7 +60,7 @@ func (attr *Attribute) EncodeBinary(bw *io.BinWriter) {
|
|||
case DescriptionURL:
|
||||
bw.WriteB(byte(len(attr.Data)))
|
||||
fallthrough
|
||||
case Script, ContractHash, Vote, Hash1, Hash2, Hash3, Hash4, Hash5, Hash6,
|
||||
case ContractHash, Vote, Hash1, Hash2, Hash3, Hash4, Hash5, Hash6,
|
||||
Hash7, Hash8, Hash9, Hash10, Hash11, Hash12, Hash13, Hash14, Hash15:
|
||||
bw.WriteBytes(attr.Data)
|
||||
default:
|
||||
|
|
|
@ -11,7 +11,6 @@ func _() {
|
|||
_ = x[ContractHash-0]
|
||||
_ = x[ECDH02-2]
|
||||
_ = x[ECDH03-3]
|
||||
_ = x[Script-32]
|
||||
_ = x[Vote-48]
|
||||
_ = x[CertURL-128]
|
||||
_ = x[DescriptionURL-129]
|
||||
|
@ -52,19 +51,18 @@ func _() {
|
|||
const (
|
||||
_AttrUsage_name_0 = "ContractHash"
|
||||
_AttrUsage_name_1 = "ECDH02ECDH03"
|
||||
_AttrUsage_name_2 = "Script"
|
||||
_AttrUsage_name_3 = "Vote"
|
||||
_AttrUsage_name_4 = "CertURLDescriptionURL"
|
||||
_AttrUsage_name_5 = "Description"
|
||||
_AttrUsage_name_6 = "Hash1Hash2Hash3Hash4Hash5Hash6Hash7Hash8Hash9Hash10Hash11Hash12Hash13Hash14Hash15"
|
||||
_AttrUsage_name_7 = "RemarkRemark1Remark2Remark3Remark4Remark5Remark6Remark7Remark8Remark9Remark10Remark11Remark12Remark13Remark14Remark15"
|
||||
_AttrUsage_name_2 = "Vote"
|
||||
_AttrUsage_name_3 = "CertURLDescriptionURL"
|
||||
_AttrUsage_name_4 = "Description"
|
||||
_AttrUsage_name_5 = "Hash1Hash2Hash3Hash4Hash5Hash6Hash7Hash8Hash9Hash10Hash11Hash12Hash13Hash14Hash15"
|
||||
_AttrUsage_name_6 = "RemarkRemark1Remark2Remark3Remark4Remark5Remark6Remark7Remark8Remark9Remark10Remark11Remark12Remark13Remark14Remark15"
|
||||
)
|
||||
|
||||
var (
|
||||
_AttrUsage_index_1 = [...]uint8{0, 6, 12}
|
||||
_AttrUsage_index_4 = [...]uint8{0, 7, 21}
|
||||
_AttrUsage_index_6 = [...]uint8{0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 51, 57, 63, 69, 75, 81}
|
||||
_AttrUsage_index_7 = [...]uint8{0, 6, 13, 20, 27, 34, 41, 48, 55, 62, 69, 77, 85, 93, 101, 109, 117}
|
||||
_AttrUsage_index_3 = [...]uint8{0, 7, 21}
|
||||
_AttrUsage_index_5 = [...]uint8{0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 51, 57, 63, 69, 75, 81}
|
||||
_AttrUsage_index_6 = [...]uint8{0, 6, 13, 20, 27, 34, 41, 48, 55, 62, 69, 77, 85, 93, 101, 109, 117}
|
||||
)
|
||||
|
||||
func (i AttrUsage) String() string {
|
||||
|
@ -74,21 +72,19 @@ func (i AttrUsage) String() string {
|
|||
case 2 <= i && i <= 3:
|
||||
i -= 2
|
||||
return _AttrUsage_name_1[_AttrUsage_index_1[i]:_AttrUsage_index_1[i+1]]
|
||||
case i == 32:
|
||||
return _AttrUsage_name_2
|
||||
case i == 48:
|
||||
return _AttrUsage_name_3
|
||||
return _AttrUsage_name_2
|
||||
case 128 <= i && i <= 129:
|
||||
i -= 128
|
||||
return _AttrUsage_name_4[_AttrUsage_index_4[i]:_AttrUsage_index_4[i+1]]
|
||||
return _AttrUsage_name_3[_AttrUsage_index_3[i]:_AttrUsage_index_3[i+1]]
|
||||
case i == 144:
|
||||
return _AttrUsage_name_5
|
||||
return _AttrUsage_name_4
|
||||
case 161 <= i && i <= 175:
|
||||
i -= 161
|
||||
return _AttrUsage_name_6[_AttrUsage_index_6[i]:_AttrUsage_index_6[i+1]]
|
||||
return _AttrUsage_name_5[_AttrUsage_index_5[i]:_AttrUsage_index_5[i+1]]
|
||||
case 240 <= i && i <= 255:
|
||||
i -= 240
|
||||
return _AttrUsage_name_7[_AttrUsage_index_7[i]:_AttrUsage_index_7[i+1]]
|
||||
return _AttrUsage_name_6[_AttrUsage_index_6[i]:_AttrUsage_index_6[i+1]]
|
||||
default:
|
||||
return "AttrUsage(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ func NewClaimTX(claim *ClaimTX) *Transaction {
|
|||
Nonce: rand.Uint32(),
|
||||
Data: claim,
|
||||
Attributes: []Attribute{},
|
||||
Cosigners: []Cosigner{},
|
||||
Inputs: []Input{},
|
||||
Outputs: []Output{},
|
||||
Scripts: []Witness{},
|
||||
|
|
|
@ -18,6 +18,7 @@ func NewContractTX() *Transaction {
|
|||
Nonce: rand.Uint32(),
|
||||
Data: &ContractTX{},
|
||||
Attributes: []Attribute{},
|
||||
Cosigners: []Cosigner{},
|
||||
Inputs: []Input{},
|
||||
Outputs: []Output{},
|
||||
Scripts: []Witness{},
|
||||
|
|
42
pkg/core/transaction/cosigner.go
Normal file
42
pkg/core/transaction/cosigner.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
// The maximum number of AllowedContracts or AllowedGroups
|
||||
const maxSubitems = 16
|
||||
|
||||
// Cosigner implements a Transaction cosigner.
|
||||
type Cosigner struct {
|
||||
Account util.Uint160 `json:"account"`
|
||||
Scopes WitnessScope `json:"scopes"`
|
||||
AllowedContracts []util.Uint160 `json:"allowedContracts,omitempty"`
|
||||
AllowedGroups []*keys.PublicKey `json:"allowedGroups,omitempty"`
|
||||
}
|
||||
|
||||
// EncodeBinary implements Serializable interface.
|
||||
func (c *Cosigner) EncodeBinary(bw *io.BinWriter) {
|
||||
bw.WriteBytes(c.Account[:])
|
||||
bw.WriteB(byte(c.Scopes))
|
||||
if c.Scopes&CustomContracts != 0 {
|
||||
bw.WriteArray(c.AllowedContracts)
|
||||
}
|
||||
if c.Scopes&CustomGroups != 0 {
|
||||
bw.WriteArray(c.AllowedGroups)
|
||||
}
|
||||
}
|
||||
|
||||
// DecodeBinary implements Serializable interface.
|
||||
func (c *Cosigner) DecodeBinary(br *io.BinReader) {
|
||||
br.ReadBytes(c.Account[:])
|
||||
c.Scopes = WitnessScope(br.ReadB())
|
||||
if c.Scopes&CustomContracts != 0 {
|
||||
br.ReadArray(&c.AllowedContracts, maxSubitems)
|
||||
}
|
||||
if c.Scopes&CustomGroups != 0 {
|
||||
br.ReadArray(&c.AllowedGroups, maxSubitems)
|
||||
}
|
||||
}
|
28
pkg/core/transaction/cosigner_test.go
Normal file
28
pkg/core/transaction/cosigner_test.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/internal/testserdes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
func TestCosignerEncodeDecode(t *testing.T) {
|
||||
expected := &Cosigner{
|
||||
Account: util.Uint160{1, 2, 3, 4, 5},
|
||||
Scopes: CustomContracts,
|
||||
AllowedContracts: []util.Uint160{{1, 2, 3, 4}, {6, 7, 8, 9}},
|
||||
}
|
||||
actual := &Cosigner{}
|
||||
testserdes.EncodeDecodeBinary(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestCosignerMarshallUnmarshallJSON(t *testing.T) {
|
||||
expected := &Cosigner{
|
||||
Account: util.Uint160{1, 2, 3, 4, 5},
|
||||
Scopes: CustomContracts,
|
||||
AllowedContracts: []util.Uint160{{1, 2, 3, 4}, {6, 7, 8, 9}},
|
||||
}
|
||||
actual := &Cosigner{}
|
||||
testserdes.MarshalUnmarshalJSON(t, expected, actual)
|
||||
}
|
|
@ -31,6 +31,7 @@ func NewInvocationTX(script []byte, gas util.Fixed8) *Transaction {
|
|||
Version: 1,
|
||||
},
|
||||
Attributes: []Attribute{},
|
||||
Cosigners: []Cosigner{},
|
||||
Inputs: []Input{},
|
||||
Outputs: []Output{},
|
||||
Scripts: []Witness{},
|
||||
|
|
|
@ -18,6 +18,7 @@ func NewIssueTX() *Transaction {
|
|||
Nonce: rand.Uint32(),
|
||||
Data: &IssueTX{},
|
||||
Attributes: []Attribute{},
|
||||
Cosigners: []Cosigner{},
|
||||
Inputs: []Input{},
|
||||
Outputs: []Output{},
|
||||
Scripts: []Witness{},
|
||||
|
|
|
@ -39,6 +39,7 @@ func NewRegisterTX(register *RegisterTX) *Transaction {
|
|||
Nonce: rand.Uint32(),
|
||||
Data: register,
|
||||
Attributes: []Attribute{},
|
||||
Cosigners: []Cosigner{},
|
||||
Inputs: []Input{},
|
||||
Outputs: []Output{},
|
||||
Scripts: []Witness{},
|
||||
|
@ -57,7 +58,7 @@ func (tx *RegisterTX) DecodeBinary(br *io.BinReader) {
|
|||
|
||||
tx.Owner.DecodeBinary(br)
|
||||
|
||||
br.ReadBytes(tx.Admin[:])
|
||||
tx.Admin.DecodeBinary(br)
|
||||
}
|
||||
|
||||
// EncodeBinary implements Serializable interface.
|
||||
|
@ -67,7 +68,7 @@ func (tx *RegisterTX) EncodeBinary(bw *io.BinWriter) {
|
|||
tx.Amount.EncodeBinary(bw)
|
||||
bw.WriteB(byte(tx.Precision))
|
||||
bw.WriteBytes(tx.Owner.Bytes())
|
||||
bw.WriteBytes(tx.Admin[:])
|
||||
tx.Admin.EncodeBinary(bw)
|
||||
}
|
||||
|
||||
// registeredAsset is a wrapper for RegisterTransaction
|
||||
|
|
|
@ -19,6 +19,9 @@ const (
|
|||
// MaxValidUntilBlockIncrement is the upper increment size of blockhain height in blocs after
|
||||
// exceeding that a transaction should fail validation. It is set to be 2102400.
|
||||
MaxValidUntilBlockIncrement = 2102400
|
||||
// MaxCosigners is maximum number of cosigners that can be contained within a transaction.
|
||||
// It is set to be 16.
|
||||
MaxCosigners = 16
|
||||
)
|
||||
|
||||
// Transaction is a process recorded in the NEO blockchain.
|
||||
|
@ -46,6 +49,9 @@ type Transaction struct {
|
|||
// Transaction attributes.
|
||||
Attributes []Attribute
|
||||
|
||||
// Transaction cosigners (not include Sender).
|
||||
Cosigners []Cosigner
|
||||
|
||||
// The inputs of the transaction.
|
||||
Inputs []Input
|
||||
|
||||
|
@ -107,25 +113,28 @@ func (t *Transaction) AddInput(in *Input) {
|
|||
t.Inputs = append(t.Inputs, *in)
|
||||
}
|
||||
|
||||
// AddVerificationHash adds a script attribute for transaction verification.
|
||||
func (t *Transaction) AddVerificationHash(addr util.Uint160) {
|
||||
t.Attributes = append(t.Attributes, Attribute{
|
||||
Usage: Script,
|
||||
Data: addr.BytesBE(),
|
||||
})
|
||||
}
|
||||
|
||||
// DecodeBinary implements Serializable interface.
|
||||
func (t *Transaction) DecodeBinary(br *io.BinReader) {
|
||||
t.Type = TXType(br.ReadB())
|
||||
t.Version = uint8(br.ReadB())
|
||||
t.Nonce = br.ReadU32LE()
|
||||
br.ReadBytes(t.Sender[:])
|
||||
t.Sender.DecodeBinary(br)
|
||||
|
||||
t.ValidUntilBlock = br.ReadU32LE()
|
||||
t.decodeData(br)
|
||||
|
||||
br.ReadArray(&t.Attributes)
|
||||
|
||||
br.ReadArray(&t.Cosigners, MaxCosigners)
|
||||
for i := 0; i < len(t.Cosigners); i++ {
|
||||
for j := i + 1; j < len(t.Cosigners); j++ {
|
||||
if t.Cosigners[i].Account.Equals(t.Cosigners[j].Account) {
|
||||
br.Err = errors.New("transaction cosigners should be unique")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
br.ReadArray(&t.Inputs)
|
||||
br.ReadArray(&t.Outputs)
|
||||
for i := range t.Outputs {
|
||||
|
@ -182,7 +191,7 @@ func (t *Transaction) encodeHashableFields(bw *io.BinWriter) {
|
|||
bw.WriteB(byte(t.Type))
|
||||
bw.WriteB(byte(t.Version))
|
||||
bw.WriteU32LE(t.Nonce)
|
||||
bw.WriteBytes(t.Sender[:])
|
||||
t.Sender.EncodeBinary(bw)
|
||||
bw.WriteU32LE(t.ValidUntilBlock)
|
||||
|
||||
// Underlying TXer.
|
||||
|
@ -193,6 +202,9 @@ func (t *Transaction) encodeHashableFields(bw *io.BinWriter) {
|
|||
// Attributes
|
||||
bw.WriteArray(t.Attributes)
|
||||
|
||||
// Cosigners
|
||||
bw.WriteArray(t.Cosigners)
|
||||
|
||||
// Inputs
|
||||
bw.WriteArray(t.Inputs)
|
||||
|
||||
|
@ -267,6 +279,7 @@ type transactionJSON struct {
|
|||
Sender string `json:"sender"`
|
||||
ValidUntilBlock uint32 `json:"valid_until_block"`
|
||||
Attributes []Attribute `json:"attributes"`
|
||||
Cosigners []Cosigner `json:"cosigners"`
|
||||
Inputs []Input `json:"vin"`
|
||||
Outputs []Output `json:"vout"`
|
||||
Scripts []Witness `json:"scripts"`
|
||||
|
@ -288,6 +301,7 @@ func (t *Transaction) MarshalJSON() ([]byte, error) {
|
|||
Sender: address.Uint160ToString(t.Sender),
|
||||
ValidUntilBlock: t.ValidUntilBlock,
|
||||
Attributes: t.Attributes,
|
||||
Cosigners: t.Cosigners,
|
||||
Inputs: t.Inputs,
|
||||
Outputs: t.Outputs,
|
||||
Scripts: t.Scripts,
|
||||
|
@ -323,6 +337,7 @@ func (t *Transaction) UnmarshalJSON(data []byte) error {
|
|||
t.Nonce = tx.Nonce
|
||||
t.ValidUntilBlock = tx.ValidUntilBlock
|
||||
t.Attributes = tx.Attributes
|
||||
t.Cosigners = tx.Cosigners
|
||||
t.Inputs = tx.Inputs
|
||||
t.Outputs = tx.Outputs
|
||||
t.Scripts = tx.Scripts
|
||||
|
|
19
pkg/core/transaction/witness_scope.go
Normal file
19
pkg/core/transaction/witness_scope.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
package transaction
|
||||
|
||||
// WitnessScope represents set of witness flags for Transaction cosigner.
|
||||
type WitnessScope byte
|
||||
|
||||
const (
|
||||
// Global allows this witness in all contexts (default Neo2 behavior).
|
||||
// This cannot be combined with other flags.
|
||||
Global WitnessScope = 0x00
|
||||
// CalledByEntry means that this condition must hold: EntryScriptHash == CallingScriptHash.
|
||||
// No params is needed, as the witness/permission/signature given on first invocation will
|
||||
// automatically expire if entering deeper internal invokes. This can be default safe
|
||||
// choice for native NEO/GAS (previously used on Neo 2 as "attach" mode).
|
||||
CalledByEntry WitnessScope = 0x01
|
||||
// CustomContracts define custom hash for contract-specific.
|
||||
CustomContracts WitnessScope = 0x10
|
||||
// CustomGroups define custom pubkey for group members.
|
||||
CustomGroups WitnessScope = 0x20
|
||||
)
|
|
@ -20,7 +20,7 @@ func TestGenesisBlockMainNet(t *testing.T) {
|
|||
// have been changed. Consequently, hash of the genesis block has been changed.
|
||||
// Update expected genesis block hash for better times.
|
||||
// Old hash is "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf"
|
||||
expect := "16ffda4cc6a9b0a0ca63f1571f7724418c43f014e2eb4e8614b4938ccf0f20f6"
|
||||
expect := "8eb36fe47f07a795a1783a9f066603db66c5b76cf878650b1e137c114f46c0cc"
|
||||
assert.Equal(t, expect, block.Hash().StringLE())
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ func TestUtilityTokenTX(t *testing.T) {
|
|||
//TODO: After we added Nonce field to transaction.Transaction, UtilityTockenTx hash
|
||||
// has been changed. Update it for better times.
|
||||
// Old hash is "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
|
||||
expect := "b16384a950ed01ed5fc15c03fe7b98228871cb43b1bc22d67029449fc854d104"
|
||||
expect := "8ef63ccd6f4ea20a93e7f4e84b2d43f778077612b241d617e42e1750cca4f2c5"
|
||||
assert.Equal(t, expect, UtilityTokenID().StringLE())
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,6 @@ func TestGoverningTokenTX(t *testing.T) {
|
|||
//TODO: After we added Nonce field to transaction.Transaction, GoveringTockenTx hash
|
||||
// has been changed. Update it for better times.
|
||||
// Old hash is "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b"
|
||||
expect := "7a37715546c6cfa5bac8d7f7e87c667a1e5a6ba0601238be475ab8c79a5abcf5"
|
||||
expect := "7dc12f8835b085d468ddbab3f7152c0e2f5679b5815b2028685abb4608e7b7dc"
|
||||
assert.Equal(t, expect, GoverningTokenID().StringLE())
|
||||
}
|
||||
|
|
|
@ -108,22 +108,13 @@ func (c *Client) TransferNEP5(acc *wallet.Account, to util.Uint160, token *walle
|
|||
emit.Opcode(w.BinWriter, opcode.THROWIFNOT)
|
||||
|
||||
tx := transaction.NewInvocationTX(w.Bytes(), gas)
|
||||
tx.Attributes = append(tx.Attributes, transaction.Attribute{
|
||||
Usage: transaction.Script,
|
||||
Data: from.BytesBE(),
|
||||
})
|
||||
tx.Sender = from
|
||||
|
||||
tx.ValidUntilBlock, err = c.CalculateValidUntilBlock()
|
||||
if err != nil {
|
||||
return util.Uint256{}, fmt.Errorf("can't calculate validUntilBlock: %v", err)
|
||||
}
|
||||
|
||||
addr, err := address.StringToUint160(acc.Address)
|
||||
if err != nil {
|
||||
return util.Uint256{}, fmt.Errorf("failed to get address: %v", err)
|
||||
}
|
||||
tx.Sender = addr
|
||||
|
||||
if err := request.AddInputsAndUnspentsToTx(tx, acc.Address, core.UtilityTokenID(), gas, c); err != nil {
|
||||
return util.Uint256{}, fmt.Errorf("can't add GAS to transaction: %v", err)
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
invoke: func(c *Client) (interface{}, error) {
|
||||
return c.GetAccountState("")
|
||||
},
|
||||
serverResponse: `{"jsonrpc":"2.0","id": 1,"result":{"version":0,"script_hash":"0x1179716da2e9523d153a35fb3ad10c561b1e5b1a","frozen":false,"votes":[],"balances":[{"asset":"0x7a37715546c6cfa5bac8d7f7e87c667a1e5a6ba0601238be475ab8c79a5abcf5","value":"94"}]}}`,
|
||||
serverResponse: `{"jsonrpc":"2.0","id": 1,"result":{"version":0,"script_hash":"0x1179716da2e9523d153a35fb3ad10c561b1e5b1a","frozen":false,"votes":[],"balances":[{"asset":"0x7dc12f8835b085d468ddbab3f7152c0e2f5679b5815b2028685abb4608e7b7dc","value":"94"}]}}`,
|
||||
result: func(c *Client) interface{} {
|
||||
scriptHash, err := util.Uint160DecodeStringLE("1179716da2e9523d153a35fb3ad10c561b1e5b1a")
|
||||
if err != nil {
|
||||
|
@ -96,7 +96,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
invoke: func(c *Client) (interface{}, error) {
|
||||
return c.GetAssetState(util.Uint256{})
|
||||
},
|
||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":"0x7a37715546c6cfa5bac8d7f7e87c667a1e5a6ba0601238be475ab8c79a5abcf5","type":0,"name":"NEO","amount":"100000000","available":"100000000","precision":0,"owner":"00","admin":"Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt","issuer":"AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM","expiration":4000000,"is_frozen":false}}`,
|
||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":"0x7dc12f8835b085d468ddbab3f7152c0e2f5679b5815b2028685abb4608e7b7dc","type":0,"name":"NEO","amount":"100000000","available":"100000000","precision":0,"owner":"00","admin":"Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt","issuer":"AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM","expiration":4000000,"is_frozen":false}}`,
|
||||
result: func(c *Client) interface{} {
|
||||
return &result.AssetState{
|
||||
ID: core.GoverningTokenID(),
|
||||
|
@ -134,45 +134,45 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
{
|
||||
name: "byIndex_positive",
|
||||
invoke: func(c *Client) (interface{}, error) {
|
||||
return c.GetBlockByIndex(5)
|
||||
return c.GetBlockByIndex(202)
|
||||
},
|
||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"000000005b25cf560918b13cc7a10071cf616426a103d58498171567aaa116af69179aa3c05c359ade4316392d69d5ca01f8860f8bdebbe1a8f752edd68d9a6a2d204fe752cca25e0000000005000000e903736ceceeceae1806eee0e3ec61e7cce476ce01fd08010c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf894130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb020057040000000000008000d5040000e903736ceceeceae1806eee0e3ec61e7cce476ce0500000000000001fd08010c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab794130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"}`,
|
||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"0000000039f06b13aa6ee24d37db9b7868533b7988a6fb1e59c3fa6677dab7fd1f51326405f4fa24f061ffa04ab3127994530ee04c5e578a7b8109133dd142b6a31192cd9debaa5e00000000ca000000e903736ceceeceae1806eee0e3ec61e7cce476ce01fd08010c404617b6788538326383015c44ffddd4a05a4e200b65a26fc84234ae8b1e28ef27b7f139dc498c58071193d530ba83081701290eba8f7108397499f5556c16e3780c402131f2bdcc494c73a379e86c46f9e9fe9899a05b23928926b1eaaf816928e160fe971b82263aa1e7efa5f7e46bf99de735fc4fc5aeb81edfdc6a9b2e9fcfa1000c408cbae1582bb9d82de9ff030b8c729737f2157844c0ca29edcdbfed1dd5e2473e0061f0dc29412477417e2c1f7c55443f11b9bd6e0d0856d1ec00240be1b9b9a70c4034d1055531cf0522ac7e5dcd817cf3cd86997ae38da806dc789b1f16eb0005f00b9bc29f7372bb43a8fed040c6763b162c8a0d8e2d0b2d7476e22e0b2b77601094130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb0200570400000000000080000300000075a94799633ed955dd85a8af314a5b435ab51903b0040000000001f6c31d4dd9edf7aea24168885ae82dc574d25e35a9b9b3063f3ea44226a3081f000001dcb7e70846bb5a6828205b81b579562f0e2c15f7b3badd68d485b035882fc17d00184a27db86230075a94799633ed955dd85a8af314a5b435ab5190301420c40bfce1ead7d53339440bb29745eed4ad9840875de4f970950065291e7a14cbd249bfbf777d9a997c5e00bbc08e8ce9fdd2cd13c45c3585b4939599ff84c6149ff290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"}`,
|
||||
result: func(c *Client) interface{} { return &block.Block{} },
|
||||
check: func(t *testing.T, c *Client, result interface{}) {
|
||||
res, ok := result.(*block.Block)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, uint32(0), res.Version)
|
||||
assert.Equal(t, "81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb", res.Hash().StringLE())
|
||||
assert.Equal(t, "a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b", res.PrevHash.StringLE())
|
||||
assert.Equal(t, "e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0", res.MerkleRoot.StringLE())
|
||||
assert.Equal(t, "75ab743487ce969792a4cb3c235d9ea5ff97af42b2646183c981437a077fbc45", res.Hash().StringLE())
|
||||
assert.Equal(t, "6432511ffdb7da7766fac3591efba688793b5368789bdb374de26eaa136bf039", res.PrevHash.StringLE())
|
||||
assert.Equal(t, "cd9211a3b642d13d1309817b8a575e4ce00e53947912b34aa0ff61f024faf405", res.MerkleRoot.StringLE())
|
||||
assert.Equal(t, 1, len(res.Transactions))
|
||||
assert.Equal(t, "69d95138263dc54c07826ef1d76f9eb32ff6bf7fc3fc3281194b46ec7683ceb3", res.Transactions[0].Hash().StringLE())
|
||||
assert.Equal(t, "115975f7d1e9c4577ec839c6ea4ae32727616284e2d7cdc5a49e4e421b32e505", res.Transactions[0].Hash().StringLE())
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "byIndex_verbose_positive",
|
||||
invoke: func(c *Client) (i interface{}, err error) {
|
||||
return c.GetBlockByIndexVerbose(5)
|
||||
return c.GetBlockByIndexVerbose(202)
|
||||
},
|
||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0x81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb","size":977,"version":0,"nextblockhash":"0xd08e408909ae24de3470a3f231f966e15719910cb7b1a30f356b3e784c1ddf6a","previousblockhash":"0xa39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b","merkleroot":"0xe74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0","time":1587727442,"index":5,"consensus_data":{"primary":0,"nonce":"0000000000000457"},"nextconsensus":"Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy","confirmations":203,"script":{"invocation":"0c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf8","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"},"tx":[{"sys_fee":"0","net_fee":"0","txid":"0x69d95138263dc54c07826ef1d76f9eb32ff6bf7fc3fc3281194b46ec7683ceb3","size":450,"type":"ContractTransaction","version":0,"nonce":1237,"sender":"Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy","valid_until_block":5,"attributes":[],"vin":[],"vout":[],"scripts":[{"invocation":"0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"}]}]}}`,
|
||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0x75ab743487ce969792a4cb3c235d9ea5ff97af42b2646183c981437a077fbc45","size":765,"version":0,"nextblockhash":"0xec27fed4ff8ad6a87bdd29aecee43e9ecb4e336321dac875d0b14d2aab1c5798","previousblockhash":"0x6432511ffdb7da7766fac3591efba688793b5368789bdb374de26eaa136bf039","merkleroot":"0xcd9211a3b642d13d1309817b8a575e4ce00e53947912b34aa0ff61f024faf405","time":1588259741,"index":202,"consensus_data":{"primary":0,"nonce":"0000000000000457"},"nextconsensus":"Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy","confirmations":6,"script":{"invocation":"0c404617b6788538326383015c44ffddd4a05a4e200b65a26fc84234ae8b1e28ef27b7f139dc498c58071193d530ba83081701290eba8f7108397499f5556c16e3780c402131f2bdcc494c73a379e86c46f9e9fe9899a05b23928926b1eaaf816928e160fe971b82263aa1e7efa5f7e46bf99de735fc4fc5aeb81edfdc6a9b2e9fcfa1000c408cbae1582bb9d82de9ff030b8c729737f2157844c0ca29edcdbfed1dd5e2473e0061f0dc29412477417e2c1f7c55443f11b9bd6e0d0856d1ec00240be1b9b9a70c4034d1055531cf0522ac7e5dcd817cf3cd86997ae38da806dc789b1f16eb0005f00b9bc29f7372bb43a8fed040c6763b162c8a0d8e2d0b2d7476e22e0b2b776010","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"},"tx":[{"sys_fee":"0","net_fee":"0","txid":"0x115975f7d1e9c4577ec839c6ea4ae32727616284e2d7cdc5a49e4e421b32e505","size":238,"type":"ContractTransaction","version":0,"nonce":3,"sender":"ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR","valid_until_block":1200,"attributes":[],"cosigners":[],"vin":[{"txid":"0x1f08a32642a43e3f06b3b9a9355ed274c52de85a886841a2aef7edd94d1dc3f6","vout":0}],"vout":[{"address":"ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR","asset":"0x7dc12f8835b085d468ddbab3f7152c0e2f5679b5815b2028685abb4608e7b7dc","n":0,"value":"99999000"}],"scripts":[{"invocation":"0c40bfce1ead7d53339440bb29745eed4ad9840875de4f970950065291e7a14cbd249bfbf777d9a997c5e00bbc08e8ce9fdd2cd13c45c3585b4939599ff84c6149ff","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"}]}]}}`,
|
||||
result: func(c *Client) interface{} {
|
||||
hash, err := util.Uint256DecodeStringLE("81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb")
|
||||
hash, err := util.Uint256DecodeStringLE("75ab743487ce969792a4cb3c235d9ea5ff97af42b2646183c981437a077fbc45")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
nextBlockHash, err := util.Uint256DecodeStringLE("d08e408909ae24de3470a3f231f966e15719910cb7b1a30f356b3e784c1ddf6a")
|
||||
nextBlockHash, err := util.Uint256DecodeStringLE("ec27fed4ff8ad6a87bdd29aecee43e9ecb4e336321dac875d0b14d2aab1c5798")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
prevBlockHash, err := util.Uint256DecodeStringLE("a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b")
|
||||
prevBlockHash, err := util.Uint256DecodeStringLE("6432511ffdb7da7766fac3591efba688793b5368789bdb374de26eaa136bf039")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
merkleRoot, err := util.Uint256DecodeStringLE("e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0")
|
||||
merkleRoot, err := util.Uint256DecodeStringLE("cd9211a3b642d13d1309817b8a575e4ce00e53947912b34aa0ff61f024faf405")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
invScript, err := hex.DecodeString("0c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf8")
|
||||
invScript, err := hex.DecodeString("0c404617b6788538326383015c44ffddd4a05a4e200b65a26fc84234ae8b1e28ef27b7f139dc498c58071193d530ba83081701290eba8f7108397499f5556c16e3780c402131f2bdcc494c73a379e86c46f9e9fe9899a05b23928926b1eaaf816928e160fe971b82263aa1e7efa5f7e46bf99de735fc4fc5aeb81edfdc6a9b2e9fcfa1000c408cbae1582bb9d82de9ff030b8c729737f2157844c0ca29edcdbfed1dd5e2473e0061f0dc29412477417e2c1f7c55443f11b9bd6e0d0856d1ec00240be1b9b9a70c4034d1055531cf0522ac7e5dcd817cf3cd86997ae38da806dc789b1f16eb0005f00b9bc29f7372bb43a8fed040c6763b162c8a0d8e2d0b2d7476e22e0b2b776010")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -180,21 +180,29 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sender, err := address.StringToUint160("Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy")
|
||||
sender, err := address.StringToUint160("ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
txInvScript, err := hex.DecodeString("0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7")
|
||||
txInvScript, err := hex.DecodeString("0c40bfce1ead7d53339440bb29745eed4ad9840875de4f970950065291e7a14cbd249bfbf777d9a997c5e00bbc08e8ce9fdd2cd13c45c3585b4939599ff84c6149ff")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
txVerifScript, err := hex.DecodeString("130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb")
|
||||
txVerifScript, err := hex.DecodeString("0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
vin, err := util.Uint256DecodeStringLE("1f08a32642a43e3f06b3b9a9355ed274c52de85a886841a2aef7edd94d1dc3f6")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
outAddress, err := address.StringToUint160("ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tx := transaction.NewContractTX()
|
||||
tx.Nonce = 1237
|
||||
tx.ValidUntilBlock = 5
|
||||
tx.Nonce = 3
|
||||
tx.ValidUntilBlock = 1200
|
||||
tx.Sender = sender
|
||||
tx.Scripts = []transaction.Witness{
|
||||
{
|
||||
|
@ -202,19 +210,34 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
VerificationScript: txVerifScript,
|
||||
},
|
||||
}
|
||||
tx.Inputs = []transaction.Input{
|
||||
{
|
||||
PrevHash: vin,
|
||||
PrevIndex: 0,
|
||||
},
|
||||
}
|
||||
tx.Outputs = []transaction.Output{
|
||||
{
|
||||
AssetID: core.GoverningTokenID(),
|
||||
Amount: util.Fixed8FromInt64(99999000),
|
||||
ScriptHash: outAddress,
|
||||
Position: 0,
|
||||
},
|
||||
}
|
||||
|
||||
// Update hashes for correct result comparison.
|
||||
_ = tx.Hash()
|
||||
return &result.Block{
|
||||
Hash: hash,
|
||||
Size: 977,
|
||||
Size: 765,
|
||||
Version: 0,
|
||||
NextBlockHash: &nextBlockHash,
|
||||
PreviousBlockHash: prevBlockHash,
|
||||
MerkleRoot: merkleRoot,
|
||||
Time: 1587727442,
|
||||
Index: 5,
|
||||
Time: 1588259741,
|
||||
Index: 202,
|
||||
NextConsensus: "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
|
||||
Confirmations: 203,
|
||||
Confirmations: 6,
|
||||
ConsensusData: result.ConsensusData{
|
||||
PrimaryIndex: 0,
|
||||
Nonce: "0000000000000457",
|
||||
|
@ -236,53 +259,53 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
{
|
||||
name: "byHash_positive",
|
||||
invoke: func(c *Client) (interface{}, error) {
|
||||
hash, err := util.Uint256DecodeStringLE("e9f71b58764157f1e2c3e29f217e654b57956ee7c8a60496b03ea85e39084b42")
|
||||
hash, err := util.Uint256DecodeStringLE("45bc7f077a4381c9836164b242af97ffa59e5d233ccba4929796ce873474ab75")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c.GetBlockByHash(hash)
|
||||
},
|
||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"000000005b25cf560918b13cc7a10071cf616426a103d58498171567aaa116af69179aa3c05c359ade4316392d69d5ca01f8860f8bdebbe1a8f752edd68d9a6a2d204fe752cca25e0000000005000000e903736ceceeceae1806eee0e3ec61e7cce476ce01fd08010c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf894130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb020057040000000000008000d5040000e903736ceceeceae1806eee0e3ec61e7cce476ce0500000000000001fd08010c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab794130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"}`,
|
||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"0000000039f06b13aa6ee24d37db9b7868533b7988a6fb1e59c3fa6677dab7fd1f51326405f4fa24f061ffa04ab3127994530ee04c5e578a7b8109133dd142b6a31192cd9debaa5e00000000ca000000e903736ceceeceae1806eee0e3ec61e7cce476ce01fd08010c404617b6788538326383015c44ffddd4a05a4e200b65a26fc84234ae8b1e28ef27b7f139dc498c58071193d530ba83081701290eba8f7108397499f5556c16e3780c402131f2bdcc494c73a379e86c46f9e9fe9899a05b23928926b1eaaf816928e160fe971b82263aa1e7efa5f7e46bf99de735fc4fc5aeb81edfdc6a9b2e9fcfa1000c408cbae1582bb9d82de9ff030b8c729737f2157844c0ca29edcdbfed1dd5e2473e0061f0dc29412477417e2c1f7c55443f11b9bd6e0d0856d1ec00240be1b9b9a70c4034d1055531cf0522ac7e5dcd817cf3cd86997ae38da806dc789b1f16eb0005f00b9bc29f7372bb43a8fed040c6763b162c8a0d8e2d0b2d7476e22e0b2b77601094130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb0200570400000000000080000300000075a94799633ed955dd85a8af314a5b435ab51903b0040000000001f6c31d4dd9edf7aea24168885ae82dc574d25e35a9b9b3063f3ea44226a3081f000001dcb7e70846bb5a6828205b81b579562f0e2c15f7b3badd68d485b035882fc17d00184a27db86230075a94799633ed955dd85a8af314a5b435ab5190301420c40bfce1ead7d53339440bb29745eed4ad9840875de4f970950065291e7a14cbd249bfbf777d9a997c5e00bbc08e8ce9fdd2cd13c45c3585b4939599ff84c6149ff290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"}`,
|
||||
result: func(c *Client) interface{} { return &block.Block{} },
|
||||
check: func(t *testing.T, c *Client, result interface{}) {
|
||||
res, ok := result.(*block.Block)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, uint32(0), res.Version)
|
||||
assert.Equal(t, "81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb", res.Hash().StringLE())
|
||||
assert.Equal(t, "a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b", res.PrevHash.StringLE())
|
||||
assert.Equal(t, "e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0", res.MerkleRoot.StringLE())
|
||||
assert.Equal(t, "75ab743487ce969792a4cb3c235d9ea5ff97af42b2646183c981437a077fbc45", res.Hash().StringLE())
|
||||
assert.Equal(t, "6432511ffdb7da7766fac3591efba688793b5368789bdb374de26eaa136bf039", res.PrevHash.StringLE())
|
||||
assert.Equal(t, "cd9211a3b642d13d1309817b8a575e4ce00e53947912b34aa0ff61f024faf405", res.MerkleRoot.StringLE())
|
||||
assert.Equal(t, 1, len(res.Transactions))
|
||||
assert.Equal(t, "69d95138263dc54c07826ef1d76f9eb32ff6bf7fc3fc3281194b46ec7683ceb3", res.Transactions[0].Hash().StringLE())
|
||||
assert.Equal(t, "115975f7d1e9c4577ec839c6ea4ae32727616284e2d7cdc5a49e4e421b32e505", res.Transactions[0].Hash().StringLE())
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "byHash_verbose_positive",
|
||||
invoke: func(c *Client) (i interface{}, err error) {
|
||||
hash, err := util.Uint256DecodeStringLE("bb09d40563c7141215b024b0959aec00a3ab316248c2ee31f32ea4c3cf4db781")
|
||||
hash, err := util.Uint256DecodeStringLE("45bc7f077a4381c9836164b242af97ffa59e5d233ccba4929796ce873474ab75")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c.GetBlockByHashVerbose(hash)
|
||||
},
|
||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0x81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb","size":977,"version":0,"nextblockhash":"0xd08e408909ae24de3470a3f231f966e15719910cb7b1a30f356b3e784c1ddf6a","previousblockhash":"0xa39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b","merkleroot":"0xe74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0","time":1587727442,"index":5,"consensus_data":{"primary":0,"nonce":"0000000000000457"},"nextconsensus":"Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy","confirmations":203,"script":{"invocation":"0c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf8","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"},"tx":[{"sys_fee":"0","net_fee":"0","txid":"0x69d95138263dc54c07826ef1d76f9eb32ff6bf7fc3fc3281194b46ec7683ceb3","size":450,"type":"ContractTransaction","version":0,"nonce":1237,"sender":"Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy","valid_until_block":5,"attributes":[],"vin":[],"vout":[],"scripts":[{"invocation":"0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"}]}]}}`,
|
||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0x75ab743487ce969792a4cb3c235d9ea5ff97af42b2646183c981437a077fbc45","size":765,"version":0,"nextblockhash":"0xec27fed4ff8ad6a87bdd29aecee43e9ecb4e336321dac875d0b14d2aab1c5798","previousblockhash":"0x6432511ffdb7da7766fac3591efba688793b5368789bdb374de26eaa136bf039","merkleroot":"0xcd9211a3b642d13d1309817b8a575e4ce00e53947912b34aa0ff61f024faf405","time":1588259741,"index":202,"consensus_data":{"primary":0,"nonce":"0000000000000457"},"nextconsensus":"Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy","confirmations":6,"script":{"invocation":"0c404617b6788538326383015c44ffddd4a05a4e200b65a26fc84234ae8b1e28ef27b7f139dc498c58071193d530ba83081701290eba8f7108397499f5556c16e3780c402131f2bdcc494c73a379e86c46f9e9fe9899a05b23928926b1eaaf816928e160fe971b82263aa1e7efa5f7e46bf99de735fc4fc5aeb81edfdc6a9b2e9fcfa1000c408cbae1582bb9d82de9ff030b8c729737f2157844c0ca29edcdbfed1dd5e2473e0061f0dc29412477417e2c1f7c55443f11b9bd6e0d0856d1ec00240be1b9b9a70c4034d1055531cf0522ac7e5dcd817cf3cd86997ae38da806dc789b1f16eb0005f00b9bc29f7372bb43a8fed040c6763b162c8a0d8e2d0b2d7476e22e0b2b776010","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"},"tx":[{"sys_fee":"0","net_fee":"0","txid":"0x115975f7d1e9c4577ec839c6ea4ae32727616284e2d7cdc5a49e4e421b32e505","size":238,"type":"ContractTransaction","version":0,"nonce":3,"sender":"ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR","valid_until_block":1200,"attributes":[],"cosigners":[],"vin":[{"txid":"0x1f08a32642a43e3f06b3b9a9355ed274c52de85a886841a2aef7edd94d1dc3f6","vout":0}],"vout":[{"address":"ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR","asset":"0x7dc12f8835b085d468ddbab3f7152c0e2f5679b5815b2028685abb4608e7b7dc","n":0,"value":"99999000"}],"scripts":[{"invocation":"0c40bfce1ead7d53339440bb29745eed4ad9840875de4f970950065291e7a14cbd249bfbf777d9a997c5e00bbc08e8ce9fdd2cd13c45c3585b4939599ff84c6149ff","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"}]}]}}`,
|
||||
result: func(c *Client) interface{} {
|
||||
hash, err := util.Uint256DecodeStringLE("81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb")
|
||||
hash, err := util.Uint256DecodeStringLE("75ab743487ce969792a4cb3c235d9ea5ff97af42b2646183c981437a077fbc45")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
nextBlockHash, err := util.Uint256DecodeStringLE("d08e408909ae24de3470a3f231f966e15719910cb7b1a30f356b3e784c1ddf6a")
|
||||
nextBlockHash, err := util.Uint256DecodeStringLE("ec27fed4ff8ad6a87bdd29aecee43e9ecb4e336321dac875d0b14d2aab1c5798")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
prevBlockHash, err := util.Uint256DecodeStringLE("a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b")
|
||||
prevBlockHash, err := util.Uint256DecodeStringLE("6432511ffdb7da7766fac3591efba688793b5368789bdb374de26eaa136bf039")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
merkleRoot, err := util.Uint256DecodeStringLE("e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0")
|
||||
merkleRoot, err := util.Uint256DecodeStringLE("cd9211a3b642d13d1309817b8a575e4ce00e53947912b34aa0ff61f024faf405")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
invScript, err := hex.DecodeString("0c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf8")
|
||||
invScript, err := hex.DecodeString("0c404617b6788538326383015c44ffddd4a05a4e200b65a26fc84234ae8b1e28ef27b7f139dc498c58071193d530ba83081701290eba8f7108397499f5556c16e3780c402131f2bdcc494c73a379e86c46f9e9fe9899a05b23928926b1eaaf816928e160fe971b82263aa1e7efa5f7e46bf99de735fc4fc5aeb81edfdc6a9b2e9fcfa1000c408cbae1582bb9d82de9ff030b8c729737f2157844c0ca29edcdbfed1dd5e2473e0061f0dc29412477417e2c1f7c55443f11b9bd6e0d0856d1ec00240be1b9b9a70c4034d1055531cf0522ac7e5dcd817cf3cd86997ae38da806dc789b1f16eb0005f00b9bc29f7372bb43a8fed040c6763b162c8a0d8e2d0b2d7476e22e0b2b776010")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -290,21 +313,29 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sender, err := address.StringToUint160("Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy")
|
||||
sender, err := address.StringToUint160("ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
txInvScript, err := hex.DecodeString("0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7")
|
||||
txInvScript, err := hex.DecodeString("0c40bfce1ead7d53339440bb29745eed4ad9840875de4f970950065291e7a14cbd249bfbf777d9a997c5e00bbc08e8ce9fdd2cd13c45c3585b4939599ff84c6149ff")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
txVerifScript, err := hex.DecodeString("130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb")
|
||||
txVerifScript, err := hex.DecodeString("0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
vin, err := util.Uint256DecodeStringLE("1f08a32642a43e3f06b3b9a9355ed274c52de85a886841a2aef7edd94d1dc3f6")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
outAddress, err := address.StringToUint160("ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tx := transaction.NewContractTX()
|
||||
tx.Nonce = 1237
|
||||
tx.ValidUntilBlock = 5
|
||||
tx.Nonce = 3
|
||||
tx.ValidUntilBlock = 1200
|
||||
tx.Sender = sender
|
||||
tx.Scripts = []transaction.Witness{
|
||||
{
|
||||
|
@ -312,19 +343,34 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
VerificationScript: txVerifScript,
|
||||
},
|
||||
}
|
||||
tx.Inputs = []transaction.Input{
|
||||
{
|
||||
PrevHash: vin,
|
||||
PrevIndex: 0,
|
||||
},
|
||||
}
|
||||
tx.Outputs = []transaction.Output{
|
||||
{
|
||||
AssetID: core.GoverningTokenID(),
|
||||
Amount: util.Fixed8FromInt64(99999000),
|
||||
ScriptHash: outAddress,
|
||||
Position: 0,
|
||||
},
|
||||
}
|
||||
|
||||
// Update hashes for correct result comparison.
|
||||
_ = tx.Hash()
|
||||
return &result.Block{
|
||||
Hash: hash,
|
||||
Size: 977,
|
||||
Size: 765,
|
||||
Version: 0,
|
||||
NextBlockHash: &nextBlockHash,
|
||||
PreviousBlockHash: prevBlockHash,
|
||||
MerkleRoot: merkleRoot,
|
||||
Time: 1587727442,
|
||||
Index: 5,
|
||||
Time: 1588259741,
|
||||
Index: 202,
|
||||
NextConsensus: "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
|
||||
Confirmations: 203,
|
||||
Confirmations: 6,
|
||||
ConsensusData: result.ConsensusData{
|
||||
PrimaryIndex: 0,
|
||||
Nonce: "0000000000000457",
|
||||
|
@ -653,19 +699,19 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
{
|
||||
name: "positive",
|
||||
invoke: func(c *Client) (i interface{}, err error) {
|
||||
hash, err := util.Uint256DecodeStringLE("b3ce8376ec464b198132fcc37fbff62fb39e6fd7f16e82074cc53d263851d969")
|
||||
hash, err := util.Uint256DecodeStringLE("05e5321b424e9ea4c5cdd7e28462612727e34aeac639c87e57c4e9d1f7755911")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c.GetRawTransaction(hash)
|
||||
},
|
||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"8000d5040000e903736ceceeceae1806eee0e3ec61e7cce476ce0500000000000001fd08010c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab794130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"}`,
|
||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"80000300000075a94799633ed955dd85a8af314a5b435ab51903b0040000000001f6c31d4dd9edf7aea24168885ae82dc574d25e35a9b9b3063f3ea44226a3081f000001dcb7e70846bb5a6828205b81b579562f0e2c15f7b3badd68d485b035882fc17d00184a27db86230075a94799633ed955dd85a8af314a5b435ab5190301420c40bfce1ead7d53339440bb29745eed4ad9840875de4f970950065291e7a14cbd249bfbf777d9a997c5e00bbc08e8ce9fdd2cd13c45c3585b4939599ff84c6149ff290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"}`,
|
||||
result: func(c *Client) interface{} { return &transaction.Transaction{} },
|
||||
check: func(t *testing.T, c *Client, result interface{}) {
|
||||
res, ok := result.(*transaction.Transaction)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, uint8(0), res.Version)
|
||||
assert.Equal(t, "b3ce8376ec464b198132fcc37fbff62fb39e6fd7f16e82074cc53d263851d969", res.Hash().StringBE())
|
||||
assert.Equal(t, "05e5321b424e9ea4c5cdd7e28462612727e34aeac639c87e57c4e9d1f7755911", res.Hash().StringBE())
|
||||
assert.Equal(t, transaction.ContractType, res.Type)
|
||||
assert.Equal(t, false, res.Trimmed)
|
||||
},
|
||||
|
@ -673,33 +719,41 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
{
|
||||
name: "verbose_positive",
|
||||
invoke: func(c *Client) (interface{}, error) {
|
||||
hash, err := util.Uint256DecodeStringLE("b3ce8376ec464b198132fcc37fbff62fb39e6fd7f16e82074cc53d263851d969")
|
||||
hash, err := util.Uint256DecodeStringLE("05e5321b424e9ea4c5cdd7e28462612727e34aeac639c87e57c4e9d1f7755911")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c.GetRawTransactionVerbose(hash)
|
||||
},
|
||||
serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"sys_fee":"0","net_fee":"0","blockhash":"0x81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb","confirmations":205,"blocktime":1587727442,"txid":"0x69d95138263dc54c07826ef1d76f9eb32ff6bf7fc3fc3281194b46ec7683ceb3","size":450,"type":"ContractTransaction","version":0,"nonce":1237,"sender":"Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy","valid_until_block":5,"attributes":[],"vin":[],"vout":[],"scripts":[{"invocation":"0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"}]}}`,
|
||||
serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"sys_fee":"0","net_fee":"0","blockhash":"0x75ab743487ce969792a4cb3c235d9ea5ff97af42b2646183c981437a077fbc45","confirmations":8,"blocktime":1588259741,"txid":"0x115975f7d1e9c4577ec839c6ea4ae32727616284e2d7cdc5a49e4e421b32e505","size":238,"type":"ContractTransaction","version":0,"nonce":3,"sender":"ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR","valid_until_block":1200,"attributes":[],"cosigners":[],"vin":[{"txid":"0x1f08a32642a43e3f06b3b9a9355ed274c52de85a886841a2aef7edd94d1dc3f6","vout":0}],"vout":[{"address":"ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR","asset":"0x7dc12f8835b085d468ddbab3f7152c0e2f5679b5815b2028685abb4608e7b7dc","n":0,"value":"99999000"}],"scripts":[{"invocation":"0c40bfce1ead7d53339440bb29745eed4ad9840875de4f970950065291e7a14cbd249bfbf777d9a997c5e00bbc08e8ce9fdd2cd13c45c3585b4939599ff84c6149ff","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"}]}}`,
|
||||
result: func(c *Client) interface{} {
|
||||
blockHash, err := util.Uint256DecodeStringLE("81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb")
|
||||
blockHash, err := util.Uint256DecodeStringLE("75ab743487ce969792a4cb3c235d9ea5ff97af42b2646183c981437a077fbc45")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sender, err := address.StringToUint160("Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy")
|
||||
sender, err := address.StringToUint160("ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
invocation, err := hex.DecodeString("0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7")
|
||||
invocation, err := hex.DecodeString("0c40bfce1ead7d53339440bb29745eed4ad9840875de4f970950065291e7a14cbd249bfbf777d9a997c5e00bbc08e8ce9fdd2cd13c45c3585b4939599ff84c6149ff")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
verification, err := hex.DecodeString("130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb")
|
||||
verification, err := hex.DecodeString("0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
vin, err := util.Uint256DecodeStringLE("1f08a32642a43e3f06b3b9a9355ed274c52de85a886841a2aef7edd94d1dc3f6")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
outAddress, err := address.StringToUint160("ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tx := transaction.NewContractTX()
|
||||
tx.Nonce = 1237
|
||||
tx.ValidUntilBlock = 5
|
||||
tx.Nonce = 3
|
||||
tx.ValidUntilBlock = 1200
|
||||
tx.Sender = sender
|
||||
tx.Scripts = []transaction.Witness{
|
||||
{
|
||||
|
@ -707,6 +761,21 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
VerificationScript: verification,
|
||||
},
|
||||
}
|
||||
tx.Inputs = []transaction.Input{
|
||||
{
|
||||
PrevHash: vin,
|
||||
PrevIndex: 0,
|
||||
},
|
||||
}
|
||||
tx.Outputs = []transaction.Output{
|
||||
{
|
||||
AssetID: core.GoverningTokenID(),
|
||||
Amount: util.Fixed8FromInt64(99999000),
|
||||
ScriptHash: outAddress,
|
||||
Position: 0,
|
||||
},
|
||||
}
|
||||
|
||||
// Update hashes for correct result comparison.
|
||||
_ = tx.Hash()
|
||||
|
||||
|
@ -716,8 +785,8 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
SysFee: 0,
|
||||
NetFee: 0,
|
||||
Blockhash: blockHash,
|
||||
Confirmations: 205,
|
||||
Timestamp: uint64(1587727442),
|
||||
Confirmations: 8,
|
||||
Timestamp: uint64(1588259741),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
|
@ -53,12 +53,12 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
"getapplicationlog": {
|
||||
{
|
||||
name: "positive",
|
||||
params: `["953b6e5ba85dd068c2eba5afd2ffdf8ff832b3a791976e2fd896baf5737b2616"]`,
|
||||
params: `["9872fd330d63d64beba7122fcc9678e7f380d2163acff6a7d4f67a3c01cd67d1"]`,
|
||||
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
|
||||
check: func(t *testing.T, e *executor, acc interface{}) {
|
||||
res, ok := acc.(*result.ApplicationLog)
|
||||
require.True(t, ok)
|
||||
expectedTxHash, err := util.Uint256DecodeStringLE("953b6e5ba85dd068c2eba5afd2ffdf8ff832b3a791976e2fd896baf5737b2616")
|
||||
expectedTxHash, err := util.Uint256DecodeStringLE("9872fd330d63d64beba7122fcc9678e7f380d2163acff6a7d4f67a3c01cd67d1")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, expectedTxHash, res.TxHash)
|
||||
assert.Equal(t, 1, len(res.Executions))
|
||||
|
@ -253,7 +253,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
"getassetstate": {
|
||||
{
|
||||
name: "positive",
|
||||
params: `["b16384a950ed01ed5fc15c03fe7b98228871cb43b1bc22d67029449fc854d104"]`,
|
||||
params: `["8ef63ccd6f4ea20a93e7f4e84b2d43f778077612b241d617e42e1750cca4f2c5"]`,
|
||||
result: func(e *executor) interface{} { return &result.AssetState{} },
|
||||
check: func(t *testing.T, e *executor, as interface{}) {
|
||||
res, ok := as.(*result.AssetState)
|
||||
|
@ -472,7 +472,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
params: `["` + testchain.MultisigAddress() + `"]`,
|
||||
result: func(*executor) interface{} {
|
||||
// hash of the issueTx
|
||||
h, _ := util.Uint256DecodeStringBE("8a4711012932f4f79f9534803feab0ef85e7a313c52a36f5d56b9f8ec190bd92")
|
||||
h, _ := util.Uint256DecodeStringBE("99bd2bb2791887ddd3f64dac70ac15339956c76e7c306a1202372ff24fe30635")
|
||||
amount := util.Fixed8FromInt64(1 * 8) // (endHeight - startHeight) * genAmount[0]
|
||||
return &result.ClaimableInfo{
|
||||
Spents: []result.Claimable{
|
||||
|
@ -531,7 +531,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
"gettransactionheight": {
|
||||
{
|
||||
name: "positive",
|
||||
params: `["5f1e841f625d52dd3d73bbf5203f8468835353b7c476a4d367161ea959944981"]`,
|
||||
params: `["1f08a32642a43e3f06b3b9a9355ed274c52de85a886841a2aef7edd94d1dc3f6"]`,
|
||||
result: func(e *executor) interface{} {
|
||||
h := 1
|
||||
return &h
|
||||
|
@ -743,7 +743,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
"sendrawtransaction": {
|
||||
{
|
||||
name: "positive",
|
||||
params: `["80000b00000075a94799633ed955dd85a8af314a5b435ab51903b004000000011e4db58df4326140a371d0b0cabecea70226b93157dfb561c73ba8db599ebcb6010001f5bc5a9ac7b85a47be381260a06b5a1e7a667ce8f7d7c8baa5cfc6465571377a0030d3dec386230075a94799633ed955dd85a8af314a5b435ab5190301420c401b3040b6eea83bfbd555554c94e7a0e6077922769f3ac19c1183e14dfd1d6ef6a87658b5499921ac59ae2d2acac10d8f0f6147620e27616bb5b7305fb36b6ce0290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"]`,
|
||||
params: `["80000b00000075a94799633ed955dd85a8af314a5b435ab51903b0040000000001e53e6c239e3d8441f623ea7b48cdea60c6ae0426a8bac04296002babfeafe5a4010001dcb7e70846bb5a6828205b81b579562f0e2c15f7b3badd68d485b035882fc17d0030d3dec386230075a94799633ed955dd85a8af314a5b435ab5190301420c408378eb6bdba1f14540cf2920a4d49c52327f617dc861a21d1c085346aaae2abd410e28dc6a03471a78e71246696a591b9677a71144dfba557d1c781c8c97e350290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"]`,
|
||||
result: func(e *executor) interface{} {
|
||||
v := true
|
||||
return &v
|
||||
|
@ -890,7 +890,7 @@ func TestRPC(t *testing.T) {
|
|||
var res string
|
||||
err := json.Unmarshal(result, &res)
|
||||
require.NoErrorf(t, err, "could not parse response: %s", result)
|
||||
assert.Equal(t, "400000000000da1745e9b549bd0bfa1a569971c77eba30cd5a4b0000000000455b7b226c616e67223a227a682d434e222c226e616d65223a22e5b08fe89a81e882a1227d2c7b226c616e67223a22656e222c226e616d65223a22416e745368617265227d5d0000c16ff28623000000da1745e9b549bd0bfa1a569971c77eba30cd5a4b00000000", res)
|
||||
assert.Equal(t, "400000000000da1745e9b549bd0bfa1a569971c77eba30cd5a4b0000000000455b7b226c616e67223a227a682d434e222c226e616d65223a22e5b08fe89a81e882a1227d2c7b226c616e67223a22656e222c226e616d65223a22416e745368617265227d5d0000c16ff28623000000da1745e9b549bd0bfa1a569971c77eba30cd5a4b0000000000", res)
|
||||
})
|
||||
|
||||
t.Run("getrawtransaction 2 arguments", func(t *testing.T) {
|
||||
|
@ -902,7 +902,7 @@ func TestRPC(t *testing.T) {
|
|||
var res string
|
||||
err := json.Unmarshal(result, &res)
|
||||
require.NoErrorf(t, err, "could not parse response: %s", result)
|
||||
assert.Equal(t, "400000000000da1745e9b549bd0bfa1a569971c77eba30cd5a4b0000000000455b7b226c616e67223a227a682d434e222c226e616d65223a22e5b08fe89a81e882a1227d2c7b226c616e67223a22656e222c226e616d65223a22416e745368617265227d5d0000c16ff28623000000da1745e9b549bd0bfa1a569971c77eba30cd5a4b00000000", res)
|
||||
assert.Equal(t, "400000000000da1745e9b549bd0bfa1a569971c77eba30cd5a4b0000000000455b7b226c616e67223a227a682d434e222c226e616d65223a22e5b08fe89a81e882a1227d2c7b226c616e67223a22656e222c226e616d65223a22416e745368617265227d5d0000c16ff28623000000da1745e9b549bd0bfa1a569971c77eba30cd5a4b0000000000", res)
|
||||
})
|
||||
|
||||
t.Run("getrawtransaction 2 arguments, verbose", func(t *testing.T) {
|
||||
|
@ -991,7 +991,7 @@ func TestRPC(t *testing.T) {
|
|||
err := json.Unmarshal(res, &txOut)
|
||||
require.NoErrorf(t, err, "could not parse response: %s", res)
|
||||
assert.Equal(t, 0, txOut.N)
|
||||
assert.Equal(t, "0xf5bc5a9ac7b85a47be381260a06b5a1e7a667ce8f7d7c8baa5cfc6465571377a", txOut.Asset)
|
||||
assert.Equal(t, "0xdcb7e70846bb5a6828205b81b579562f0e2c15f7b3badd68d485b035882fc17d", txOut.Asset)
|
||||
assert.Equal(t, util.Fixed8FromInt64(100000000), txOut.Value)
|
||||
assert.Equal(t, testchain.MultisigAddress(), txOut.Address)
|
||||
})
|
||||
|
|
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
Binary file not shown.
|
@ -5,6 +5,8 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
// Uint160Size is the size of Uint160 in bytes.
|
||||
|
@ -131,3 +133,13 @@ func (u *Uint160) UnmarshalJSON(data []byte) (err error) {
|
|||
func (u Uint160) MarshalJSON() ([]byte, error) {
|
||||
return []byte(`"0x` + u.StringLE() + `"`), nil
|
||||
}
|
||||
|
||||
// EncodeBinary implements Serializable interface.
|
||||
func (u *Uint160) EncodeBinary(bw *io.BinWriter) {
|
||||
bw.WriteBytes(u[:])
|
||||
}
|
||||
|
||||
// DecodeBinary implements Serializable interface.
|
||||
func (u *Uint160) DecodeBinary(br *io.BinReader) {
|
||||
br.ReadBytes(u[:])
|
||||
}
|
||||
|
|
|
@ -223,10 +223,14 @@ func (c *Context) String() string {
|
|||
return "execution context"
|
||||
}
|
||||
|
||||
// GetContextScriptHash returns script hash of the invocation stack element
|
||||
// getContextScriptHash returns script hash of the invocation stack element
|
||||
// number n.
|
||||
func (v *VM) GetContextScriptHash(n int) util.Uint160 {
|
||||
ctxIface := v.Istack().Peek(n).Value()
|
||||
func (v *VM) getContextScriptHash(n int) util.Uint160 {
|
||||
element := v.Istack().Peek(n)
|
||||
if element == nil {
|
||||
return util.Uint160{}
|
||||
}
|
||||
ctxIface := element.Value()
|
||||
ctx := ctxIface.(*Context)
|
||||
return ctx.ScriptHash()
|
||||
}
|
||||
|
@ -234,7 +238,7 @@ func (v *VM) GetContextScriptHash(n int) util.Uint160 {
|
|||
// PushContextScriptHash pushes to evaluation stack the script hash of the
|
||||
// invocation stack element number n.
|
||||
func (v *VM) PushContextScriptHash(n int) error {
|
||||
h := v.GetContextScriptHash(n)
|
||||
h := v.getContextScriptHash(n)
|
||||
v.Estack().PushVal(h.BytesBE())
|
||||
return nil
|
||||
}
|
||||
|
|
22
pkg/vm/vm.go
22
pkg/vm/vm.go
|
@ -34,6 +34,13 @@ func newError(ip int, op opcode.Opcode, err interface{}) *errorAtInstruct {
|
|||
// StateMessage is a vm state message which could be used as additional info for example by cli.
|
||||
type StateMessage string
|
||||
|
||||
// ScriptHashGetter defines an interface for getting calling, entry and current script hashes.
|
||||
type ScriptHashGetter interface {
|
||||
GetCallingScriptHash() util.Uint160
|
||||
GetEntryScriptHash() util.Uint160
|
||||
GetCurrentScriptHash() util.Uint160
|
||||
}
|
||||
|
||||
const (
|
||||
// MaxArraySize is the maximum array size allowed in the VM.
|
||||
MaxArraySize = 1024
|
||||
|
@ -1527,3 +1534,18 @@ func (v *VM) bytesToPublicKey(b []byte) *keys.PublicKey {
|
|||
}
|
||||
return pkey
|
||||
}
|
||||
|
||||
// GetCallingScriptHash implements ScriptHashGetter interface
|
||||
func (v *VM) GetCallingScriptHash() util.Uint160 {
|
||||
return v.getContextScriptHash(1)
|
||||
}
|
||||
|
||||
// GetEntryScriptHash implements ScriptHashGetter interface
|
||||
func (v *VM) GetEntryScriptHash() util.Uint160 {
|
||||
return v.getContextScriptHash(v.Istack().Len() - 1)
|
||||
}
|
||||
|
||||
// GetCurrentScriptHash implements ScriptHashGetter interface
|
||||
func (v *VM) GetCurrentScriptHash() util.Uint160 {
|
||||
return v.getContextScriptHash(0)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue