rpc: add notifications into the invoke* result

This commit is contained in:
Roman Khimov 2022-01-18 22:35:44 +03:00
parent 0afe8826ba
commit d79d8324e0
4 changed files with 57 additions and 18 deletions

View file

@ -4,7 +4,9 @@ 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/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 +20,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
@ -30,32 +33,38 @@ type InvokeDiag struct {
} }
// 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}
} }
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 +142,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 +199,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

View file

@ -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))

View file

@ -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.

View file

@ -880,6 +880,29 @@ 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, 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,10 +911,11 @@ 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{
Invocations: []*vm.InvocationTree{{ Invocations: []*vm.InvocationTree{{
Current: hash.Hash160(script), Current: hash.Hash160(script),
@ -967,6 +991,7 @@ 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{
Invocations: []*vm.InvocationTree{{ Invocations: []*vm.InvocationTree{{
Current: hash.Hash160(script), Current: hash.Hash160(script),