forked from TrueCloudLab/neoneo-go
Merge pull request #1216 from nspcc-dev/neo3/rpc/sendrawtransaction
rpc: adjust `sendrawtransaction` and `submitblock` RPC calls
This commit is contained in:
commit
c4cde44543
8 changed files with 70 additions and 48 deletions
|
@ -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())
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,40 +386,34 @@ 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.
|
||||
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
|
||||
|
@ -453,11 +448,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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -712,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
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -830,13 +837,13 @@ 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))
|
||||
},
|
||||
},
|
||||
{
|
||||
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,
|
||||
|
@ -986,13 +993,13 @@ 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{})
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "submitblock_invalid_params_error",
|
||||
invoke: func(c *Client) (interface{}, error) {
|
||||
return nil, c.SubmitBlock(block.Block{})
|
||||
return c.SubmitBlock(block.Block{})
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -1168,13 +1175,13 @@ 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))
|
||||
},
|
||||
},
|
||||
{
|
||||
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,
|
||||
|
|
8
pkg/rpc/response/result/relay_result.go
Normal file
8
pkg/rpc/response/result/relay_result.go
Normal file
|
@ -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"`
|
||||
}
|
|
@ -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) {
|
||||
|
@ -921,7 +923,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:
|
||||
|
|
|
@ -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)
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -756,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)
|
||||
})
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in a new issue