Merge pull request #2165 from nspcc-dev/rpc/audit
rpc: request handlers audit
This commit is contained in:
commit
c4637514d4
9 changed files with 84 additions and 49 deletions
|
@ -88,6 +88,11 @@ feature is not supported by the C# node.
|
|||
It's possible to get non-native contract state by its ID, unlike with C# node where
|
||||
it only works for native contracts.
|
||||
|
||||
##### `getrawtransaction`
|
||||
|
||||
VM state is included to verbose response along with other transaction fields if
|
||||
the transaction is already on chain.
|
||||
|
||||
##### `getstorage`
|
||||
|
||||
This method doesn't work for the Ledger contract, you can get data via regular
|
||||
|
|
|
@ -157,7 +157,7 @@ func (b Header) MarshalJSON() ([]byte, error) {
|
|||
PrevHash: b.PrevHash,
|
||||
MerkleRoot: b.MerkleRoot,
|
||||
Timestamp: b.Timestamp,
|
||||
Nonce: fmt.Sprintf("%016x", b.Nonce),
|
||||
Nonce: fmt.Sprintf("%016X", b.Nonce),
|
||||
Index: b.Index,
|
||||
PrimaryIndex: b.PrimaryIndex,
|
||||
NextConsensus: address.Uint160ToString(b.NextConsensus),
|
||||
|
|
|
@ -140,6 +140,7 @@ func NewContractMD(name string, id int32) *ContractMD {
|
|||
// Therefore values are taken from C# node.
|
||||
c.NEF.Header.Compiler = "neo-core-v3.0"
|
||||
c.NEF.Header.Magic = nef.Magic
|
||||
c.NEF.Tokens = []nef.MethodToken{} // avoid `nil` result during JSON marshalling
|
||||
c.Hash = state.CreateContractHash(util.Uint160{}, 0, c.Name)
|
||||
c.Manifest = *manifest.DefaultManifest(name)
|
||||
|
||||
|
|
|
@ -294,6 +294,9 @@ func (c *nep17TokenNative) addTokens(ic *interop.Context, h util.Uint160, amount
|
|||
}
|
||||
|
||||
func newDescriptor(name string, ret smartcontract.ParamType, ps ...manifest.Parameter) *manifest.Method {
|
||||
if len(ps) == 0 {
|
||||
ps = []manifest.Parameter{}
|
||||
}
|
||||
return &manifest.Method{
|
||||
Name: name,
|
||||
Parameters: ps,
|
||||
|
|
|
@ -264,17 +264,12 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
result: func(c *Client) interface{} {
|
||||
b := getResultBlock1()
|
||||
return &result.Header{
|
||||
Hash: b.Hash(),
|
||||
Size: 457,
|
||||
Version: b.Version,
|
||||
NextBlockHash: b.NextBlockHash,
|
||||
PrevBlockHash: b.PrevHash,
|
||||
MerkleRoot: b.MerkleRoot,
|
||||
Timestamp: b.Timestamp,
|
||||
Index: b.Index,
|
||||
NextConsensus: address.Uint160ToString(b.NextConsensus),
|
||||
Witnesses: []transaction.Witness{b.Script},
|
||||
Confirmations: b.Confirmations,
|
||||
Header: b.Header,
|
||||
BlockMetadata: result.BlockMetadata{
|
||||
Size: 457,
|
||||
NextBlockHash: b.NextBlockHash,
|
||||
Confirmations: b.Confirmations,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package result
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/blockchainer"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
)
|
||||
|
@ -13,33 +14,19 @@ type (
|
|||
// Header wrapper used for the representation of
|
||||
// block header on the RPC Server.
|
||||
Header struct {
|
||||
Hash util.Uint256 `json:"hash"`
|
||||
Size int `json:"size"`
|
||||
Version uint32 `json:"version"`
|
||||
PrevBlockHash util.Uint256 `json:"previousblockhash"`
|
||||
MerkleRoot util.Uint256 `json:"merkleroot"`
|
||||
Timestamp uint64 `json:"time"`
|
||||
Index uint32 `json:"index"`
|
||||
NextConsensus string `json:"nextconsensus"`
|
||||
Witnesses []transaction.Witness `json:"witnesses"`
|
||||
Confirmations uint32 `json:"confirmations"`
|
||||
NextBlockHash *util.Uint256 `json:"nextblockhash,omitempty"`
|
||||
block.Header
|
||||
BlockMetadata
|
||||
}
|
||||
)
|
||||
|
||||
// NewHeader creates a new Header wrapper.
|
||||
func NewHeader(h *block.Header, chain blockchainer.Blockchainer) Header {
|
||||
res := Header{
|
||||
Hash: h.Hash(),
|
||||
Size: io.GetVarSize(h),
|
||||
Version: h.Version,
|
||||
PrevBlockHash: h.PrevHash,
|
||||
MerkleRoot: h.MerkleRoot,
|
||||
Timestamp: h.Timestamp,
|
||||
Index: h.Index,
|
||||
NextConsensus: address.Uint160ToString(h.NextConsensus),
|
||||
Witnesses: []transaction.Witness{h.Script},
|
||||
Confirmations: chain.BlockHeight() - h.Index + 1,
|
||||
Header: *h,
|
||||
BlockMetadata: BlockMetadata{
|
||||
Size: io.GetVarSize(h),
|
||||
Confirmations: chain.BlockHeight() - h.Index + 1,
|
||||
},
|
||||
}
|
||||
|
||||
hash := chain.GetHeaderHash(int(h.Index) + 1)
|
||||
|
@ -48,3 +35,42 @@ func NewHeader(h *block.Header, chain blockchainer.Blockchainer) Header {
|
|||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// MarshalJSON implements json.Marshaler interface.
|
||||
func (h Header) MarshalJSON() ([]byte, error) {
|
||||
output, err := json.Marshal(h.BlockMetadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
baseBytes, err := json.Marshal(h.Header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We have to keep both "fields" at the same level in json in order to
|
||||
// match C# API, so there's no way to marshall Block correctly with
|
||||
// standard json.Marshaller tool.
|
||||
if output[len(output)-1] != '}' || baseBytes[0] != '{' {
|
||||
return nil, errors.New("can't merge internal jsons")
|
||||
}
|
||||
output[len(output)-1] = ','
|
||||
output = append(output, baseBytes[1:]...)
|
||||
return output, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler interface.
|
||||
func (h *Header) UnmarshalJSON(data []byte) error {
|
||||
// As block.Block and BlockMetadata are at the same level in json,
|
||||
// do unmarshalling separately for both structs.
|
||||
meta := new(BlockMetadata)
|
||||
err := json.Unmarshal(data, meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal(data, &h.Header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.BlockMetadata = *meta
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -548,8 +548,9 @@ func (s *Server) getRawMempool(reqParams request.Params) (interface{}, *response
|
|||
return hashList, nil
|
||||
}
|
||||
return result.RawMempool{
|
||||
Height: s.chain.BlockHeight(),
|
||||
Verified: hashList,
|
||||
Height: s.chain.BlockHeight(),
|
||||
Verified: hashList,
|
||||
Unverified: []util.Uint256{}, // avoid `null` result
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -1280,11 +1281,12 @@ func (s *Server) invokescript(reqParams request.Params) (interface{}, *response.
|
|||
|
||||
tx := &transaction.Transaction{}
|
||||
if len(reqParams) > 1 {
|
||||
signers, _, err := reqParams[1].GetSignersWithWitnesses()
|
||||
signers, witnesses, err := reqParams[1].GetSignersWithWitnesses()
|
||||
if err != nil {
|
||||
return nil, response.ErrInvalidParams
|
||||
}
|
||||
tx.Signers = signers
|
||||
tx.Scripts = witnesses
|
||||
}
|
||||
if len(tx.Signers) == 0 {
|
||||
tx.Signers = []transaction.Signer{{Account: util.Uint160{}, Scopes: transaction.None}}
|
||||
|
|
|
@ -1455,17 +1455,12 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
|
|||
t.Run("verbose != 0", func(t *testing.T) {
|
||||
nextHash := chain.GetHeaderHash(int(hdr.Index) + 1)
|
||||
expected := &result.Header{
|
||||
Hash: hdr.Hash(),
|
||||
Size: io.GetVarSize(hdr),
|
||||
Version: hdr.Version,
|
||||
PrevBlockHash: hdr.PrevHash,
|
||||
MerkleRoot: hdr.MerkleRoot,
|
||||
Timestamp: hdr.Timestamp,
|
||||
Index: hdr.Index,
|
||||
NextConsensus: address.Uint160ToString(hdr.NextConsensus),
|
||||
Witnesses: []transaction.Witness{hdr.Script},
|
||||
Confirmations: e.chain.BlockHeight() - hdr.Index + 1,
|
||||
NextBlockHash: &nextHash,
|
||||
Header: *hdr,
|
||||
BlockMetadata: result.BlockMetadata{
|
||||
Size: io.GetVarSize(hdr),
|
||||
NextBlockHash: &nextHash,
|
||||
Confirmations: e.chain.BlockHeight() - hdr.Index + 1,
|
||||
},
|
||||
}
|
||||
|
||||
rpc := fmt.Sprintf(rpc, `["`+testHeaderHash+`", 2]`)
|
||||
|
|
|
@ -69,6 +69,14 @@ func TestEncodeDecodeBinary(t *testing.T) {
|
|||
expected.Header.Magic = Magic
|
||||
testserdes.EncodeDecodeBinary(t, expected, &File{})
|
||||
})
|
||||
t.Run("positive with empty tokens", func(t *testing.T) {
|
||||
expected.Script = script
|
||||
// Check `Tokens` won't be deserialized to `nil`. We expect them to be non-nil slice in the related code.
|
||||
expected.Tokens = []MethodToken{}
|
||||
expected.Checksum = expected.CalculateChecksum()
|
||||
expected.Header.Magic = Magic
|
||||
testserdes.EncodeDecodeBinary(t, expected, &File{})
|
||||
})
|
||||
t.Run("invalid reserved bytes", func(t *testing.T) {
|
||||
expected.Script = script
|
||||
expected.Tokens = expected.Tokens[:0]
|
||||
|
|
Loading…
Reference in a new issue