mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-26 19:42:23 +00:00
Merge pull request #2331 from nspcc-dev/extend-invokefunction-results
Extend invokefunction results
This commit is contained in:
commit
4e864ca7fb
7 changed files with 175 additions and 74 deletions
|
@ -1,7 +1,6 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -14,58 +13,9 @@ import (
|
||||||
type dump []blockDump
|
type dump []blockDump
|
||||||
|
|
||||||
type blockDump struct {
|
type blockDump struct {
|
||||||
Block uint32 `json:"block"`
|
Block uint32 `json:"block"`
|
||||||
Size int `json:"size"`
|
Size int `json:"size"`
|
||||||
Storage []storageOp `json:"storage"`
|
Storage []storage.Operation `json:"storage"`
|
||||||
}
|
|
||||||
|
|
||||||
type storageOp struct {
|
|
||||||
State string `json:"state"`
|
|
||||||
Key string `json:"key"`
|
|
||||||
Value string `json:"value,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// batchToMap converts batch to a map so that JSON is compatible
|
|
||||||
// with https://github.com/NeoResearch/neo-storage-audit/
|
|
||||||
func batchToMap(index uint32, batch *storage.MemBatch) blockDump {
|
|
||||||
size := len(batch.Put) + len(batch.Deleted)
|
|
||||||
ops := make([]storageOp, 0, size)
|
|
||||||
for i := range batch.Put {
|
|
||||||
key := batch.Put[i].Key
|
|
||||||
if len(key) == 0 || key[0] != byte(storage.STStorage) && key[0] != byte(storage.STTempStorage) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
op := "Added"
|
|
||||||
if batch.Put[i].Exists {
|
|
||||||
op = "Changed"
|
|
||||||
}
|
|
||||||
|
|
||||||
ops = append(ops, storageOp{
|
|
||||||
State: op,
|
|
||||||
Key: base64.StdEncoding.EncodeToString(key[1:]),
|
|
||||||
Value: base64.StdEncoding.EncodeToString(batch.Put[i].Value),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range batch.Deleted {
|
|
||||||
key := batch.Deleted[i].Key
|
|
||||||
if len(key) == 0 || !batch.Deleted[i].Exists ||
|
|
||||||
key[0] != byte(storage.STStorage) && key[0] != byte(storage.STTempStorage) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
ops = append(ops, storageOp{
|
|
||||||
State: "Deleted",
|
|
||||||
Key: base64.StdEncoding.EncodeToString(key[1:]),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return blockDump{
|
|
||||||
Block: index,
|
|
||||||
Size: len(ops),
|
|
||||||
Storage: ops,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDump() *dump {
|
func newDump() *dump {
|
||||||
|
@ -73,8 +23,12 @@ func newDump() *dump {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dump) add(index uint32, batch *storage.MemBatch) {
|
func (d *dump) add(index uint32, batch *storage.MemBatch) {
|
||||||
m := batchToMap(index, batch)
|
ops := storage.BatchToOperations(batch)
|
||||||
*d = append(*d, m)
|
*d = append(*d, blockDump{
|
||||||
|
Block: index,
|
||||||
|
Size: len(ops),
|
||||||
|
Storage: ops,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dump) tryPersist(prefix string, index uint32) error {
|
func (d *dump) tryPersist(prefix string, index uint32) error {
|
||||||
|
|
|
@ -45,6 +45,15 @@ const (
|
||||||
MaxStorageValueLen = 65535
|
MaxStorageValueLen = 65535
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Operation represents a single KV operation (add/del/change) performed
|
||||||
|
// in the DB.
|
||||||
|
type Operation struct {
|
||||||
|
// State can be Added, Changed or Deleted.
|
||||||
|
State string `json:"state"`
|
||||||
|
Key []byte `json:"key"`
|
||||||
|
Value []byte `json:"value,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// SeekRange represents options for Store.Seek operation.
|
// SeekRange represents options for Store.Seek operation.
|
||||||
type SeekRange struct {
|
type SeekRange struct {
|
||||||
// Prefix denotes the Seek's lookup key.
|
// Prefix denotes the Seek's lookup key.
|
||||||
|
@ -139,3 +148,40 @@ func NewStore(cfg DBConfiguration) (Store, error) {
|
||||||
}
|
}
|
||||||
return store, err
|
return store, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BatchToOperations converts a batch of changes into array of Operations.
|
||||||
|
func BatchToOperations(batch *MemBatch) []Operation {
|
||||||
|
size := len(batch.Put) + len(batch.Deleted)
|
||||||
|
ops := make([]Operation, 0, size)
|
||||||
|
for i := range batch.Put {
|
||||||
|
key := batch.Put[i].Key
|
||||||
|
if len(key) == 0 || key[0] != byte(STStorage) && key[0] != byte(STTempStorage) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
op := "Added"
|
||||||
|
if batch.Put[i].Exists {
|
||||||
|
op = "Changed"
|
||||||
|
}
|
||||||
|
|
||||||
|
ops = append(ops, Operation{
|
||||||
|
State: op,
|
||||||
|
Key: key[1:],
|
||||||
|
Value: batch.Put[i].Value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range batch.Deleted {
|
||||||
|
key := batch.Deleted[i].Key
|
||||||
|
if len(key) == 0 || !batch.Deleted[i].Exists ||
|
||||||
|
key[0] != byte(STStorage) && key[0] != byte(STTempStorage) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ops = append(ops, Operation{
|
||||||
|
State: "Deleted",
|
||||||
|
Key: key[1:],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return ops
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -43,3 +44,24 @@ func TestAppendPrefixInt(t *testing.T) {
|
||||||
assert.Equal(t, KeyPrefix(expected[i]), KeyPrefix(prefix[0]))
|
assert.Equal(t, KeyPrefix(expected[i]), KeyPrefix(prefix[0]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBatchToOperations(t *testing.T) {
|
||||||
|
b := &MemBatch{
|
||||||
|
Put: []KeyValueExists{
|
||||||
|
{KeyValue: KeyValue{Key: []byte{byte(STStorage), 0x01}, Value: []byte{0x01}}},
|
||||||
|
{KeyValue: KeyValue{Key: []byte{byte(STAccount), 0x02}, Value: []byte{0x02}}},
|
||||||
|
{KeyValue: KeyValue{Key: []byte{byte(STStorage), 0x03}, Value: []byte{0x03}}, Exists: true},
|
||||||
|
},
|
||||||
|
Deleted: []KeyValueExists{
|
||||||
|
{KeyValue: KeyValue{Key: []byte{byte(STStorage), 0x04}, Value: []byte{0x04}}},
|
||||||
|
{KeyValue: KeyValue{Key: []byte{byte(STAccount), 0x05}, Value: []byte{0x05}}},
|
||||||
|
{KeyValue: KeyValue{Key: []byte{byte(STStorage), 0x06}, Value: []byte{0x06}}, Exists: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
o := []Operation{
|
||||||
|
{State: "Added", Key: []byte{0x01}, Value: []byte{0x01}},
|
||||||
|
{State: "Changed", Key: []byte{0x03}, Value: []byte{0x03}},
|
||||||
|
{State: "Deleted", Key: []byte{0x06}},
|
||||||
|
}
|
||||||
|
require.Equal(t, o, BatchToOperations(b))
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,10 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/iterator"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/iterator"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
@ -18,6 +21,7 @@ type Invoke struct {
|
||||||
Script []byte
|
Script []byte
|
||||||
Stack []stackitem.Item
|
Stack []stackitem.Item
|
||||||
FaultException string
|
FaultException string
|
||||||
|
Notifications []state.NotificationEvent
|
||||||
Transaction *transaction.Transaction
|
Transaction *transaction.Transaction
|
||||||
Diagnostics *InvokeDiag
|
Diagnostics *InvokeDiag
|
||||||
maxIteratorResultItems int
|
maxIteratorResultItems int
|
||||||
|
@ -26,36 +30,46 @@ type Invoke struct {
|
||||||
|
|
||||||
// InvokeDiag is an additional diagnostic data for invocation.
|
// InvokeDiag is an additional diagnostic data for invocation.
|
||||||
type InvokeDiag struct {
|
type InvokeDiag struct {
|
||||||
|
Changes []storage.Operation `json:"storagechanges"`
|
||||||
Invocations []*vm.InvocationTree `json:"invokedcontracts"`
|
Invocations []*vm.InvocationTree `json:"invokedcontracts"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInvoke returns new Invoke structure with the given fields set.
|
// NewInvoke returns new Invoke structure with the given fields set.
|
||||||
func NewInvoke(vm *vm.VM, finalize func(), script []byte, faultException string, maxIteratorResultItems int) *Invoke {
|
func NewInvoke(ic *interop.Context, script []byte, faultException string, maxIteratorResultItems int) *Invoke {
|
||||||
var diag *InvokeDiag
|
var diag *InvokeDiag
|
||||||
tree := vm.GetInvocationTree()
|
tree := ic.VM.GetInvocationTree()
|
||||||
if tree != nil {
|
if tree != nil {
|
||||||
diag = &InvokeDiag{Invocations: tree.Calls}
|
diag = &InvokeDiag{
|
||||||
|
Invocations: tree.Calls,
|
||||||
|
Changes: storage.BatchToOperations(ic.DAO.GetBatch()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notifications := ic.Notifications
|
||||||
|
if notifications == nil {
|
||||||
|
notifications = make([]state.NotificationEvent, 0)
|
||||||
}
|
}
|
||||||
return &Invoke{
|
return &Invoke{
|
||||||
State: vm.State().String(),
|
State: ic.VM.State().String(),
|
||||||
GasConsumed: vm.GasConsumed(),
|
GasConsumed: ic.VM.GasConsumed(),
|
||||||
Script: script,
|
Script: script,
|
||||||
Stack: vm.Estack().ToArray(),
|
Stack: ic.VM.Estack().ToArray(),
|
||||||
FaultException: faultException,
|
FaultException: faultException,
|
||||||
|
Notifications: notifications,
|
||||||
Diagnostics: diag,
|
Diagnostics: diag,
|
||||||
maxIteratorResultItems: maxIteratorResultItems,
|
maxIteratorResultItems: maxIteratorResultItems,
|
||||||
finalize: finalize,
|
finalize: ic.Finalize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type invokeAux struct {
|
type invokeAux struct {
|
||||||
State string `json:"state"`
|
State string `json:"state"`
|
||||||
GasConsumed int64 `json:"gasconsumed,string"`
|
GasConsumed int64 `json:"gasconsumed,string"`
|
||||||
Script []byte `json:"script"`
|
Script []byte `json:"script"`
|
||||||
Stack json.RawMessage `json:"stack"`
|
Stack json.RawMessage `json:"stack"`
|
||||||
FaultException string `json:"exception,omitempty"`
|
FaultException string `json:"exception,omitempty"`
|
||||||
Transaction []byte `json:"tx,omitempty"`
|
Notifications []state.NotificationEvent `json:"notifications"`
|
||||||
Diagnostics *InvokeDiag `json:"diagnostics,omitempty"`
|
Transaction []byte `json:"tx,omitempty"`
|
||||||
|
Diagnostics *InvokeDiag `json:"diagnostics,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type iteratorAux struct {
|
type iteratorAux struct {
|
||||||
|
@ -133,6 +147,7 @@ func (r Invoke) MarshalJSON() ([]byte, error) {
|
||||||
State: r.State,
|
State: r.State,
|
||||||
Stack: st,
|
Stack: st,
|
||||||
FaultException: r.FaultException,
|
FaultException: r.FaultException,
|
||||||
|
Notifications: r.Notifications,
|
||||||
Transaction: txbytes,
|
Transaction: txbytes,
|
||||||
Diagnostics: r.Diagnostics,
|
Diagnostics: r.Diagnostics,
|
||||||
})
|
})
|
||||||
|
@ -189,6 +204,7 @@ func (r *Invoke) UnmarshalJSON(data []byte) error {
|
||||||
r.Script = aux.Script
|
r.Script = aux.Script
|
||||||
r.State = aux.State
|
r.State = aux.State
|
||||||
r.FaultException = aux.FaultException
|
r.FaultException = aux.FaultException
|
||||||
|
r.Notifications = aux.Notifications
|
||||||
r.Transaction = tx
|
r.Transaction = tx
|
||||||
r.Diagnostics = aux.Diagnostics
|
r.Diagnostics = aux.Diagnostics
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
@ -25,6 +26,7 @@ func TestInvoke_MarshalJSON(t *testing.T) {
|
||||||
Script: []byte{10},
|
Script: []byte{10},
|
||||||
Stack: []stackitem.Item{stackitem.NewBigInteger(big.NewInt(1))},
|
Stack: []stackitem.Item{stackitem.NewBigInteger(big.NewInt(1))},
|
||||||
FaultException: "",
|
FaultException: "",
|
||||||
|
Notifications: []state.NotificationEvent{},
|
||||||
Transaction: tx,
|
Transaction: tx,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +39,7 @@ func TestInvoke_MarshalJSON(t *testing.T) {
|
||||||
"stack":[
|
"stack":[
|
||||||
{"type":"Integer","value":"1"}
|
{"type":"Integer","value":"1"}
|
||||||
],
|
],
|
||||||
|
"notifications":[],
|
||||||
"tx":"` + base64.StdEncoding.EncodeToString(tx.Bytes()) + `"
|
"tx":"` + base64.StdEncoding.EncodeToString(tx.Bytes()) + `"
|
||||||
}`
|
}`
|
||||||
require.JSONEq(t, expected, string(data))
|
require.JSONEq(t, expected, string(data))
|
||||||
|
|
|
@ -1715,7 +1715,7 @@ func (s *Server) runScriptInVM(t trigger.Type, script []byte, contractScriptHash
|
||||||
if err != nil {
|
if err != nil {
|
||||||
faultException = err.Error()
|
faultException = err.Error()
|
||||||
}
|
}
|
||||||
return result.NewInvoke(ic.VM, ic.Finalize, script, faultException, s.config.MaxIteratorResultItems), nil
|
return result.NewInvoke(ic, script, faultException, s.config.MaxIteratorResultItems), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// submitBlock broadcasts a raw block over the NEO network.
|
// submitBlock broadcasts a raw block over the NEO network.
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/fee"
|
"github.com/nspcc-dev/neo-go/pkg/core/fee"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
@ -880,6 +881,61 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
assert.NotEqual(t, 0, res.GasConsumed)
|
assert.NotEqual(t, 0, res.GasConsumed)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "positive, with notifications",
|
||||||
|
params: `["` + NNSHash.StringLE() + `", "transfer", [{"type":"Hash160", "value":"0x0bcd2978634d961c24f5aea0802297ff128724d6"},{"type":"String", "value":"neo.com"},{"type":"Any", "value":null}],["0xb248508f4ef7088e10c48f14d04be3272ca29eee"]]`,
|
||||||
|
result: func(e *executor) interface{} {
|
||||||
|
script := []byte{0x0b, 0x0c, 0x07, 0x6e, 0x65, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x0c, 0x14, 0xd6, 0x24, 0x87, 0x12, 0xff, 0x97, 0x22, 0x80, 0xa0, 0xae, 0xf5, 0x24, 0x1c, 0x96, 0x4d, 0x63, 0x78, 0x29, 0xcd, 0x0b, 0x13, 0xc0, 0x1f, 0x0c, 0x08, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x0c, 0x14, 0xdc, 0xe2, 0xd3, 0xba, 0x0e, 0xbb, 0xa9, 0xf4, 0x44, 0xac, 0xbf, 0x50, 0x08, 0x76, 0xfd, 0x7c, 0x3e, 0x2b, 0x60, 0x3a, 0x41, 0x62, 0x7d, 0x5b, 0x52}
|
||||||
|
return &result.Invoke{
|
||||||
|
State: "HALT",
|
||||||
|
GasConsumed: 33767940,
|
||||||
|
Script: script,
|
||||||
|
Stack: []stackitem.Item{stackitem.Make(true)},
|
||||||
|
Notifications: []state.NotificationEvent{{
|
||||||
|
ScriptHash: NNSHash,
|
||||||
|
Name: "Transfer",
|
||||||
|
Item: stackitem.NewArray([]stackitem.Item{
|
||||||
|
stackitem.Make([]byte{0xee, 0x9e, 0xa2, 0x2c, 0x27, 0xe3, 0x4b, 0xd0, 0x14, 0x8f, 0xc4, 0x10, 0x8e, 0x08, 0xf7, 0x4e, 0x8f, 0x50, 0x48, 0xb2}),
|
||||||
|
stackitem.Make([]byte{0xd6, 0x24, 0x87, 0x12, 0xff, 0x97, 0x22, 0x80, 0xa0, 0xae, 0xf5, 0x24, 0x1c, 0x96, 0x4d, 0x63, 0x78, 0x29, 0xcd, 0x0b}),
|
||||||
|
stackitem.Make(1),
|
||||||
|
stackitem.Make("neo.com"),
|
||||||
|
}),
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "positive, with storage changes",
|
||||||
|
params: `["0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5", "transfer", [{"type":"Hash160", "value":"0xb248508f4ef7088e10c48f14d04be3272ca29eee"},{"type":"Hash160", "value":"0x0bcd2978634d961c24f5aea0802297ff128724d6"},{"type":"Integer", "value":1},{"type":"Any", "value":null}],["0xb248508f4ef7088e10c48f14d04be3272ca29eee"],true]`,
|
||||||
|
result: func(e *executor) interface{} { return &result.Invoke{} },
|
||||||
|
check: func(t *testing.T, e *executor, inv interface{}) {
|
||||||
|
res, ok := inv.(*result.Invoke)
|
||||||
|
require.True(t, ok)
|
||||||
|
assert.NotNil(t, res.Script)
|
||||||
|
assert.Equal(t, "HALT", res.State)
|
||||||
|
assert.Equal(t, []stackitem.Item{stackitem.Make(true)}, res.Stack)
|
||||||
|
assert.NotEqual(t, 0, res.GasConsumed)
|
||||||
|
chg := []storage.Operation{{
|
||||||
|
State: "Changed",
|
||||||
|
Key: []byte{0xfa, 0xff, 0xff, 0xff, 0xb},
|
||||||
|
Value: []byte{0xbc, 0xf8, 0x8b, 0xa, 0x56, 0x79, 0x12},
|
||||||
|
}, {
|
||||||
|
State: "Added",
|
||||||
|
Key: []byte{0xfb, 0xff, 0xff, 0xff, 0x14, 0xd6, 0x24, 0x87, 0x12, 0xff, 0x97, 0x22, 0x80, 0xa0, 0xae, 0xf5, 0x24, 0x1c, 0x96, 0x4d, 0x63, 0x78, 0x29, 0xcd, 0xb},
|
||||||
|
Value: []byte{0x41, 0x3, 0x21, 0x1, 0x1, 0x21, 0x1, 0x11, 0x0},
|
||||||
|
}, {
|
||||||
|
State: "Changed",
|
||||||
|
Key: []byte{0xfb, 0xff, 0xff, 0xff, 0x14, 0xee, 0x9e, 0xa2, 0x2c, 0x27, 0xe3, 0x4b, 0xd0, 0x14, 0x8f, 0xc4, 0x10, 0x8e, 0x8, 0xf7, 0x4e, 0x8f, 0x50, 0x48, 0xb2},
|
||||||
|
Value: []byte{0x41, 0x3, 0x21, 0x4, 0x2f, 0xd9, 0xf5, 0x5, 0x21, 0x1, 0x11, 0x0},
|
||||||
|
}, {
|
||||||
|
State: "Changed",
|
||||||
|
Key: []byte{0xfa, 0xff, 0xff, 0xff, 0x14, 0xee, 0x9e, 0xa2, 0x2c, 0x27, 0xe3, 0x4b, 0xd0, 0x14, 0x8f, 0xc4, 0x10, 0x8e, 0x8, 0xf7, 0x4e, 0x8f, 0x50, 0x48, 0xb2},
|
||||||
|
Value: []byte{0x41, 0x1, 0x21, 0x5, 0x4, 0xfa, 0xb2, 0x9b, 0xd},
|
||||||
|
}}
|
||||||
|
// Can be returned in any order.
|
||||||
|
assert.ElementsMatch(t, chg, res.Diagnostics.Changes)
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "positive, verbose",
|
name: "positive, verbose",
|
||||||
params: `["` + NNSHash.StringLE() + `", "resolve", [{"type":"String", "value":"neo.com"},{"type":"Integer","value":1}], [], true]`,
|
params: `["` + NNSHash.StringLE() + `", "resolve", [{"type":"String", "value":"neo.com"},{"type":"Integer","value":1}], [], true]`,
|
||||||
|
@ -888,11 +944,13 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
stdHash, _ := e.chain.GetNativeContractScriptHash(nativenames.StdLib)
|
stdHash, _ := e.chain.GetNativeContractScriptHash(nativenames.StdLib)
|
||||||
cryptoHash, _ := e.chain.GetNativeContractScriptHash(nativenames.CryptoLib)
|
cryptoHash, _ := e.chain.GetNativeContractScriptHash(nativenames.CryptoLib)
|
||||||
return &result.Invoke{
|
return &result.Invoke{
|
||||||
State: "HALT",
|
State: "HALT",
|
||||||
GasConsumed: 17958510,
|
GasConsumed: 17958510,
|
||||||
Script: script,
|
Script: script,
|
||||||
Stack: []stackitem.Item{stackitem.Make("1.2.3.4")},
|
Stack: []stackitem.Item{stackitem.Make("1.2.3.4")},
|
||||||
|
Notifications: []state.NotificationEvent{},
|
||||||
Diagnostics: &result.InvokeDiag{
|
Diagnostics: &result.InvokeDiag{
|
||||||
|
Changes: []storage.Operation{},
|
||||||
Invocations: []*vm.InvocationTree{{
|
Invocations: []*vm.InvocationTree{{
|
||||||
Current: hash.Hash160(script),
|
Current: hash.Hash160(script),
|
||||||
Calls: []*vm.InvocationTree{
|
Calls: []*vm.InvocationTree{
|
||||||
|
@ -967,7 +1025,9 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
Script: script,
|
Script: script,
|
||||||
Stack: []stackitem.Item{},
|
Stack: []stackitem.Item{},
|
||||||
FaultException: "at instruction 0 (ROT): too big index",
|
FaultException: "at instruction 0 (ROT): too big index",
|
||||||
|
Notifications: []state.NotificationEvent{},
|
||||||
Diagnostics: &result.InvokeDiag{
|
Diagnostics: &result.InvokeDiag{
|
||||||
|
Changes: []storage.Operation{},
|
||||||
Invocations: []*vm.InvocationTree{{
|
Invocations: []*vm.InvocationTree{{
|
||||||
Current: hash.Hash160(script),
|
Current: hash.Hash160(script),
|
||||||
}},
|
}},
|
||||||
|
|
Loading…
Reference in a new issue