Merge pull request #1070 from nspcc-dev/fix/getapplicationlog
Update `getapplicationlog` RPC
This commit is contained in:
commit
ce6bacd51a
12 changed files with 48 additions and 60 deletions
|
@ -565,6 +565,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
|||
systemInterop := bc.newInteropContext(trigger.System, cache, block, nil)
|
||||
v := SpawnVM(systemInterop)
|
||||
v.LoadScriptWithFlags(bc.contracts.GetPersistScript(), smartcontract.AllowModifyStates|smartcontract.AllowCall)
|
||||
v.SetPriceGetter(getPrice)
|
||||
if err := v.Run(); err != nil {
|
||||
return errors.Wrap(err, "can't persist native contracts")
|
||||
} else if _, err := systemInterop.DAO.Persist(); err != nil {
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -65,7 +66,10 @@ func (cs *Contracts) GetPersistScript() []byte {
|
|||
w := io.NewBufBinWriter()
|
||||
for i := range cs.Contracts {
|
||||
md := cs.Contracts[i].Metadata()
|
||||
emit.AppCallWithOperationAndArgs(w.BinWriter, md.Hash, "onPersist")
|
||||
emit.Int(w.BinWriter, 0)
|
||||
emit.Opcode(w.BinWriter, opcode.NEWARRAY)
|
||||
emit.String(w.BinWriter, "onPersist")
|
||||
emit.AppCall(w.BinWriter, md.Hash)
|
||||
}
|
||||
cs.persistScript = w.Bytes()
|
||||
return cs.persistScript
|
||||
|
|
|
@ -103,28 +103,19 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
invoke: func(c *Client) (interface{}, error) {
|
||||
return c.GetApplicationLog(util.Uint256{})
|
||||
},
|
||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"txid":"0x17145a039fca704fcdbeb46e6b210af98a1a9e5b9768e46ffc38f71c79ac2521","executions":[{"trigger":"Application","contract":"0xb9fa3b421eb749d5dd585fe1c1133b311a14bcb1","vmstate":"HALT","gas_consumed":"1","stack":[{"type":"Integer","value":1}],"notifications":[]}]}}`,
|
||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"txid":"0x17145a039fca704fcdbeb46e6b210af98a1a9e5b9768e46ffc38f71c79ac2521","trigger":"Application","vmstate":"HALT","gas_consumed":"1","stack":[{"type":"Integer","value":1}],"notifications":[]}}`,
|
||||
result: func(c *Client) interface{} {
|
||||
txHash, err := util.Uint256DecodeStringLE("17145a039fca704fcdbeb46e6b210af98a1a9e5b9768e46ffc38f71c79ac2521")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
scriptHash, err := util.Uint160DecodeStringLE("b9fa3b421eb749d5dd585fe1c1133b311a14bcb1")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return &result.ApplicationLog{
|
||||
TxHash: txHash,
|
||||
Executions: []result.Execution{
|
||||
{
|
||||
Trigger: "Application",
|
||||
ScriptHash: scriptHash,
|
||||
VMState: "HALT",
|
||||
GasConsumed: util.Fixed8FromInt64(1),
|
||||
Stack: []smartcontract.Parameter{{Type: smartcontract.IntegerType, Value: int64(1)}},
|
||||
Events: []result.NotificationEvent{},
|
||||
},
|
||||
},
|
||||
TxHash: txHash,
|
||||
Trigger: "Application",
|
||||
VMState: "HALT",
|
||||
GasConsumed: "1",
|
||||
Stack: []smartcontract.Parameter{{Type: smartcontract.IntegerType, Value: int64(1)}},
|
||||
Events: []result.NotificationEvent{},
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
@ -116,9 +116,9 @@ func TestWSClientEvents(t *testing.T) {
|
|||
var ok bool
|
||||
// Events from RPC server test chain.
|
||||
var events = []string{
|
||||
`{"jsonrpc":"2.0","method":"transaction_executed","params":[{"txid":"0xe1cd5e57e721d2a2e05fb1f08721b12057b25ab1dd7fd0f33ee1639932fdfad7","executions":[{"trigger":"Application","contract":"0x0000000000000000000000000000000000000000","vmstate":"HALT","gas_consumed":"2.291","stack":[],"notifications":[{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"Y29udHJhY3QgY2FsbA=="},{"type":"ByteArray","value":"dHJhbnNmZXI="},{"type":"Array","value":[{"type":"ByteArray","value":"dpFiJB7t+XwkgWUq3xug9b9XQxs="},{"type":"ByteArray","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"Integer","value":"1000"}]}]}},{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"dHJhbnNmZXI="},{"type":"ByteArray","value":"dpFiJB7t+XwkgWUq3xug9b9XQxs="},{"type":"ByteArray","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"Integer","value":"1000"}]}}]}]}]}`,
|
||||
`{"jsonrpc":"2.0","method":"transaction_executed","params":[{"txid":"0xe1cd5e57e721d2a2e05fb1f08721b12057b25ab1dd7fd0f33ee1639932fdfad7","trigger":"Application","vmstate":"HALT","gas_consumed":"2.291","stack":[],"notifications":[{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"Y29udHJhY3QgY2FsbA=="},{"type":"ByteArray","value":"dHJhbnNmZXI="},{"type":"Array","value":[{"type":"ByteArray","value":"dpFiJB7t+XwkgWUq3xug9b9XQxs="},{"type":"ByteArray","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"Integer","value":"1000"}]}]}},{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"dHJhbnNmZXI="},{"type":"ByteArray","value":"dpFiJB7t+XwkgWUq3xug9b9XQxs="},{"type":"ByteArray","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"Integer","value":"1000"}]}}]}]}`,
|
||||
`{"jsonrpc":"2.0","method":"notification_from_execution","params":[{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"Y29udHJhY3QgY2FsbA=="},{"type":"ByteArray","value":"dHJhbnNmZXI="},{"type":"Array","value":[{"type":"ByteArray","value":"dpFiJB7t+XwkgWUq3xug9b9XQxs="},{"type":"ByteArray","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"Integer","value":"1000"}]}]}}]}`,
|
||||
`{"jsonrpc":"2.0","method":"transaction_executed","params":[{"txid":"0xf97a72b7722c109f909a8bc16c22368c5023d85828b09b127b237aace33cf099","executions":[{"trigger":"Application","contract":"0x0000000000000000000000000000000000000000","vmstate":"HALT","gas_consumed":"0.0604261","stack":[],"notifications":[{"contract":"0xe65ff7b3a02d207b584a5c27057d4e9862ef01da","state":{"type":"Array","value":[{"type":"ByteArray","value":"Y29udHJhY3QgY2FsbA=="},{"type":"ByteArray","value":"dHJhbnNmZXI="},{"type":"Array","value":[{"type":"ByteArray","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"ByteArray","value":"IHKCdK+vw29DoHHTKM+j5inZy7A="},{"type":"Integer","value":"123"}]}]}},{"contract":"0xe65ff7b3a02d207b584a5c27057d4e9862ef01da","state":{"type":"Array","value":[{"type":"ByteArray","value":"dHJhbnNmZXI="},{"type":"ByteArray","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"ByteArray","value":"IHKCdK+vw29DoHHTKM+j5inZy7A="},{"type":"Integer","value":"123"}]}}]}]}]}`,
|
||||
`{"jsonrpc":"2.0","method":"transaction_executed","params":[{"txid":"0xf97a72b7722c109f909a8bc16c22368c5023d85828b09b127b237aace33cf099","trigger":"Application","vmstate":"HALT","gas_consumed":"0.0604261","stack":[],"notifications":[{"contract":"0xe65ff7b3a02d207b584a5c27057d4e9862ef01da","state":{"type":"Array","value":[{"type":"ByteArray","value":"Y29udHJhY3QgY2FsbA=="},{"type":"ByteArray","value":"dHJhbnNmZXI="},{"type":"Array","value":[{"type":"ByteArray","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"ByteArray","value":"IHKCdK+vw29DoHHTKM+j5inZy7A="},{"type":"Integer","value":"123"}]}]}},{"contract":"0xe65ff7b3a02d207b584a5c27057d4e9862ef01da","state":{"type":"Array","value":[{"type":"ByteArray","value":"dHJhbnNmZXI="},{"type":"ByteArray","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"ByteArray","value":"IHKCdK+vw29DoHHTKM+j5inZy7A="},{"type":"Integer","value":"123"}]}}]}]}`,
|
||||
`{"jsonrpc":"2.0","method":"block_added","params":[{"hash":"0x2d312f6379ead13cf62634c703091b750e7903728df2a3cf5bd96ce80b84a849","version":0,"previousblockhash":"0xb8237d34c156cac6be7b01578decf8ac8c99a62f0b6f774d622aad7be0fe189d","merkleroot":"0xf89169e89361692b71e671f13c088e84c5325015c413e8f89e7ba38efdb41287","time":1592472500006,"index":6,"nextconsensus":"Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2","witnesses":[{"invocation":"DEDblVguNGXWbUswDvBfVJzBt76BJyJ0Ga6siquyjioGn4Dbr6zy1IvcLl3xN5akcejRy9e+Mr1qvpe/gkLgtW4QDEDRwPISZagMFjE/plXTnZ/gEU0IbBAAe23U29zVWteUmzRsPxF/MdzXvdffR9W0edkj17AmkWpn+5rqzH9aCOpLDECEvjgxZaRoAHEDNzp1REllLcGzMwrwSjudtzfgRglQL3g1BKerDx6cGHH73medRVkL9QVm4KzSxlywVtvhwBMrDEBuPKvzg5TtakFW2jr/bfmy1bn2FiLARlOySwaGdKRV93ozA5lVEIAvHbBlJtT4/5H8jHjbncXXMrP3OUHqebZz","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFAtBMHOzuw=="}],"consensus_data":{"primary":0,"nonce":"0000000000000457"},"tx":[{"txid":"0xf97a72b7722c109f909a8bc16c22368c5023d85828b09b127b237aace33cf099","size":265,"version":0,"nonce":9,"sender":"NQRLhCpAru9BjGsMwk67vdMwmzKMRgsnnN","sys_fee":"0","net_fee":"0.0036521","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x870958fd19ee3f6c7dc3c2df399d013910856e31","scopes":"CalledByEntry"}],"script":"AHsMFCBygnSvr8NvQ6Bx0yjPo+Yp2cuwDBQxboUQOQGdOd/Cw31sP+4Z/VgJhxPADAh0cmFuc2ZlcgwU2gHvYphOfQUnXEpYeyAtoLP3X+ZBYn1bUjg=","scripts":[{"invocation":"DECwklSj3liZOJbktRtkVdUCu8U2LQlrU6Dv8NtMgd0xXbk5lXjc2p68xv6xtJXbJ4aoFMJZ9lkcNpGoeUCcaCet","verification":"DCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcILQQqQatQ="}]}]}]}`,
|
||||
`{"jsonrpc":"2.0","method":"event_missed","params":[]}`,
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package result
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
|
@ -10,16 +12,10 @@ import (
|
|||
// ApplicationLog wrapper used for the representation of the
|
||||
// state.AppExecResult based on the specific tx on the RPC Server.
|
||||
type ApplicationLog struct {
|
||||
TxHash util.Uint256 `json:"txid"`
|
||||
Executions []Execution `json:"executions"`
|
||||
}
|
||||
|
||||
// Execution response wrapper
|
||||
type Execution struct {
|
||||
TxHash util.Uint256 `json:"txid"`
|
||||
Trigger string `json:"trigger"`
|
||||
ScriptHash util.Uint160 `json:"contract"`
|
||||
VMState string `json:"vmstate"`
|
||||
GasConsumed util.Fixed8 `json:"gas_consumed"`
|
||||
GasConsumed string `json:"gas_consumed"`
|
||||
Stack []smartcontract.Parameter `json:"stack"`
|
||||
Events []NotificationEvent `json:"notifications"`
|
||||
}
|
||||
|
@ -42,25 +38,18 @@ func StateEventToResultNotification(event state.NotificationEvent) NotificationE
|
|||
}
|
||||
|
||||
// NewApplicationLog creates a new ApplicationLog wrapper.
|
||||
func NewApplicationLog(appExecRes *state.AppExecResult, scriptHash util.Uint160) ApplicationLog {
|
||||
func NewApplicationLog(appExecRes *state.AppExecResult) ApplicationLog {
|
||||
events := make([]NotificationEvent, 0, len(appExecRes.Events))
|
||||
for _, e := range appExecRes.Events {
|
||||
events = append(events, StateEventToResultNotification(e))
|
||||
}
|
||||
|
||||
triggerString := appExecRes.Trigger.String()
|
||||
|
||||
executions := []Execution{{
|
||||
Trigger: triggerString,
|
||||
ScriptHash: scriptHash,
|
||||
return ApplicationLog{
|
||||
TxHash: appExecRes.TxHash,
|
||||
Trigger: appExecRes.Trigger.String(),
|
||||
VMState: appExecRes.VMState,
|
||||
GasConsumed: appExecRes.GasConsumed,
|
||||
GasConsumed: strconv.FormatInt(int64(appExecRes.GasConsumed), 10),
|
||||
Stack: appExecRes.Stack,
|
||||
Events: events,
|
||||
}}
|
||||
|
||||
return ApplicationLog{
|
||||
TxHash: appExecRes.TxHash,
|
||||
Executions: executions,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/blockchainer"
|
||||
"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/crypto/hash"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
|
||||
|
@ -497,14 +496,7 @@ func (s *Server) getApplicationLog(reqParams request.Params) (interface{}, *resp
|
|||
return nil, response.NewRPCError("Unknown transaction", "", nil)
|
||||
}
|
||||
|
||||
tx, _, err := s.chain.GetTransaction(txHash)
|
||||
if err != nil {
|
||||
return nil, response.NewRPCError("Error while getting transaction", "", nil)
|
||||
}
|
||||
|
||||
scriptHash := hash.Hash160(tx.Script)
|
||||
|
||||
return result.NewApplicationLog(appExecResult, scriptHash), nil
|
||||
return result.NewApplicationLog(appExecResult), nil
|
||||
}
|
||||
|
||||
func (s *Server) getNEP5Balances(ps request.Params) (interface{}, *response.Error) {
|
||||
|
@ -1153,7 +1145,7 @@ chloop:
|
|||
resp.Payload[0] = b
|
||||
case execution := <-s.executionCh:
|
||||
resp.Event = response.ExecutionEventID
|
||||
resp.Payload[0] = result.NewApplicationLog(execution, util.Uint160{})
|
||||
resp.Payload[0] = result.NewApplicationLog(execution)
|
||||
case notification := <-s.notificationCh:
|
||||
resp.Event = response.NotificationEventID
|
||||
resp.Payload[0] = result.StateEventToResultNotification(*notification)
|
||||
|
|
|
@ -65,9 +65,8 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
expectedTxHash, err := util.Uint256DecodeStringLE(deploymentTxHash)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, expectedTxHash, res.TxHash)
|
||||
assert.Equal(t, 1, len(res.Executions))
|
||||
assert.Equal(t, "Application", res.Executions[0].Trigger)
|
||||
assert.Equal(t, "HALT", res.Executions[0].VMState)
|
||||
assert.Equal(t, "Application", res.Trigger)
|
||||
assert.Equal(t, "HALT", res.VMState)
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -824,6 +823,16 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
|
|||
})
|
||||
}
|
||||
|
||||
t.Run("getapplicationlog for block", func(t *testing.T) {
|
||||
rpc := `{"jsonrpc": "2.0", "id": 1, "method": "getapplicationlog", "params": ["%s"]}`
|
||||
body := doRPCCall(fmt.Sprintf(rpc, e.chain.GetHeaderHash(1).StringLE()), httpSrv.URL, t)
|
||||
data := checkErrGetResult(t, body, false)
|
||||
var res result.ApplicationLog
|
||||
require.NoError(t, json.Unmarshal(data, &res))
|
||||
require.Equal(t, "System", res.Trigger)
|
||||
require.Equal(t, "HALT", res.VMState)
|
||||
})
|
||||
|
||||
t.Run("submit", func(t *testing.T) {
|
||||
rpc := `{"jsonrpc": "2.0", "id": 1, "method": "submitblock", "params": ["%s"]}`
|
||||
t.Run("invalid signature", func(t *testing.T) {
|
||||
|
|
|
@ -77,7 +77,7 @@ func (f *feed) Matches(r *response.Notification) bool {
|
|||
case response.ExecutionEventID:
|
||||
filt := f.filter.(request.ExecutionFilter)
|
||||
applog := r.Payload[0].(result.ApplicationLog)
|
||||
return len(applog.Executions) != 0 && applog.Executions[0].VMState == filt.State
|
||||
return applog.VMState == filt.State
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -185,9 +185,7 @@ func TestFilteredSubscriptions(t *testing.T) {
|
|||
check: func(t *testing.T, resp *response.Notification) {
|
||||
rmap := resp.Payload[0].(map[string]interface{})
|
||||
require.Equal(t, response.ExecutionEventID, resp.Event)
|
||||
execs := rmap["executions"].([]interface{})
|
||||
exec0 := execs[0].(map[string]interface{})
|
||||
st := exec0["vmstate"].(string)
|
||||
st := rmap["vmstate"].(string)
|
||||
require.Equal(t, "HALT", st)
|
||||
},
|
||||
},
|
||||
|
|
|
@ -48,7 +48,7 @@ func (pt ParamType) String() string {
|
|||
case Hash256Type:
|
||||
return "Hash256"
|
||||
case ByteArrayType:
|
||||
return "ByteArray"
|
||||
return "ByteString"
|
||||
case PublicKeyType:
|
||||
return "PublicKey"
|
||||
case StringType:
|
||||
|
@ -143,7 +143,7 @@ func ParseParamType(typ string) (ParamType, error) {
|
|||
return Hash160Type, nil
|
||||
case "hash256":
|
||||
return Hash256Type, nil
|
||||
case "bytes", "bytearray":
|
||||
case "bytes", "bytearray", "bytestring":
|
||||
return ByteArrayType, nil
|
||||
case "key", "publickey":
|
||||
return PublicKeyType, nil
|
||||
|
|
|
@ -53,7 +53,7 @@ func NewParameter(t ParamType) Parameter {
|
|||
|
||||
type rawParameter struct {
|
||||
Type ParamType `json:"type"`
|
||||
Value json.RawMessage `json:"value"`
|
||||
Value json.RawMessage `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
// MarshalJSON implements Marshaler interface.
|
||||
|
@ -88,7 +88,7 @@ func (p *Parameter) MarshalJSON() ([]byte, error) {
|
|||
ppair := p.Value.([]ParameterPair)
|
||||
resultRawValue, resultErr = json.Marshal(ppair)
|
||||
case InteropInterfaceType, AnyType:
|
||||
resultRawValue = []byte("null")
|
||||
resultRawValue = nil
|
||||
default:
|
||||
resultErr = errors.Errorf("Marshaller for type %s not implemented", p.Type)
|
||||
}
|
||||
|
|
|
@ -70,6 +70,8 @@ func serializeItemTo(item Item, w *io.BinWriter, seen map[Item]bool) {
|
|||
serializeItemTo(t.Value().([]MapElement)[i].Key, w, seen)
|
||||
serializeItemTo(t.Value().([]MapElement)[i].Value, w, seen)
|
||||
}
|
||||
case Null:
|
||||
w.WriteB(byte(AnyT))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,6 +129,8 @@ func DecodeBinaryStackItem(r *io.BinReader) Item {
|
|||
m.Add(key, value)
|
||||
}
|
||||
return m
|
||||
case AnyT:
|
||||
return Null{}
|
||||
default:
|
||||
r.Err = errors.New("unknown type")
|
||||
return nil
|
||||
|
|
Loading…
Reference in a new issue