From c2534b1a0b5a0026ef3e8f7bdc87f1b2c38088ff Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 21 Jul 2020 10:31:45 +0300 Subject: [PATCH 1/2] rpc: adjust `sendrawtransaction` RPC-call It should return tx has instead of boolean. --- cli/wallet/multisig.go | 5 ++++- cli/wallet/nep5.go | 5 ++++- pkg/rpc/client/nep5.go | 6 +----- pkg/rpc/client/rpc.go | 20 ++++++++++---------- pkg/rpc/client/rpc_test.go | 18 +++++++++++------- pkg/rpc/response/result/relay_result.go | 8 ++++++++ pkg/rpc/server/server.go | 4 +++- pkg/rpc/server/server_test.go | 10 +++++++--- 8 files changed, 48 insertions(+), 28 deletions(-) create mode 100644 pkg/rpc/response/result/relay_result.go diff --git a/cli/wallet/multisig.go b/cli/wallet/multisig.go index 2e1bbf3c9..3165de97f 100644 --- a/cli/wallet/multisig.go +++ b/cli/wallet/multisig.go @@ -89,9 +89,12 @@ func signMultisig(ctx *cli.Context) error { if err != nil { return err } - if err := c.SendRawTransaction(tx); err != nil { + res, err := c.SendRawTransaction(tx) + if err != nil { return cli.NewExitError(err, 1) } + fmt.Println(res.StringLE()) + return nil } fmt.Println(tx.Hash().StringLE()) diff --git a/cli/wallet/nep5.go b/cli/wallet/nep5.go index 58c2cfb22..da9f9c3c2 100644 --- a/cli/wallet/nep5.go +++ b/cli/wallet/nep5.go @@ -384,9 +384,12 @@ func transferNEP5(ctx *cli.Context) error { } } else { _ = acc.SignTx(tx) - if err := c.SendRawTransaction(tx); err != nil { + res, err := c.SendRawTransaction(tx) + if err != nil { return cli.NewExitError(err, 1) } + fmt.Println(res.StringLE()) + return nil } fmt.Println(tx.Hash().StringLE()) diff --git a/pkg/rpc/client/nep5.go b/pkg/rpc/client/nep5.go index 673503cce..1d7d6de3c 100644 --- a/pkg/rpc/client/nep5.go +++ b/pkg/rpc/client/nep5.go @@ -159,11 +159,7 @@ func (c *Client) TransferNEP5(acc *wallet.Account, to util.Uint160, token util.U return util.Uint256{}, fmt.Errorf("can't sign tx: %v", err) } - if err := c.SendRawTransaction(tx); err != nil { - return util.Uint256{}, err - } - - return tx.Hash(), nil + return c.SendRawTransaction(tx) } func topIntFromStack(st []smartcontract.Parameter) (int64, error) { diff --git a/pkg/rpc/client/rpc.go b/pkg/rpc/client/rpc.go index 00165bd47..3bd80382e 100644 --- a/pkg/rpc/client/rpc.go +++ b/pkg/rpc/client/rpc.go @@ -2,6 +2,7 @@ package client import ( "encoding/hex" + "fmt" "github.com/nspcc-dev/neo-go/pkg/core" "github.com/nspcc-dev/neo-go/pkg/core/block" @@ -385,18 +386,15 @@ func (c *Client) invokeSomething(method string, p request.RawParams, cosigners [ // The given hex string needs to be signed with a keypair. // When the result of the response object is true, the TX has successfully // been broadcasted to the network. -func (c *Client) SendRawTransaction(rawTX *transaction.Transaction) error { +func (c *Client) SendRawTransaction(rawTX *transaction.Transaction) (util.Uint256, error) { var ( params = request.NewRawParams(hex.EncodeToString(rawTX.Bytes())) - resp bool + resp = new(result.RelayResult) ) - if err := c.performRequest("sendrawtransaction", params, &resp); err != nil { - return err + if err := c.performRequest("sendrawtransaction", params, resp); err != nil { + return util.Uint256{}, err } - if !resp { - return errors.New("sendrawtransaction returned false") - } - return nil + return resp.Hash, nil } // SubmitBlock broadcasts a raw block over the NEO network. @@ -453,11 +451,13 @@ func (c *Client) SignAndPushInvocationTx(script []byte, acc *wallet.Account, sys return txHash, errors.Wrap(err, "failed to sign tx") } txHash = tx.Hash() - err = c.SendRawTransaction(tx) - + actualHash, err := c.SendRawTransaction(tx) if err != nil { return txHash, errors.Wrap(err, "failed sendning tx") } + if !actualHash.Equals(txHash) { + return actualHash, fmt.Errorf("sent and actual tx hashes mismatch:\n\tsent: %v\n\tactual: %v", txHash.StringLE(), actualHash.StringLE()) + } return txHash, nil } diff --git a/pkg/rpc/client/rpc_test.go b/pkg/rpc/client/rpc_test.go index 38365491c..64c890e8b 100644 --- a/pkg/rpc/client/rpc_test.go +++ b/pkg/rpc/client/rpc_test.go @@ -4,6 +4,7 @@ import ( "context" "encoding/base64" "encoding/hex" + "fmt" "math/big" "net/http" "net/http/httptest" @@ -699,12 +700,15 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ { name: "positive", invoke: func(c *Client) (interface{}, error) { - return nil, c.SendRawTransaction(transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)) + return c.SendRawTransaction(transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)) }, - serverResponse: `{"jsonrpc":"2.0","id":1,"result":true}`, + serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"hash":"0x72159b0cf1221110daad6e1df6ef4ff03012173b63c86910bd7134deb659c875"}}`, result: func(c *Client) interface{} { - // no error expected - return nil + h, err := util.Uint256DecodeStringLE("72159b0cf1221110daad6e1df6ef4ff03012173b63c86910bd7134deb659c875") + if err != nil { + panic(fmt.Errorf("can't decode `sendrawtransaction` result hash: %v", err)) + } + return h }, }, }, @@ -830,7 +834,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ { name: "sendrawtransaction_bad_server_answer", invoke: func(c *Client) (interface{}, error) { - return nil, c.SendRawTransaction(transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)) + return c.SendRawTransaction(transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)) }, }, { @@ -986,7 +990,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ { name: "sendrawtransaction_invalid_params_error", invoke: func(c *Client) (interface{}, error) { - return nil, c.SendRawTransaction(&transaction.Transaction{}) + return c.SendRawTransaction(&transaction.Transaction{}) }, }, { @@ -1168,7 +1172,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ { name: "sendrawtransaction_unmarshalling_error", invoke: func(c *Client) (interface{}, error) { - return nil, c.SendRawTransaction(transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)) + return c.SendRawTransaction(transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)) }, }, { diff --git a/pkg/rpc/response/result/relay_result.go b/pkg/rpc/response/result/relay_result.go new file mode 100644 index 000000000..492d16377 --- /dev/null +++ b/pkg/rpc/response/result/relay_result.go @@ -0,0 +1,8 @@ +package result + +import "github.com/nspcc-dev/neo-go/pkg/util" + +// RelayResult ia a result of `sendrawtransaction` or `submitblock` RPC calls. +type RelayResult struct { + Hash util.Uint256 `json:"hash"` +} diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index 60e4f1086..999b40c30 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -921,7 +921,9 @@ func (s *Server) sendrawtransaction(reqParams request.Params) (interface{}, *res relayReason := s.coreServer.RelayTxn(tx) switch relayReason { case network.RelaySucceed: - results = true + results = result.RelayResult{ + Hash: tx.Hash(), + } case network.RelayAlreadyExists: resultsErr = response.ErrAlreadyExists case network.RelayOutOfMemory: diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index 7223259f5..bbf257017 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -590,9 +590,13 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: `["000a000000aa8acf859d4fe402b34e673f2156821796a488eb80969800000000009269130000000000b00400000001aa8acf859d4fe402b34e673f2156821796a488eb015d0300e87648170000000c1478ba4c24009fe510e136c9995a2e05215e1be4dc0c14aa8acf859d4fe402b34e673f2156821796a488eb13c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b523801420c4040719393aa590d962cb5a48e16360ac75a6c358c9699e9f1a853afede4d601b6783e28f5ec74542aaf59519e76830ba9d267656db324461fdb08d1d51521e103290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b4195440d78"]`, - result: func(e *executor) interface{} { - v := true - return &v + result: func(e *executor) interface{} { return &result.RelayResult{} }, + check: func(t *testing.T, e *executor, inv interface{}) { + res, ok := inv.(*result.RelayResult) + require.True(t, ok) + expectedHash, err := util.Uint256DecodeStringLE("72159b0cf1221110daad6e1df6ef4ff03012173b63c86910bd7134deb659c875") + require.NoError(t, err) + assert.Equal(t, expectedHash, res.Hash) }, }, { From 889a5d7eb616cf4caf7e711f0d927868fe44232b Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 21 Jul 2020 10:41:18 +0300 Subject: [PATCH 2/2] rpc: adjust `submitblock` RPC-call It should return block hash instead of boolean. --- pkg/rpc/client/rpc.go | 15 ++++++--------- pkg/rpc/client/rpc_test.go | 17 ++++++++++------- pkg/rpc/server/server.go | 4 +++- pkg/rpc/server/server_test.go | 6 +++--- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/pkg/rpc/client/rpc.go b/pkg/rpc/client/rpc.go index 3bd80382e..0e1344d99 100644 --- a/pkg/rpc/client/rpc.go +++ b/pkg/rpc/client/rpc.go @@ -398,25 +398,22 @@ func (c *Client) SendRawTransaction(rawTX *transaction.Transaction) (util.Uint25 } // SubmitBlock broadcasts a raw block over the NEO network. -func (c *Client) SubmitBlock(b block.Block) error { +func (c *Client) SubmitBlock(b block.Block) (util.Uint256, error) { var ( params request.RawParams - resp bool + resp = new(result.RelayResult) ) buf := io.NewBufBinWriter() b.EncodeBinary(buf.BinWriter) if err := buf.Err; err != nil { - return err + return util.Uint256{}, err } params = request.NewRawParams(hex.EncodeToString(buf.Bytes())) - if err := c.performRequest("submitblock", params, &resp); err != nil { - return err + if err := c.performRequest("submitblock", params, resp); err != nil { + return util.Uint256{}, err } - if !resp { - return errors.New("submitblock returned false") - } - return nil + return resp.Hash, nil } // SignAndPushInvocationTx signs and pushes given script as an invocation diff --git a/pkg/rpc/client/rpc_test.go b/pkg/rpc/client/rpc_test.go index 64c890e8b..35e6e561c 100644 --- a/pkg/rpc/client/rpc_test.go +++ b/pkg/rpc/client/rpc_test.go @@ -716,16 +716,19 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ { name: "positive", invoke: func(c *Client) (interface{}, error) { - return nil, c.SubmitBlock(block.Block{ + return c.SubmitBlock(block.Block{ Base: block.Base{}, Transactions: nil, Trimmed: false, }) }, - serverResponse: `{"jsonrpc":"2.0","id":1,"result":true}`, + serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"hash":"0x1bdea8f80eb5bd97fade38d5e7fb93b02c9d3e01394e9f4324218132293f7ea6"}}`, result: func(c *Client) interface{} { - // no error expected - return nil + h, err := util.Uint256DecodeStringLE("1bdea8f80eb5bd97fade38d5e7fb93b02c9d3e01394e9f4324218132293f7ea6") + if err != nil { + panic(fmt.Errorf("can't decode `submitblock` result hash: %v", err)) + } + return h }, }, }, @@ -840,7 +843,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ { name: "submitblock_bad_server_answer", invoke: func(c *Client) (interface{}, error) { - return nil, c.SubmitBlock(block.Block{ + return c.SubmitBlock(block.Block{ Base: block.Base{}, Transactions: nil, Trimmed: false, @@ -996,7 +999,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ { name: "submitblock_invalid_params_error", invoke: func(c *Client) (interface{}, error) { - return nil, c.SubmitBlock(block.Block{}) + return c.SubmitBlock(block.Block{}) }, }, { @@ -1178,7 +1181,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ { name: "submitblock_unmarshalling_error", invoke: func(c *Client) (interface{}, error) { - return nil, c.SubmitBlock(block.Block{ + return c.SubmitBlock(block.Block{ Base: block.Base{}, Transactions: nil, Trimmed: false, diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index 999b40c30..bac1dfeb8 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -902,7 +902,9 @@ func (s *Server) submitBlock(reqParams request.Params) (interface{}, *response.E return nil, response.ErrValidationFailed } } - return true, nil + return &result.RelayResult{ + Hash: b.Hash(), + }, nil } func (s *Server) sendrawtransaction(reqParams request.Params) (interface{}, *response.Error) { diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index bbf257017..b41b08eba 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -760,9 +760,9 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) [] b := newBlock(t, chain, 1, 0, newTx()) body := doRPCCall(fmt.Sprintf(rpc, encodeBlock(t, b)), httpSrv.URL, t) data := checkErrGetResult(t, body, false) - var res bool - require.NoError(t, json.Unmarshal(data, &res)) - require.True(t, res) + var res = new(result.RelayResult) + require.NoError(t, json.Unmarshal(data, res)) + require.Equal(t, b.Hash(), res.Hash) }) })