forked from TrueCloudLab/neoneo-go
parent
d3063c26e1
commit
a746d8e6e6
6 changed files with 108 additions and 1 deletions
|
@ -63,7 +63,7 @@ which would yield the response:
|
||||||
| `invokefunction` | Yes |
|
| `invokefunction` | Yes |
|
||||||
| `invokescript` | Yes |
|
| `invokescript` | Yes |
|
||||||
| `sendrawtransaction` | Yes |
|
| `sendrawtransaction` | Yes |
|
||||||
| `submitblock` | No (#344) |
|
| `submitblock` | Yes |
|
||||||
| `validateaddress` | Yes |
|
| `validateaddress` | Yes |
|
||||||
|
|
||||||
### Unsupported methods
|
### Unsupported methods
|
||||||
|
|
|
@ -391,6 +391,17 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
require.NoError(t, writer.Err)
|
require.NoError(t, writer.Err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Blocks for `submitblock` test. If you are planning to modify test chain from `testblocks.acc`,
|
||||||
|
// please, update params value of `empty block` and `positive` tests.
|
||||||
|
var blocks []*block.Block
|
||||||
|
blocks = append(blocks, bc.newBlock(), bc.newBlock(newMinerTX()))
|
||||||
|
for _, b := range blocks {
|
||||||
|
buf := io.NewBufBinWriter()
|
||||||
|
b.EncodeBinary(buf.BinWriter)
|
||||||
|
require.NoError(t, buf.Err)
|
||||||
|
t.Log(hex.EncodeToString(buf.Bytes()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNEP5Transfer(sc, from, to util.Uint160, amount int64) *transaction.Transaction {
|
func newNEP5Transfer(sc, from, to util.Uint160, amount int64) *transaction.Transaction {
|
||||||
|
|
|
@ -20,6 +20,18 @@ type (
|
||||||
var (
|
var (
|
||||||
// ErrInvalidParams represents a generic 'invalid parameters' error.
|
// ErrInvalidParams represents a generic 'invalid parameters' error.
|
||||||
ErrInvalidParams = NewInvalidParamsError("", nil)
|
ErrInvalidParams = NewInvalidParamsError("", nil)
|
||||||
|
// ErrAlreadyExists represents SubmitError with code -501
|
||||||
|
ErrAlreadyExists = NewSubmitError(-501, "Block or transaction already exists and cannot be sent repeatedly.")
|
||||||
|
// ErrOutOfMemory represents SubmitError with code -502
|
||||||
|
ErrOutOfMemory = NewSubmitError(-502, "The memory pool is full and no more transactions can be sent.")
|
||||||
|
// ErrUnableToVerify represents SubmitError with code -503
|
||||||
|
ErrUnableToVerify = NewSubmitError(-503, "The block cannot be validated.")
|
||||||
|
// ErrValidationFailed represents SubmitError with code -504
|
||||||
|
ErrValidationFailed = NewSubmitError(-504, "Block or transaction validation failed.")
|
||||||
|
// ErrPolicyFail represents SubmitError with code -505
|
||||||
|
ErrPolicyFail = NewSubmitError(-505, "One of the Policy filters failed.")
|
||||||
|
// ErrUnknown represents SubmitError with code -500
|
||||||
|
ErrUnknown = NewSubmitError(-500, "Unknown error.")
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewError is an Error constructor that takes Error contents from its
|
// NewError is an Error constructor that takes Error contents from its
|
||||||
|
@ -71,6 +83,12 @@ func NewRPCError(message string, data string, cause error) *Error {
|
||||||
return NewError(-100, http.StatusUnprocessableEntity, message, data, cause)
|
return NewError(-100, http.StatusUnprocessableEntity, message, data, cause)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewSubmitError creates a new error with
|
||||||
|
// specified error code and error message
|
||||||
|
func NewSubmitError(code int64, message string) *Error {
|
||||||
|
return NewError(code, http.StatusUnprocessableEntity, message, "", nil)
|
||||||
|
}
|
||||||
|
|
||||||
// Error implements the error interface.
|
// Error implements the error interface.
|
||||||
func (e *Error) Error() string {
|
func (e *Error) Error() string {
|
||||||
return fmt.Sprintf("%s (%d) - %s - %s", e.Message, e.Code, e.Data, e.Cause)
|
return fmt.Sprintf("%s (%d) - %s - %s", e.Message, e.Code, e.Data, e.Cause)
|
||||||
|
|
|
@ -179,6 +179,14 @@ var (
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
submitblockCalled = prometheus.NewCounter(
|
||||||
|
prometheus.CounterOpts{
|
||||||
|
Help: "Number of calls to submitblock rpc endpoint",
|
||||||
|
Name: "submitblock_called",
|
||||||
|
Namespace: "neogo",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
getstorageCalled = prometheus.NewCounter(
|
getstorageCalled = prometheus.NewCounter(
|
||||||
prometheus.CounterOpts{
|
prometheus.CounterOpts{
|
||||||
Help: "Number of calls to getstorage rpc endpoint",
|
Help: "Number of calls to getstorage rpc endpoint",
|
||||||
|
@ -209,6 +217,7 @@ func init() {
|
||||||
gettxoutCalled,
|
gettxoutCalled,
|
||||||
getrawtransactionCalled,
|
getrawtransactionCalled,
|
||||||
sendrawtransactionCalled,
|
sendrawtransactionCalled,
|
||||||
|
submitblockCalled,
|
||||||
getstorageCalled,
|
getstorageCalled,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/config"
|
"github.com/nspcc-dev/neo-go/config"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core"
|
"github.com/nspcc-dev/neo-go/pkg/core"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||||
"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/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"
|
||||||
|
@ -302,6 +303,10 @@ Methods:
|
||||||
case "invokescript":
|
case "invokescript":
|
||||||
results, resultsErr = s.invokescript(reqParams)
|
results, resultsErr = s.invokescript(reqParams)
|
||||||
|
|
||||||
|
case "submitblock":
|
||||||
|
submitblockCalled.Inc()
|
||||||
|
results, resultsErr = s.submitBlock(reqParams)
|
||||||
|
|
||||||
case "sendrawtransaction":
|
case "sendrawtransaction":
|
||||||
sendrawtransactionCalled.Inc()
|
sendrawtransactionCalled.Inc()
|
||||||
results, resultsErr = s.sendrawtransaction(reqParams)
|
results, resultsErr = s.sendrawtransaction(reqParams)
|
||||||
|
@ -808,6 +813,34 @@ func (s *Server) runScriptInVM(script []byte) *result.Invoke {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// submitBlock broadcasts a raw block over the NEO network.
|
||||||
|
func (s *Server) submitBlock(reqParams request.Params) (interface{}, error) {
|
||||||
|
param, ok := reqParams.ValueWithType(0, request.StringT)
|
||||||
|
if !ok {
|
||||||
|
return nil, response.ErrInvalidParams
|
||||||
|
}
|
||||||
|
blockBytes, err := param.GetBytesHex()
|
||||||
|
if err != nil {
|
||||||
|
return nil, response.ErrInvalidParams
|
||||||
|
}
|
||||||
|
b := block.Block{}
|
||||||
|
r := io.NewBinReaderFromBuf(blockBytes)
|
||||||
|
b.DecodeBinary(r)
|
||||||
|
if r.Err != nil {
|
||||||
|
return nil, response.ErrInvalidParams
|
||||||
|
}
|
||||||
|
err = s.chain.AddBlock(&b)
|
||||||
|
if err != nil {
|
||||||
|
switch err {
|
||||||
|
case core.ErrInvalidBlockIndex, core.ErrAlreadyExists:
|
||||||
|
return nil, response.ErrAlreadyExists
|
||||||
|
default:
|
||||||
|
return nil, response.ErrValidationFailed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) sendrawtransaction(reqParams request.Params) (interface{}, error) {
|
func (s *Server) sendrawtransaction(reqParams request.Params) (interface{}, error) {
|
||||||
var resultsErr error
|
var resultsErr error
|
||||||
var results interface{}
|
var results interface{}
|
||||||
|
|
|
@ -742,6 +742,42 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
fail: true,
|
fail: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"submitblock": {
|
||||||
|
{
|
||||||
|
name: "empty block",
|
||||||
|
params: `["00000000270dd14a8ddb4961cada75e9ec4cce906f9feeaef21b1d6cea5b2f0230baf92e00000000000000000000000000000000000000000000000000000000000000009f0e625ed10000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd040140bd2b961ca7df75d6d8896fd4ef487128ddd1ca9feda9cb09da58a6a24607fc71cd572ba072e4ec9d9847c7da6a33fc44dc9a64208fd62851d27d330012bd0bf640ee6e92653789b0d1c87e0cd485c5bbd84194479995930567df9ffec7ab370c965df320134632e53d139a785840cecb16c4fe801f3c6bed17a9dd83460f5f297440fbe5f9d3cc23f9c7b9f10e191eae541fcb71eb03799c09886aa04c0bc43e98c2c91686a5b4fb988c8855f4d217807f01ca9a61bc0d5536eb3149dce7ae66965c407af69085454fb39f0c27cf308219c09efbe902f0a092a065b38864c97529f1dd12fa54c346e8d9482106c7154b3170c150887170c78fe78a5c70e3956880489c8b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae00"]`,
|
||||||
|
fail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid block height",
|
||||||
|
params: `["000000005fb86f62eafe8e9246bc0d1648e4e5c8389dee9fb7fe03fcc6772ec8c5e4ec2aedb908054ac1409be5f77d5369c6e03490b2f6676d68d0b3370f8159e0fdadf99bc05f5e030000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd0401406f299c82b513f59f5bd120317974852c9694c6e10db1ef2f1bb848b1a33e47a08f8dc03ee784166b2060a94cd4e7af88899b39787938f7f2763ea4d2182776ed40f3bafd85214fef38a4836ca97793001ea411f553c51e88781f7b916c59c145bff28314b6e7ea246789422a996fc4937e290a1b40f6b97c5222540f65b0d47aca40d2b3d19203d456428bfdb529e846285052105957385b65388b9a617f6e2d56a64ec41aa73439eafccb52987bb1975c9b67518b053d9e61b445e4a3377dbc206640bd688489bd62adf6bed9d61a73905b9591eb87053c6f0f4dd70f3bee7295541b490caef044b55b6f9f01dc4a05a756a3f2edd06f5adcbe4e984c1e552f9023f08b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae0100000000000000000000"]`,
|
||||||
|
fail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid hex",
|
||||||
|
params: `["000000005gb86f62eafe8e9246bc0d1648e4e5c8389dee9fb7fe03fcc6772ec8c5e4ec2aedb908054ac1409be5f77d5369c6e03490b2f6676d68d0b3370f8159e0fdadf99bc05f5e030000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd0401406f299c82b513f59f5bd120317974852c9694c6e10db1ef2f1bb848b1a33e47a08f8dc03ee784166b2060a94cd4e7af88899b39787938f7f2763ea4d2182776ed40f3bafd85214fef38a4836ca97793001ea411f553c51e88781f7b916c59c145bff28314b6e7ea246789422a996fc4937e290a1b40f6b97c5222540f65b0d47aca40d2b3d19203d456428bfdb529e846285052105957385b65388b9a617f6e2d56a64ec41aa73439eafccb52987bb1975c9b67518b053d9e61b445e4a3377dbc206640bd688489bd62adf6bed9d61a73905b9591eb87053c6f0f4dd70f3bee7295541b490caef044b55b6f9f01dc4a05a756a3f2edd06f5adcbe4e984c1e552f9023f08b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae0100000000000000000000"]`,
|
||||||
|
fail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid block bytes",
|
||||||
|
params: `["0000000027"]`,
|
||||||
|
fail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no params",
|
||||||
|
params: `[]`,
|
||||||
|
fail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "positive",
|
||||||
|
// If you are planning to modify test chain from `testblocks.acc`, please, update param value
|
||||||
|
params: `["00000000270dd14a8ddb4961cada75e9ec4cce906f9feeaef21b1d6cea5b2f0230baf92eedb908054ac1409be5f77d5369c6e03490b2f6676d68d0b3370f8159e0fdadf9b93a615ed10000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd0401402dca64bfc20107819171fab7c636427e9634a58f560ff9ef94ff9005a82509dd5e1b054d195201013a8477529d023d794a3ca6efa717f5d7e541e3b81fbabff840b5395429f0da5a8d1023907dca3771c02eca31e520e1acc2851b373a6aedd5bf6ba75a80b0949ee0794156ae48356b98e761143b90ebaa816ca4b0b0f91b38ab40a6feb77e09c0c95c6f2c6571155843f388e1f7cb7ba5af2bc235bac1d57a8c316d817e54895bfdb98b9c34ed9550e7ccff2a06b46ca0f2b99ba720368d9934eb40dbbdc94154cc304296ccda73e4e0257cdc344c4bad4c70f419f59f5d6d862819cead91c55e73e7c30daff2cd38d74eae3e0e49a5226de3060843d0e3b9262dc08b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae0100000000000000000000"]`,
|
||||||
|
result: func(e *executor) interface{} {
|
||||||
|
v := true
|
||||||
|
return &v
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
"validateaddress": {
|
"validateaddress": {
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
|
|
Loading…
Reference in a new issue