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 := transaction.NewInvocationTX([]byte{0x51}, 1)
|
||||||
tx.Version = 0
|
tx.Version = 0
|
||||||
|
tx.Sender = fromAddressHash
|
||||||
tx.Attributes = append(tx.Attributes,
|
tx.Attributes = append(tx.Attributes,
|
||||||
transaction.Attribute{
|
transaction.Attribute{
|
||||||
Usage: transaction.Description,
|
Usage: transaction.Description,
|
||||||
Data: []byte(randString(10)),
|
Data: []byte(randString(10)),
|
||||||
})
|
})
|
||||||
tx.Attributes = append(tx.Attributes,
|
|
||||||
transaction.Attribute{
|
|
||||||
Usage: transaction.Script,
|
|
||||||
Data: fromAddressHash.BytesBE(),
|
|
||||||
})
|
|
||||||
return tx
|
return tx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1548,17 +1548,6 @@ func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([
|
||||||
for i := range references {
|
for i := range references {
|
||||||
hashes[references[i].Out.ScriptHash] = true
|
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() {
|
for a, outputs := range t.GroupOutputByAssetID() {
|
||||||
as := bc.GetAssetState(a)
|
as := bc.GetAssetState(a)
|
||||||
|
@ -1575,6 +1564,9 @@ func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hashes[t.Sender] = true
|
hashes[t.Sender] = true
|
||||||
|
for _, c := range t.Cosigners {
|
||||||
|
hashes[c.Account] = true
|
||||||
|
}
|
||||||
switch t.Type {
|
switch t.Type {
|
||||||
case transaction.ClaimType:
|
case transaction.ClaimType:
|
||||||
claim := t.Data.(*transaction.ClaimTX)
|
claim := t.Data.(*transaction.ClaimTX)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"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/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
|
@ -10,7 +11,12 @@ import (
|
||||||
|
|
||||||
// CheckHashedWitness checks given hash against current list of script hashes
|
// CheckHashedWitness checks given hash against current list of script hashes
|
||||||
// for verifying in the interop context.
|
// 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)
|
hashes, err := ic.Chain.GetScriptHashesForVerifying(ic.Tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "failed to get script hashes")
|
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
|
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
|
// CheckKeyedWitness checks hash of signature check contract with a given public
|
||||||
// key against current list of script hashes for verifying in the interop context.
|
// key against current list of script hashes for verifying in the interop context.
|
||||||
func CheckKeyedWitness(ic *interop.Context, key *keys.PublicKey) (bool, error) {
|
func CheckKeyedWitness(ic *interop.Context, v vm.ScriptHashGetter, key *keys.PublicKey) (bool, error) {
|
||||||
return CheckHashedWitness(ic, key.GetScriptHash())
|
return CheckHashedWitness(ic, v, key.GetScriptHash())
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckWitness checks witnesses.
|
// CheckWitness checks witnesses.
|
||||||
|
@ -42,9 +95,9 @@ func CheckWitness(ic *interop.Context, v *vm.VM) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("parameter given is neither a key nor a hash")
|
return errors.New("parameter given is neither a key nor a hash")
|
||||||
}
|
}
|
||||||
res, err = CheckKeyedWitness(ic, key)
|
res, err = CheckKeyedWitness(ic, v, key)
|
||||||
} else {
|
} else {
|
||||||
res, err = CheckHashedWitness(ic, hash)
|
res, err = CheckHashedWitness(ic, v, hash)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to check")
|
return errors.Wrap(err, "failed to check")
|
||||||
|
|
|
@ -540,7 +540,7 @@ func contractMigrate(ic *interop.Context, v *vm.VM) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if contract.HasStorage() {
|
if contract.HasStorage() {
|
||||||
hash := v.GetContextScriptHash(0)
|
hash := v.GetCurrentScriptHash()
|
||||||
siMap, err := ic.DAO.GetStorageItems(hash)
|
siMap, err := ic.DAO.GetStorageItems(hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -601,7 +601,7 @@ func assetCreate(ic *interop.Context, v *vm.VM) error {
|
||||||
if owner.IsInfinity() {
|
if owner.IsInfinity() {
|
||||||
return errors.New("can't have infinity as an owner key")
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,7 +292,7 @@ func runtimeNotify(ic *interop.Context, v *vm.VM) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
item = vm.NewByteArrayItem([]byte(fmt.Sprintf("bad notification: %v", err)))
|
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)
|
ic.Notifications = append(ic.Notifications, ne)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -301,7 +301,7 @@ func runtimeNotify(ic *interop.Context, v *vm.VM) error {
|
||||||
func runtimeLog(ic *interop.Context, v *vm.VM) error {
|
func runtimeLog(ic *interop.Context, v *vm.VM) error {
|
||||||
msg := fmt.Sprintf("%q", v.Estack().Pop().Bytes())
|
msg := fmt.Sprintf("%q", v.Estack().Pop().Bytes())
|
||||||
ic.Log.Info("runtime log",
|
ic.Log.Info("runtime log",
|
||||||
zap.Stringer("script", v.GetContextScriptHash(0)),
|
zap.Stringer("script", v.GetCurrentScriptHash()),
|
||||||
zap.String("logs", msg))
|
zap.String("logs", msg))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -383,7 +383,7 @@ func storageGet(ic *interop.Context, v *vm.VM) error {
|
||||||
// storageGetContext returns storage context (scripthash).
|
// storageGetContext returns storage context (scripthash).
|
||||||
func storageGetContext(ic *interop.Context, v *vm.VM) error {
|
func storageGetContext(ic *interop.Context, v *vm.VM) error {
|
||||||
sc := &StorageContext{
|
sc := &StorageContext{
|
||||||
ScriptHash: v.GetContextScriptHash(0),
|
ScriptHash: v.GetCurrentScriptHash(),
|
||||||
ReadOnly: false,
|
ReadOnly: false,
|
||||||
}
|
}
|
||||||
v.Estack().PushVal(vm.NewInteropItem(sc))
|
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).
|
// storageGetReadOnlyContext returns read-only context (scripthash).
|
||||||
func storageGetReadOnlyContext(ic *interop.Context, v *vm.VM) error {
|
func storageGetReadOnlyContext(ic *interop.Context, v *vm.VM) error {
|
||||||
sc := &StorageContext{
|
sc := &StorageContext{
|
||||||
ScriptHash: v.GetContextScriptHash(0),
|
ScriptHash: v.GetCurrentScriptHash(),
|
||||||
ReadOnly: true,
|
ReadOnly: true,
|
||||||
}
|
}
|
||||||
v.Estack().PushVal(vm.NewInteropItem(sc))
|
v.Estack().PushVal(vm.NewInteropItem(sc))
|
||||||
|
@ -475,7 +475,7 @@ func contractDestroy(ic *interop.Context, v *vm.VM) error {
|
||||||
if ic.Trigger != trigger.Application {
|
if ic.Trigger != trigger.Application {
|
||||||
return errors.New("can't destroy contract when not triggered by 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)
|
cs, err := ic.DAO.GetContractState(hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -69,7 +69,7 @@ func (cs *Contracts) GetNativeInterop(ic *interop.Context) func(uint32) *vm.Inte
|
||||||
// getNativeInterop returns native contract interop.
|
// getNativeInterop returns native contract interop.
|
||||||
func getNativeInterop(ic *interop.Context, c interop.Contract) func(v *vm.VM) error {
|
func getNativeInterop(ic *interop.Context, c interop.Contract) func(v *vm.VM) error {
|
||||||
return func(v *vm.VM) error {
|
return func(v *vm.VM) error {
|
||||||
h := v.GetContextScriptHash(0)
|
h := v.GetCurrentScriptHash()
|
||||||
if !h.Equals(c.Metadata().Hash) {
|
if !h.Equals(c.Metadata().Hash) {
|
||||||
return errors.New("invalid 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.
|
// VoteInternal votes from account h for validarors specified in pubs.
|
||||||
func (n *NEO) VoteInternal(ic *interop.Context, h util.Uint160, pubs keys.PublicKeys) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if !ok {
|
} else if !ok {
|
||||||
|
@ -479,3 +479,24 @@ func toPublicKey(s vm.StackItem) *keys.PublicKey {
|
||||||
}
|
}
|
||||||
return pub
|
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.
|
// DecodeBinary decodes Account from the given BinReader.
|
||||||
func (s *Account) DecodeBinary(br *io.BinReader) {
|
func (s *Account) DecodeBinary(br *io.BinReader) {
|
||||||
s.Version = uint8(br.ReadB())
|
s.Version = uint8(br.ReadB())
|
||||||
br.ReadBytes(s.ScriptHash[:])
|
s.ScriptHash.DecodeBinary(br)
|
||||||
s.IsFrozen = br.ReadBool()
|
s.IsFrozen = br.ReadBool()
|
||||||
|
|
||||||
s.Balances = make(map[util.Uint256][]UnspentBalance)
|
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.
|
// EncodeBinary encodes Account to the given BinWriter.
|
||||||
func (s *Account) EncodeBinary(bw *io.BinWriter) {
|
func (s *Account) EncodeBinary(bw *io.BinWriter) {
|
||||||
bw.WriteB(byte(s.Version))
|
bw.WriteB(byte(s.Version))
|
||||||
bw.WriteBytes(s.ScriptHash[:])
|
s.ScriptHash.EncodeBinary(bw)
|
||||||
bw.WriteBool(s.IsFrozen)
|
bw.WriteBool(s.IsFrozen)
|
||||||
|
|
||||||
bw.WriteVarUint(uint64(len(s.Balances)))
|
bw.WriteVarUint(uint64(len(s.Balances)))
|
||||||
|
|
|
@ -37,11 +37,11 @@ func (a *Asset) DecodeBinary(br *io.BinReader) {
|
||||||
a.Available.DecodeBinary(br)
|
a.Available.DecodeBinary(br)
|
||||||
a.Precision = uint8(br.ReadB())
|
a.Precision = uint8(br.ReadB())
|
||||||
a.FeeMode = uint8(br.ReadB())
|
a.FeeMode = uint8(br.ReadB())
|
||||||
br.ReadBytes(a.FeeAddress[:])
|
a.FeeAddress.DecodeBinary(br)
|
||||||
|
|
||||||
a.Owner.DecodeBinary(br)
|
a.Owner.DecodeBinary(br)
|
||||||
br.ReadBytes(a.Admin[:])
|
a.Admin.DecodeBinary(br)
|
||||||
br.ReadBytes(a.Issuer[:])
|
a.Issuer.DecodeBinary(br)
|
||||||
a.Expiration = br.ReadU32LE()
|
a.Expiration = br.ReadU32LE()
|
||||||
a.IsFrozen = br.ReadBool()
|
a.IsFrozen = br.ReadBool()
|
||||||
}
|
}
|
||||||
|
@ -55,12 +55,12 @@ func (a *Asset) EncodeBinary(bw *io.BinWriter) {
|
||||||
a.Available.EncodeBinary(bw)
|
a.Available.EncodeBinary(bw)
|
||||||
bw.WriteB(byte(a.Precision))
|
bw.WriteB(byte(a.Precision))
|
||||||
bw.WriteB(byte(a.FeeMode))
|
bw.WriteB(byte(a.FeeMode))
|
||||||
bw.WriteBytes(a.FeeAddress[:])
|
a.FeeAddress.EncodeBinary(bw)
|
||||||
|
|
||||||
a.Owner.EncodeBinary(bw)
|
a.Owner.EncodeBinary(bw)
|
||||||
|
|
||||||
bw.WriteBytes(a.Admin[:])
|
a.Admin.EncodeBinary(bw)
|
||||||
bw.WriteBytes(a.Issuer[:])
|
a.Issuer.EncodeBinary(bw)
|
||||||
bw.WriteU32LE(a.Expiration)
|
bw.WriteU32LE(a.Expiration)
|
||||||
bw.WriteBool(a.IsFrozen)
|
bw.WriteBool(a.IsFrozen)
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,13 +28,13 @@ type AppExecResult struct {
|
||||||
|
|
||||||
// EncodeBinary implements the Serializable interface.
|
// EncodeBinary implements the Serializable interface.
|
||||||
func (ne *NotificationEvent) EncodeBinary(w *io.BinWriter) {
|
func (ne *NotificationEvent) EncodeBinary(w *io.BinWriter) {
|
||||||
w.WriteBytes(ne.ScriptHash[:])
|
ne.ScriptHash.EncodeBinary(w)
|
||||||
vm.EncodeBinaryStackItem(ne.Item, w)
|
vm.EncodeBinaryStackItem(ne.Item, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeBinary implements the Serializable interface.
|
// DecodeBinary implements the Serializable interface.
|
||||||
func (ne *NotificationEvent) DecodeBinary(r *io.BinReader) {
|
func (ne *NotificationEvent) DecodeBinary(r *io.BinReader) {
|
||||||
r.ReadBytes(ne.ScriptHash[:])
|
ne.ScriptHash.DecodeBinary(r)
|
||||||
ne.Item = vm.DecodeBinaryStackItem(r)
|
ne.Item = vm.DecodeBinaryStackItem(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ const (
|
||||||
ContractHash AttrUsage = 0x00
|
ContractHash AttrUsage = 0x00
|
||||||
ECDH02 AttrUsage = 0x02
|
ECDH02 AttrUsage = 0x02
|
||||||
ECDH03 AttrUsage = 0x03
|
ECDH03 AttrUsage = 0x03
|
||||||
Script AttrUsage = 0x20
|
|
||||||
Vote AttrUsage = 0x30
|
Vote AttrUsage = 0x30
|
||||||
CertURL AttrUsage = 0x80
|
CertURL AttrUsage = 0x80
|
||||||
DescriptionURL AttrUsage = 0x81
|
DescriptionURL AttrUsage = 0x81
|
||||||
|
|
|
@ -31,8 +31,6 @@ func (attr *Attribute) DecodeBinary(br *io.BinReader) {
|
||||||
Hash6, Hash7, Hash8, Hash9, Hash10, Hash11, Hash12, Hash13,
|
Hash6, Hash7, Hash8, Hash9, Hash10, Hash11, Hash12, Hash13,
|
||||||
Hash14, Hash15:
|
Hash14, Hash15:
|
||||||
datasize = 32
|
datasize = 32
|
||||||
case Script:
|
|
||||||
datasize = 20
|
|
||||||
case DescriptionURL:
|
case DescriptionURL:
|
||||||
// It's not VarUint as per C# implementation, dunno why
|
// It's not VarUint as per C# implementation, dunno why
|
||||||
var urllen = br.ReadB()
|
var urllen = br.ReadB()
|
||||||
|
@ -62,7 +60,7 @@ func (attr *Attribute) EncodeBinary(bw *io.BinWriter) {
|
||||||
case DescriptionURL:
|
case DescriptionURL:
|
||||||
bw.WriteB(byte(len(attr.Data)))
|
bw.WriteB(byte(len(attr.Data)))
|
||||||
fallthrough
|
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:
|
Hash7, Hash8, Hash9, Hash10, Hash11, Hash12, Hash13, Hash14, Hash15:
|
||||||
bw.WriteBytes(attr.Data)
|
bw.WriteBytes(attr.Data)
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -11,7 +11,6 @@ func _() {
|
||||||
_ = x[ContractHash-0]
|
_ = x[ContractHash-0]
|
||||||
_ = x[ECDH02-2]
|
_ = x[ECDH02-2]
|
||||||
_ = x[ECDH03-3]
|
_ = x[ECDH03-3]
|
||||||
_ = x[Script-32]
|
|
||||||
_ = x[Vote-48]
|
_ = x[Vote-48]
|
||||||
_ = x[CertURL-128]
|
_ = x[CertURL-128]
|
||||||
_ = x[DescriptionURL-129]
|
_ = x[DescriptionURL-129]
|
||||||
|
@ -52,19 +51,18 @@ func _() {
|
||||||
const (
|
const (
|
||||||
_AttrUsage_name_0 = "ContractHash"
|
_AttrUsage_name_0 = "ContractHash"
|
||||||
_AttrUsage_name_1 = "ECDH02ECDH03"
|
_AttrUsage_name_1 = "ECDH02ECDH03"
|
||||||
_AttrUsage_name_2 = "Script"
|
_AttrUsage_name_2 = "Vote"
|
||||||
_AttrUsage_name_3 = "Vote"
|
_AttrUsage_name_3 = "CertURLDescriptionURL"
|
||||||
_AttrUsage_name_4 = "CertURLDescriptionURL"
|
_AttrUsage_name_4 = "Description"
|
||||||
_AttrUsage_name_5 = "Description"
|
_AttrUsage_name_5 = "Hash1Hash2Hash3Hash4Hash5Hash6Hash7Hash8Hash9Hash10Hash11Hash12Hash13Hash14Hash15"
|
||||||
_AttrUsage_name_6 = "Hash1Hash2Hash3Hash4Hash5Hash6Hash7Hash8Hash9Hash10Hash11Hash12Hash13Hash14Hash15"
|
_AttrUsage_name_6 = "RemarkRemark1Remark2Remark3Remark4Remark5Remark6Remark7Remark8Remark9Remark10Remark11Remark12Remark13Remark14Remark15"
|
||||||
_AttrUsage_name_7 = "RemarkRemark1Remark2Remark3Remark4Remark5Remark6Remark7Remark8Remark9Remark10Remark11Remark12Remark13Remark14Remark15"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_AttrUsage_index_1 = [...]uint8{0, 6, 12}
|
_AttrUsage_index_1 = [...]uint8{0, 6, 12}
|
||||||
_AttrUsage_index_4 = [...]uint8{0, 7, 21}
|
_AttrUsage_index_3 = [...]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_5 = [...]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_6 = [...]uint8{0, 6, 13, 20, 27, 34, 41, 48, 55, 62, 69, 77, 85, 93, 101, 109, 117}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (i AttrUsage) String() string {
|
func (i AttrUsage) String() string {
|
||||||
|
@ -74,21 +72,19 @@ func (i AttrUsage) String() string {
|
||||||
case 2 <= i && i <= 3:
|
case 2 <= i && i <= 3:
|
||||||
i -= 2
|
i -= 2
|
||||||
return _AttrUsage_name_1[_AttrUsage_index_1[i]:_AttrUsage_index_1[i+1]]
|
return _AttrUsage_name_1[_AttrUsage_index_1[i]:_AttrUsage_index_1[i+1]]
|
||||||
case i == 32:
|
|
||||||
return _AttrUsage_name_2
|
|
||||||
case i == 48:
|
case i == 48:
|
||||||
return _AttrUsage_name_3
|
return _AttrUsage_name_2
|
||||||
case 128 <= i && i <= 129:
|
case 128 <= i && i <= 129:
|
||||||
i -= 128
|
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:
|
case i == 144:
|
||||||
return _AttrUsage_name_5
|
return _AttrUsage_name_4
|
||||||
case 161 <= i && i <= 175:
|
case 161 <= i && i <= 175:
|
||||||
i -= 161
|
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:
|
case 240 <= i && i <= 255:
|
||||||
i -= 240
|
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:
|
default:
|
||||||
return "AttrUsage(" + strconv.FormatInt(int64(i), 10) + ")"
|
return "AttrUsage(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ func NewClaimTX(claim *ClaimTX) *Transaction {
|
||||||
Nonce: rand.Uint32(),
|
Nonce: rand.Uint32(),
|
||||||
Data: claim,
|
Data: claim,
|
||||||
Attributes: []Attribute{},
|
Attributes: []Attribute{},
|
||||||
|
Cosigners: []Cosigner{},
|
||||||
Inputs: []Input{},
|
Inputs: []Input{},
|
||||||
Outputs: []Output{},
|
Outputs: []Output{},
|
||||||
Scripts: []Witness{},
|
Scripts: []Witness{},
|
||||||
|
|
|
@ -18,6 +18,7 @@ func NewContractTX() *Transaction {
|
||||||
Nonce: rand.Uint32(),
|
Nonce: rand.Uint32(),
|
||||||
Data: &ContractTX{},
|
Data: &ContractTX{},
|
||||||
Attributes: []Attribute{},
|
Attributes: []Attribute{},
|
||||||
|
Cosigners: []Cosigner{},
|
||||||
Inputs: []Input{},
|
Inputs: []Input{},
|
||||||
Outputs: []Output{},
|
Outputs: []Output{},
|
||||||
Scripts: []Witness{},
|
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,
|
Version: 1,
|
||||||
},
|
},
|
||||||
Attributes: []Attribute{},
|
Attributes: []Attribute{},
|
||||||
|
Cosigners: []Cosigner{},
|
||||||
Inputs: []Input{},
|
Inputs: []Input{},
|
||||||
Outputs: []Output{},
|
Outputs: []Output{},
|
||||||
Scripts: []Witness{},
|
Scripts: []Witness{},
|
||||||
|
|
|
@ -18,6 +18,7 @@ func NewIssueTX() *Transaction {
|
||||||
Nonce: rand.Uint32(),
|
Nonce: rand.Uint32(),
|
||||||
Data: &IssueTX{},
|
Data: &IssueTX{},
|
||||||
Attributes: []Attribute{},
|
Attributes: []Attribute{},
|
||||||
|
Cosigners: []Cosigner{},
|
||||||
Inputs: []Input{},
|
Inputs: []Input{},
|
||||||
Outputs: []Output{},
|
Outputs: []Output{},
|
||||||
Scripts: []Witness{},
|
Scripts: []Witness{},
|
||||||
|
|
|
@ -39,6 +39,7 @@ func NewRegisterTX(register *RegisterTX) *Transaction {
|
||||||
Nonce: rand.Uint32(),
|
Nonce: rand.Uint32(),
|
||||||
Data: register,
|
Data: register,
|
||||||
Attributes: []Attribute{},
|
Attributes: []Attribute{},
|
||||||
|
Cosigners: []Cosigner{},
|
||||||
Inputs: []Input{},
|
Inputs: []Input{},
|
||||||
Outputs: []Output{},
|
Outputs: []Output{},
|
||||||
Scripts: []Witness{},
|
Scripts: []Witness{},
|
||||||
|
@ -57,7 +58,7 @@ func (tx *RegisterTX) DecodeBinary(br *io.BinReader) {
|
||||||
|
|
||||||
tx.Owner.DecodeBinary(br)
|
tx.Owner.DecodeBinary(br)
|
||||||
|
|
||||||
br.ReadBytes(tx.Admin[:])
|
tx.Admin.DecodeBinary(br)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeBinary implements Serializable interface.
|
// EncodeBinary implements Serializable interface.
|
||||||
|
@ -67,7 +68,7 @@ func (tx *RegisterTX) EncodeBinary(bw *io.BinWriter) {
|
||||||
tx.Amount.EncodeBinary(bw)
|
tx.Amount.EncodeBinary(bw)
|
||||||
bw.WriteB(byte(tx.Precision))
|
bw.WriteB(byte(tx.Precision))
|
||||||
bw.WriteBytes(tx.Owner.Bytes())
|
bw.WriteBytes(tx.Owner.Bytes())
|
||||||
bw.WriteBytes(tx.Admin[:])
|
tx.Admin.EncodeBinary(bw)
|
||||||
}
|
}
|
||||||
|
|
||||||
// registeredAsset is a wrapper for RegisterTransaction
|
// registeredAsset is a wrapper for RegisterTransaction
|
||||||
|
|
|
@ -19,6 +19,9 @@ const (
|
||||||
// MaxValidUntilBlockIncrement is the upper increment size of blockhain height in blocs after
|
// 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.
|
// exceeding that a transaction should fail validation. It is set to be 2102400.
|
||||||
MaxValidUntilBlockIncrement = 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.
|
// Transaction is a process recorded in the NEO blockchain.
|
||||||
|
@ -46,6 +49,9 @@ type Transaction struct {
|
||||||
// Transaction attributes.
|
// Transaction attributes.
|
||||||
Attributes []Attribute
|
Attributes []Attribute
|
||||||
|
|
||||||
|
// Transaction cosigners (not include Sender).
|
||||||
|
Cosigners []Cosigner
|
||||||
|
|
||||||
// The inputs of the transaction.
|
// The inputs of the transaction.
|
||||||
Inputs []Input
|
Inputs []Input
|
||||||
|
|
||||||
|
@ -107,25 +113,28 @@ func (t *Transaction) AddInput(in *Input) {
|
||||||
t.Inputs = append(t.Inputs, *in)
|
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.
|
// DecodeBinary implements Serializable interface.
|
||||||
func (t *Transaction) DecodeBinary(br *io.BinReader) {
|
func (t *Transaction) DecodeBinary(br *io.BinReader) {
|
||||||
t.Type = TXType(br.ReadB())
|
t.Type = TXType(br.ReadB())
|
||||||
t.Version = uint8(br.ReadB())
|
t.Version = uint8(br.ReadB())
|
||||||
t.Nonce = br.ReadU32LE()
|
t.Nonce = br.ReadU32LE()
|
||||||
br.ReadBytes(t.Sender[:])
|
t.Sender.DecodeBinary(br)
|
||||||
|
|
||||||
t.ValidUntilBlock = br.ReadU32LE()
|
t.ValidUntilBlock = br.ReadU32LE()
|
||||||
t.decodeData(br)
|
t.decodeData(br)
|
||||||
|
|
||||||
br.ReadArray(&t.Attributes)
|
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.Inputs)
|
||||||
br.ReadArray(&t.Outputs)
|
br.ReadArray(&t.Outputs)
|
||||||
for i := range 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.Type))
|
||||||
bw.WriteB(byte(t.Version))
|
bw.WriteB(byte(t.Version))
|
||||||
bw.WriteU32LE(t.Nonce)
|
bw.WriteU32LE(t.Nonce)
|
||||||
bw.WriteBytes(t.Sender[:])
|
t.Sender.EncodeBinary(bw)
|
||||||
bw.WriteU32LE(t.ValidUntilBlock)
|
bw.WriteU32LE(t.ValidUntilBlock)
|
||||||
|
|
||||||
// Underlying TXer.
|
// Underlying TXer.
|
||||||
|
@ -193,6 +202,9 @@ func (t *Transaction) encodeHashableFields(bw *io.BinWriter) {
|
||||||
// Attributes
|
// Attributes
|
||||||
bw.WriteArray(t.Attributes)
|
bw.WriteArray(t.Attributes)
|
||||||
|
|
||||||
|
// Cosigners
|
||||||
|
bw.WriteArray(t.Cosigners)
|
||||||
|
|
||||||
// Inputs
|
// Inputs
|
||||||
bw.WriteArray(t.Inputs)
|
bw.WriteArray(t.Inputs)
|
||||||
|
|
||||||
|
@ -267,6 +279,7 @@ type transactionJSON struct {
|
||||||
Sender string `json:"sender"`
|
Sender string `json:"sender"`
|
||||||
ValidUntilBlock uint32 `json:"valid_until_block"`
|
ValidUntilBlock uint32 `json:"valid_until_block"`
|
||||||
Attributes []Attribute `json:"attributes"`
|
Attributes []Attribute `json:"attributes"`
|
||||||
|
Cosigners []Cosigner `json:"cosigners"`
|
||||||
Inputs []Input `json:"vin"`
|
Inputs []Input `json:"vin"`
|
||||||
Outputs []Output `json:"vout"`
|
Outputs []Output `json:"vout"`
|
||||||
Scripts []Witness `json:"scripts"`
|
Scripts []Witness `json:"scripts"`
|
||||||
|
@ -288,6 +301,7 @@ func (t *Transaction) MarshalJSON() ([]byte, error) {
|
||||||
Sender: address.Uint160ToString(t.Sender),
|
Sender: address.Uint160ToString(t.Sender),
|
||||||
ValidUntilBlock: t.ValidUntilBlock,
|
ValidUntilBlock: t.ValidUntilBlock,
|
||||||
Attributes: t.Attributes,
|
Attributes: t.Attributes,
|
||||||
|
Cosigners: t.Cosigners,
|
||||||
Inputs: t.Inputs,
|
Inputs: t.Inputs,
|
||||||
Outputs: t.Outputs,
|
Outputs: t.Outputs,
|
||||||
Scripts: t.Scripts,
|
Scripts: t.Scripts,
|
||||||
|
@ -323,6 +337,7 @@ func (t *Transaction) UnmarshalJSON(data []byte) error {
|
||||||
t.Nonce = tx.Nonce
|
t.Nonce = tx.Nonce
|
||||||
t.ValidUntilBlock = tx.ValidUntilBlock
|
t.ValidUntilBlock = tx.ValidUntilBlock
|
||||||
t.Attributes = tx.Attributes
|
t.Attributes = tx.Attributes
|
||||||
|
t.Cosigners = tx.Cosigners
|
||||||
t.Inputs = tx.Inputs
|
t.Inputs = tx.Inputs
|
||||||
t.Outputs = tx.Outputs
|
t.Outputs = tx.Outputs
|
||||||
t.Scripts = tx.Scripts
|
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.
|
// have been changed. Consequently, hash of the genesis block has been changed.
|
||||||
// Update expected genesis block hash for better times.
|
// Update expected genesis block hash for better times.
|
||||||
// Old hash is "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf"
|
// Old hash is "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf"
|
||||||
expect := "16ffda4cc6a9b0a0ca63f1571f7724418c43f014e2eb4e8614b4938ccf0f20f6"
|
expect := "8eb36fe47f07a795a1783a9f066603db66c5b76cf878650b1e137c114f46c0cc"
|
||||||
assert.Equal(t, expect, block.Hash().StringLE())
|
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
|
//TODO: After we added Nonce field to transaction.Transaction, UtilityTockenTx hash
|
||||||
// has been changed. Update it for better times.
|
// has been changed. Update it for better times.
|
||||||
// Old hash is "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
|
// Old hash is "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
|
||||||
expect := "b16384a950ed01ed5fc15c03fe7b98228871cb43b1bc22d67029449fc854d104"
|
expect := "8ef63ccd6f4ea20a93e7f4e84b2d43f778077612b241d617e42e1750cca4f2c5"
|
||||||
assert.Equal(t, expect, UtilityTokenID().StringLE())
|
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
|
//TODO: After we added Nonce field to transaction.Transaction, GoveringTockenTx hash
|
||||||
// has been changed. Update it for better times.
|
// has been changed. Update it for better times.
|
||||||
// Old hash is "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b"
|
// Old hash is "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b"
|
||||||
expect := "7a37715546c6cfa5bac8d7f7e87c667a1e5a6ba0601238be475ab8c79a5abcf5"
|
expect := "7dc12f8835b085d468ddbab3f7152c0e2f5679b5815b2028685abb4608e7b7dc"
|
||||||
assert.Equal(t, expect, GoverningTokenID().StringLE())
|
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)
|
emit.Opcode(w.BinWriter, opcode.THROWIFNOT)
|
||||||
|
|
||||||
tx := transaction.NewInvocationTX(w.Bytes(), gas)
|
tx := transaction.NewInvocationTX(w.Bytes(), gas)
|
||||||
tx.Attributes = append(tx.Attributes, transaction.Attribute{
|
tx.Sender = from
|
||||||
Usage: transaction.Script,
|
|
||||||
Data: from.BytesBE(),
|
|
||||||
})
|
|
||||||
|
|
||||||
tx.ValidUntilBlock, err = c.CalculateValidUntilBlock()
|
tx.ValidUntilBlock, err = c.CalculateValidUntilBlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return util.Uint256{}, fmt.Errorf("can't calculate validUntilBlock: %v", err)
|
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 {
|
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)
|
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) {
|
invoke: func(c *Client) (interface{}, error) {
|
||||||
return c.GetAccountState("")
|
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{} {
|
result: func(c *Client) interface{} {
|
||||||
scriptHash, err := util.Uint160DecodeStringLE("1179716da2e9523d153a35fb3ad10c561b1e5b1a")
|
scriptHash, err := util.Uint160DecodeStringLE("1179716da2e9523d153a35fb3ad10c561b1e5b1a")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -96,7 +96,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
invoke: func(c *Client) (interface{}, error) {
|
invoke: func(c *Client) (interface{}, error) {
|
||||||
return c.GetAssetState(util.Uint256{})
|
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{} {
|
result: func(c *Client) interface{} {
|
||||||
return &result.AssetState{
|
return &result.AssetState{
|
||||||
ID: core.GoverningTokenID(),
|
ID: core.GoverningTokenID(),
|
||||||
|
@ -134,45 +134,45 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
{
|
{
|
||||||
name: "byIndex_positive",
|
name: "byIndex_positive",
|
||||||
invoke: func(c *Client) (interface{}, error) {
|
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{} },
|
result: func(c *Client) interface{} { return &block.Block{} },
|
||||||
check: func(t *testing.T, c *Client, result interface{}) {
|
check: func(t *testing.T, c *Client, result interface{}) {
|
||||||
res, ok := result.(*block.Block)
|
res, ok := result.(*block.Block)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
assert.Equal(t, uint32(0), res.Version)
|
assert.Equal(t, uint32(0), res.Version)
|
||||||
assert.Equal(t, "81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb", res.Hash().StringLE())
|
assert.Equal(t, "75ab743487ce969792a4cb3c235d9ea5ff97af42b2646183c981437a077fbc45", res.Hash().StringLE())
|
||||||
assert.Equal(t, "a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b", res.PrevHash.StringLE())
|
assert.Equal(t, "6432511ffdb7da7766fac3591efba688793b5368789bdb374de26eaa136bf039", res.PrevHash.StringLE())
|
||||||
assert.Equal(t, "e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0", res.MerkleRoot.StringLE())
|
assert.Equal(t, "cd9211a3b642d13d1309817b8a575e4ce00e53947912b34aa0ff61f024faf405", res.MerkleRoot.StringLE())
|
||||||
assert.Equal(t, 1, len(res.Transactions))
|
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",
|
name: "byIndex_verbose_positive",
|
||||||
invoke: func(c *Client) (i interface{}, err error) {
|
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{} {
|
result: func(c *Client) interface{} {
|
||||||
hash, err := util.Uint256DecodeStringLE("81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb")
|
hash, err := util.Uint256DecodeStringLE("75ab743487ce969792a4cb3c235d9ea5ff97af42b2646183c981437a077fbc45")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
nextBlockHash, err := util.Uint256DecodeStringLE("d08e408909ae24de3470a3f231f966e15719910cb7b1a30f356b3e784c1ddf6a")
|
nextBlockHash, err := util.Uint256DecodeStringLE("ec27fed4ff8ad6a87bdd29aecee43e9ecb4e336321dac875d0b14d2aab1c5798")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
prevBlockHash, err := util.Uint256DecodeStringLE("a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b")
|
prevBlockHash, err := util.Uint256DecodeStringLE("6432511ffdb7da7766fac3591efba688793b5368789bdb374de26eaa136bf039")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
merkleRoot, err := util.Uint256DecodeStringLE("e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0")
|
merkleRoot, err := util.Uint256DecodeStringLE("cd9211a3b642d13d1309817b8a575e4ce00e53947912b34aa0ff61f024faf405")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
invScript, err := hex.DecodeString("0c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf8")
|
invScript, err := hex.DecodeString("0c404617b6788538326383015c44ffddd4a05a4e200b65a26fc84234ae8b1e28ef27b7f139dc498c58071193d530ba83081701290eba8f7108397499f5556c16e3780c402131f2bdcc494c73a379e86c46f9e9fe9899a05b23928926b1eaaf816928e160fe971b82263aa1e7efa5f7e46bf99de735fc4fc5aeb81edfdc6a9b2e9fcfa1000c408cbae1582bb9d82de9ff030b8c729737f2157844c0ca29edcdbfed1dd5e2473e0061f0dc29412477417e2c1f7c55443f11b9bd6e0d0856d1ec00240be1b9b9a70c4034d1055531cf0522ac7e5dcd817cf3cd86997ae38da806dc789b1f16eb0005f00b9bc29f7372bb43a8fed040c6763b162c8a0d8e2d0b2d7476e22e0b2b776010")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -180,21 +180,29 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
sender, err := address.StringToUint160("Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy")
|
sender, err := address.StringToUint160("ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
txInvScript, err := hex.DecodeString("0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7")
|
txInvScript, err := hex.DecodeString("0c40bfce1ead7d53339440bb29745eed4ad9840875de4f970950065291e7a14cbd249bfbf777d9a997c5e00bbc08e8ce9fdd2cd13c45c3585b4939599ff84c6149ff")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
tx := transaction.NewContractTX()
|
tx := transaction.NewContractTX()
|
||||||
tx.Nonce = 1237
|
tx.Nonce = 3
|
||||||
tx.ValidUntilBlock = 5
|
tx.ValidUntilBlock = 1200
|
||||||
tx.Sender = sender
|
tx.Sender = sender
|
||||||
tx.Scripts = []transaction.Witness{
|
tx.Scripts = []transaction.Witness{
|
||||||
{
|
{
|
||||||
|
@ -202,19 +210,34 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
VerificationScript: txVerifScript,
|
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.
|
// Update hashes for correct result comparison.
|
||||||
_ = tx.Hash()
|
_ = tx.Hash()
|
||||||
return &result.Block{
|
return &result.Block{
|
||||||
Hash: hash,
|
Hash: hash,
|
||||||
Size: 977,
|
Size: 765,
|
||||||
Version: 0,
|
Version: 0,
|
||||||
NextBlockHash: &nextBlockHash,
|
NextBlockHash: &nextBlockHash,
|
||||||
PreviousBlockHash: prevBlockHash,
|
PreviousBlockHash: prevBlockHash,
|
||||||
MerkleRoot: merkleRoot,
|
MerkleRoot: merkleRoot,
|
||||||
Time: 1587727442,
|
Time: 1588259741,
|
||||||
Index: 5,
|
Index: 202,
|
||||||
NextConsensus: "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
|
NextConsensus: "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
|
||||||
Confirmations: 203,
|
Confirmations: 6,
|
||||||
ConsensusData: result.ConsensusData{
|
ConsensusData: result.ConsensusData{
|
||||||
PrimaryIndex: 0,
|
PrimaryIndex: 0,
|
||||||
Nonce: "0000000000000457",
|
Nonce: "0000000000000457",
|
||||||
|
@ -236,53 +259,53 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
{
|
{
|
||||||
name: "byHash_positive",
|
name: "byHash_positive",
|
||||||
invoke: func(c *Client) (interface{}, error) {
|
invoke: func(c *Client) (interface{}, error) {
|
||||||
hash, err := util.Uint256DecodeStringLE("e9f71b58764157f1e2c3e29f217e654b57956ee7c8a60496b03ea85e39084b42")
|
hash, err := util.Uint256DecodeStringLE("45bc7f077a4381c9836164b242af97ffa59e5d233ccba4929796ce873474ab75")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return c.GetBlockByHash(hash)
|
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{} },
|
result: func(c *Client) interface{} { return &block.Block{} },
|
||||||
check: func(t *testing.T, c *Client, result interface{}) {
|
check: func(t *testing.T, c *Client, result interface{}) {
|
||||||
res, ok := result.(*block.Block)
|
res, ok := result.(*block.Block)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
assert.Equal(t, uint32(0), res.Version)
|
assert.Equal(t, uint32(0), res.Version)
|
||||||
assert.Equal(t, "81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb", res.Hash().StringLE())
|
assert.Equal(t, "75ab743487ce969792a4cb3c235d9ea5ff97af42b2646183c981437a077fbc45", res.Hash().StringLE())
|
||||||
assert.Equal(t, "a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b", res.PrevHash.StringLE())
|
assert.Equal(t, "6432511ffdb7da7766fac3591efba688793b5368789bdb374de26eaa136bf039", res.PrevHash.StringLE())
|
||||||
assert.Equal(t, "e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0", res.MerkleRoot.StringLE())
|
assert.Equal(t, "cd9211a3b642d13d1309817b8a575e4ce00e53947912b34aa0ff61f024faf405", res.MerkleRoot.StringLE())
|
||||||
assert.Equal(t, 1, len(res.Transactions))
|
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",
|
name: "byHash_verbose_positive",
|
||||||
invoke: func(c *Client) (i interface{}, err error) {
|
invoke: func(c *Client) (i interface{}, err error) {
|
||||||
hash, err := util.Uint256DecodeStringLE("bb09d40563c7141215b024b0959aec00a3ab316248c2ee31f32ea4c3cf4db781")
|
hash, err := util.Uint256DecodeStringLE("45bc7f077a4381c9836164b242af97ffa59e5d233ccba4929796ce873474ab75")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return c.GetBlockByHashVerbose(hash)
|
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{} {
|
result: func(c *Client) interface{} {
|
||||||
hash, err := util.Uint256DecodeStringLE("81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb")
|
hash, err := util.Uint256DecodeStringLE("75ab743487ce969792a4cb3c235d9ea5ff97af42b2646183c981437a077fbc45")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
nextBlockHash, err := util.Uint256DecodeStringLE("d08e408909ae24de3470a3f231f966e15719910cb7b1a30f356b3e784c1ddf6a")
|
nextBlockHash, err := util.Uint256DecodeStringLE("ec27fed4ff8ad6a87bdd29aecee43e9ecb4e336321dac875d0b14d2aab1c5798")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
prevBlockHash, err := util.Uint256DecodeStringLE("a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b")
|
prevBlockHash, err := util.Uint256DecodeStringLE("6432511ffdb7da7766fac3591efba688793b5368789bdb374de26eaa136bf039")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
merkleRoot, err := util.Uint256DecodeStringLE("e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0")
|
merkleRoot, err := util.Uint256DecodeStringLE("cd9211a3b642d13d1309817b8a575e4ce00e53947912b34aa0ff61f024faf405")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
invScript, err := hex.DecodeString("0c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf8")
|
invScript, err := hex.DecodeString("0c404617b6788538326383015c44ffddd4a05a4e200b65a26fc84234ae8b1e28ef27b7f139dc498c58071193d530ba83081701290eba8f7108397499f5556c16e3780c402131f2bdcc494c73a379e86c46f9e9fe9899a05b23928926b1eaaf816928e160fe971b82263aa1e7efa5f7e46bf99de735fc4fc5aeb81edfdc6a9b2e9fcfa1000c408cbae1582bb9d82de9ff030b8c729737f2157844c0ca29edcdbfed1dd5e2473e0061f0dc29412477417e2c1f7c55443f11b9bd6e0d0856d1ec00240be1b9b9a70c4034d1055531cf0522ac7e5dcd817cf3cd86997ae38da806dc789b1f16eb0005f00b9bc29f7372bb43a8fed040c6763b162c8a0d8e2d0b2d7476e22e0b2b776010")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -290,21 +313,29 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
sender, err := address.StringToUint160("Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy")
|
sender, err := address.StringToUint160("ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
txInvScript, err := hex.DecodeString("0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7")
|
txInvScript, err := hex.DecodeString("0c40bfce1ead7d53339440bb29745eed4ad9840875de4f970950065291e7a14cbd249bfbf777d9a997c5e00bbc08e8ce9fdd2cd13c45c3585b4939599ff84c6149ff")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
tx := transaction.NewContractTX()
|
tx := transaction.NewContractTX()
|
||||||
tx.Nonce = 1237
|
tx.Nonce = 3
|
||||||
tx.ValidUntilBlock = 5
|
tx.ValidUntilBlock = 1200
|
||||||
tx.Sender = sender
|
tx.Sender = sender
|
||||||
tx.Scripts = []transaction.Witness{
|
tx.Scripts = []transaction.Witness{
|
||||||
{
|
{
|
||||||
|
@ -312,19 +343,34 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
VerificationScript: txVerifScript,
|
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.
|
// Update hashes for correct result comparison.
|
||||||
_ = tx.Hash()
|
_ = tx.Hash()
|
||||||
return &result.Block{
|
return &result.Block{
|
||||||
Hash: hash,
|
Hash: hash,
|
||||||
Size: 977,
|
Size: 765,
|
||||||
Version: 0,
|
Version: 0,
|
||||||
NextBlockHash: &nextBlockHash,
|
NextBlockHash: &nextBlockHash,
|
||||||
PreviousBlockHash: prevBlockHash,
|
PreviousBlockHash: prevBlockHash,
|
||||||
MerkleRoot: merkleRoot,
|
MerkleRoot: merkleRoot,
|
||||||
Time: 1587727442,
|
Time: 1588259741,
|
||||||
Index: 5,
|
Index: 202,
|
||||||
NextConsensus: "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
|
NextConsensus: "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
|
||||||
Confirmations: 203,
|
Confirmations: 6,
|
||||||
ConsensusData: result.ConsensusData{
|
ConsensusData: result.ConsensusData{
|
||||||
PrimaryIndex: 0,
|
PrimaryIndex: 0,
|
||||||
Nonce: "0000000000000457",
|
Nonce: "0000000000000457",
|
||||||
|
@ -653,19 +699,19 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
invoke: func(c *Client) (i interface{}, err error) {
|
invoke: func(c *Client) (i interface{}, err error) {
|
||||||
hash, err := util.Uint256DecodeStringLE("b3ce8376ec464b198132fcc37fbff62fb39e6fd7f16e82074cc53d263851d969")
|
hash, err := util.Uint256DecodeStringLE("05e5321b424e9ea4c5cdd7e28462612727e34aeac639c87e57c4e9d1f7755911")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return c.GetRawTransaction(hash)
|
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{} },
|
result: func(c *Client) interface{} { return &transaction.Transaction{} },
|
||||||
check: func(t *testing.T, c *Client, result interface{}) {
|
check: func(t *testing.T, c *Client, result interface{}) {
|
||||||
res, ok := result.(*transaction.Transaction)
|
res, ok := result.(*transaction.Transaction)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
assert.Equal(t, uint8(0), res.Version)
|
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, transaction.ContractType, res.Type)
|
||||||
assert.Equal(t, false, res.Trimmed)
|
assert.Equal(t, false, res.Trimmed)
|
||||||
},
|
},
|
||||||
|
@ -673,33 +719,41 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
{
|
{
|
||||||
name: "verbose_positive",
|
name: "verbose_positive",
|
||||||
invoke: func(c *Client) (interface{}, error) {
|
invoke: func(c *Client) (interface{}, error) {
|
||||||
hash, err := util.Uint256DecodeStringLE("b3ce8376ec464b198132fcc37fbff62fb39e6fd7f16e82074cc53d263851d969")
|
hash, err := util.Uint256DecodeStringLE("05e5321b424e9ea4c5cdd7e28462612727e34aeac639c87e57c4e9d1f7755911")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return c.GetRawTransactionVerbose(hash)
|
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{} {
|
result: func(c *Client) interface{} {
|
||||||
blockHash, err := util.Uint256DecodeStringLE("81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb")
|
blockHash, err := util.Uint256DecodeStringLE("75ab743487ce969792a4cb3c235d9ea5ff97af42b2646183c981437a077fbc45")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
sender, err := address.StringToUint160("Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy")
|
sender, err := address.StringToUint160("ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
invocation, err := hex.DecodeString("0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7")
|
invocation, err := hex.DecodeString("0c40bfce1ead7d53339440bb29745eed4ad9840875de4f970950065291e7a14cbd249bfbf777d9a997c5e00bbc08e8ce9fdd2cd13c45c3585b4939599ff84c6149ff")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
tx := transaction.NewContractTX()
|
tx := transaction.NewContractTX()
|
||||||
tx.Nonce = 1237
|
tx.Nonce = 3
|
||||||
tx.ValidUntilBlock = 5
|
tx.ValidUntilBlock = 1200
|
||||||
tx.Sender = sender
|
tx.Sender = sender
|
||||||
tx.Scripts = []transaction.Witness{
|
tx.Scripts = []transaction.Witness{
|
||||||
{
|
{
|
||||||
|
@ -707,6 +761,21 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
VerificationScript: verification,
|
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.
|
// Update hashes for correct result comparison.
|
||||||
_ = tx.Hash()
|
_ = tx.Hash()
|
||||||
|
|
||||||
|
@ -716,8 +785,8 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
SysFee: 0,
|
SysFee: 0,
|
||||||
NetFee: 0,
|
NetFee: 0,
|
||||||
Blockhash: blockHash,
|
Blockhash: blockHash,
|
||||||
Confirmations: 205,
|
Confirmations: 8,
|
||||||
Timestamp: uint64(1587727442),
|
Timestamp: uint64(1588259741),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -53,12 +53,12 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
"getapplicationlog": {
|
"getapplicationlog": {
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
params: `["953b6e5ba85dd068c2eba5afd2ffdf8ff832b3a791976e2fd896baf5737b2616"]`,
|
params: `["9872fd330d63d64beba7122fcc9678e7f380d2163acff6a7d4f67a3c01cd67d1"]`,
|
||||||
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
|
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
|
||||||
check: func(t *testing.T, e *executor, acc interface{}) {
|
check: func(t *testing.T, e *executor, acc interface{}) {
|
||||||
res, ok := acc.(*result.ApplicationLog)
|
res, ok := acc.(*result.ApplicationLog)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
expectedTxHash, err := util.Uint256DecodeStringLE("953b6e5ba85dd068c2eba5afd2ffdf8ff832b3a791976e2fd896baf5737b2616")
|
expectedTxHash, err := util.Uint256DecodeStringLE("9872fd330d63d64beba7122fcc9678e7f380d2163acff6a7d4f67a3c01cd67d1")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, expectedTxHash, res.TxHash)
|
assert.Equal(t, expectedTxHash, res.TxHash)
|
||||||
assert.Equal(t, 1, len(res.Executions))
|
assert.Equal(t, 1, len(res.Executions))
|
||||||
|
@ -253,7 +253,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
"getassetstate": {
|
"getassetstate": {
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
params: `["b16384a950ed01ed5fc15c03fe7b98228871cb43b1bc22d67029449fc854d104"]`,
|
params: `["8ef63ccd6f4ea20a93e7f4e84b2d43f778077612b241d617e42e1750cca4f2c5"]`,
|
||||||
result: func(e *executor) interface{} { return &result.AssetState{} },
|
result: func(e *executor) interface{} { return &result.AssetState{} },
|
||||||
check: func(t *testing.T, e *executor, as interface{}) {
|
check: func(t *testing.T, e *executor, as interface{}) {
|
||||||
res, ok := as.(*result.AssetState)
|
res, ok := as.(*result.AssetState)
|
||||||
|
@ -472,7 +472,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
params: `["` + testchain.MultisigAddress() + `"]`,
|
params: `["` + testchain.MultisigAddress() + `"]`,
|
||||||
result: func(*executor) interface{} {
|
result: func(*executor) interface{} {
|
||||||
// hash of the issueTx
|
// hash of the issueTx
|
||||||
h, _ := util.Uint256DecodeStringBE("8a4711012932f4f79f9534803feab0ef85e7a313c52a36f5d56b9f8ec190bd92")
|
h, _ := util.Uint256DecodeStringBE("99bd2bb2791887ddd3f64dac70ac15339956c76e7c306a1202372ff24fe30635")
|
||||||
amount := util.Fixed8FromInt64(1 * 8) // (endHeight - startHeight) * genAmount[0]
|
amount := util.Fixed8FromInt64(1 * 8) // (endHeight - startHeight) * genAmount[0]
|
||||||
return &result.ClaimableInfo{
|
return &result.ClaimableInfo{
|
||||||
Spents: []result.Claimable{
|
Spents: []result.Claimable{
|
||||||
|
@ -531,7 +531,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
"gettransactionheight": {
|
"gettransactionheight": {
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
params: `["5f1e841f625d52dd3d73bbf5203f8468835353b7c476a4d367161ea959944981"]`,
|
params: `["1f08a32642a43e3f06b3b9a9355ed274c52de85a886841a2aef7edd94d1dc3f6"]`,
|
||||||
result: func(e *executor) interface{} {
|
result: func(e *executor) interface{} {
|
||||||
h := 1
|
h := 1
|
||||||
return &h
|
return &h
|
||||||
|
@ -743,7 +743,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
"sendrawtransaction": {
|
"sendrawtransaction": {
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
params: `["80000b00000075a94799633ed955dd85a8af314a5b435ab51903b004000000011e4db58df4326140a371d0b0cabecea70226b93157dfb561c73ba8db599ebcb6010001f5bc5a9ac7b85a47be381260a06b5a1e7a667ce8f7d7c8baa5cfc6465571377a0030d3dec386230075a94799633ed955dd85a8af314a5b435ab5190301420c401b3040b6eea83bfbd555554c94e7a0e6077922769f3ac19c1183e14dfd1d6ef6a87658b5499921ac59ae2d2acac10d8f0f6147620e27616bb5b7305fb36b6ce0290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"]`,
|
params: `["80000b00000075a94799633ed955dd85a8af314a5b435ab51903b0040000000001e53e6c239e3d8441f623ea7b48cdea60c6ae0426a8bac04296002babfeafe5a4010001dcb7e70846bb5a6828205b81b579562f0e2c15f7b3badd68d485b035882fc17d0030d3dec386230075a94799633ed955dd85a8af314a5b435ab5190301420c408378eb6bdba1f14540cf2920a4d49c52327f617dc861a21d1c085346aaae2abd410e28dc6a03471a78e71246696a591b9677a71144dfba557d1c781c8c97e350290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"]`,
|
||||||
result: func(e *executor) interface{} {
|
result: func(e *executor) interface{} {
|
||||||
v := true
|
v := true
|
||||||
return &v
|
return &v
|
||||||
|
@ -890,7 +890,7 @@ func TestRPC(t *testing.T) {
|
||||||
var res string
|
var res string
|
||||||
err := json.Unmarshal(result, &res)
|
err := json.Unmarshal(result, &res)
|
||||||
require.NoErrorf(t, err, "could not parse response: %s", result)
|
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) {
|
t.Run("getrawtransaction 2 arguments", func(t *testing.T) {
|
||||||
|
@ -902,7 +902,7 @@ func TestRPC(t *testing.T) {
|
||||||
var res string
|
var res string
|
||||||
err := json.Unmarshal(result, &res)
|
err := json.Unmarshal(result, &res)
|
||||||
require.NoErrorf(t, err, "could not parse response: %s", result)
|
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) {
|
t.Run("getrawtransaction 2 arguments, verbose", func(t *testing.T) {
|
||||||
|
@ -991,7 +991,7 @@ func TestRPC(t *testing.T) {
|
||||||
err := json.Unmarshal(res, &txOut)
|
err := json.Unmarshal(res, &txOut)
|
||||||
require.NoErrorf(t, err, "could not parse response: %s", res)
|
require.NoErrorf(t, err, "could not parse response: %s", res)
|
||||||
assert.Equal(t, 0, txOut.N)
|
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, util.Fixed8FromInt64(100000000), txOut.Value)
|
||||||
assert.Equal(t, testchain.MultisigAddress(), txOut.Address)
|
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"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Uint160Size is the size of Uint160 in bytes.
|
// 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) {
|
func (u Uint160) MarshalJSON() ([]byte, error) {
|
||||||
return []byte(`"0x` + u.StringLE() + `"`), nil
|
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"
|
return "execution context"
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetContextScriptHash returns script hash of the invocation stack element
|
// getContextScriptHash returns script hash of the invocation stack element
|
||||||
// number n.
|
// number n.
|
||||||
func (v *VM) GetContextScriptHash(n int) util.Uint160 {
|
func (v *VM) getContextScriptHash(n int) util.Uint160 {
|
||||||
ctxIface := v.Istack().Peek(n).Value()
|
element := v.Istack().Peek(n)
|
||||||
|
if element == nil {
|
||||||
|
return util.Uint160{}
|
||||||
|
}
|
||||||
|
ctxIface := element.Value()
|
||||||
ctx := ctxIface.(*Context)
|
ctx := ctxIface.(*Context)
|
||||||
return ctx.ScriptHash()
|
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
|
// PushContextScriptHash pushes to evaluation stack the script hash of the
|
||||||
// invocation stack element number n.
|
// invocation stack element number n.
|
||||||
func (v *VM) PushContextScriptHash(n int) error {
|
func (v *VM) PushContextScriptHash(n int) error {
|
||||||
h := v.GetContextScriptHash(n)
|
h := v.getContextScriptHash(n)
|
||||||
v.Estack().PushVal(h.BytesBE())
|
v.Estack().PushVal(h.BytesBE())
|
||||||
return nil
|
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.
|
// StateMessage is a vm state message which could be used as additional info for example by cli.
|
||||||
type StateMessage string
|
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 (
|
const (
|
||||||
// MaxArraySize is the maximum array size allowed in the VM.
|
// MaxArraySize is the maximum array size allowed in the VM.
|
||||||
MaxArraySize = 1024
|
MaxArraySize = 1024
|
||||||
|
@ -1527,3 +1534,18 @@ func (v *VM) bytesToPublicKey(b []byte) *keys.PublicKey {
|
||||||
}
|
}
|
||||||
return pkey
|
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