rpc: use core Header for getblockheader response

Nonce and Primary fields were missing from response.
This commit is contained in:
Anna Shaleva 2021-09-09 16:13:59 +03:00
parent db13362e86
commit ed9cdfe667
3 changed files with 61 additions and 45 deletions

View file

@ -264,17 +264,12 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
result: func(c *Client) interface{} { result: func(c *Client) interface{} {
b := getResultBlock1() b := getResultBlock1()
return &result.Header{ return &result.Header{
Hash: b.Hash(), Header: b.Header,
Size: 457, BlockMetadata: result.BlockMetadata{
Version: b.Version, Size: 457,
NextBlockHash: b.NextBlockHash, NextBlockHash: b.NextBlockHash,
PrevBlockHash: b.PrevHash, Confirmations: b.Confirmations,
MerkleRoot: b.MerkleRoot, },
Timestamp: b.Timestamp,
Index: b.Index,
NextConsensus: address.Uint160ToString(b.NextConsensus),
Witnesses: []transaction.Witness{b.Script},
Confirmations: b.Confirmations,
} }
}, },
}, },

View file

@ -1,10 +1,11 @@
package result package result
import ( import (
"encoding/json"
"errors"
"github.com/nspcc-dev/neo-go/pkg/core/block" "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/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/io"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
) )
@ -13,33 +14,19 @@ type (
// Header wrapper used for the representation of // Header wrapper used for the representation of
// block header on the RPC Server. // block header on the RPC Server.
Header struct { Header struct {
Hash util.Uint256 `json:"hash"` block.Header
Size int `json:"size"` BlockMetadata
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"`
} }
) )
// NewHeader creates a new Header wrapper. // NewHeader creates a new Header wrapper.
func NewHeader(h *block.Header, chain blockchainer.Blockchainer) Header { func NewHeader(h *block.Header, chain blockchainer.Blockchainer) Header {
res := Header{ res := Header{
Hash: h.Hash(), Header: *h,
Size: io.GetVarSize(h), BlockMetadata: BlockMetadata{
Version: h.Version, Size: io.GetVarSize(h),
PrevBlockHash: h.PrevHash, Confirmations: chain.BlockHeight() - h.Index + 1,
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,
} }
hash := chain.GetHeaderHash(int(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 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
}

View file

@ -1455,17 +1455,12 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
t.Run("verbose != 0", func(t *testing.T) { t.Run("verbose != 0", func(t *testing.T) {
nextHash := chain.GetHeaderHash(int(hdr.Index) + 1) nextHash := chain.GetHeaderHash(int(hdr.Index) + 1)
expected := &result.Header{ expected := &result.Header{
Hash: hdr.Hash(), Header: *hdr,
Size: io.GetVarSize(hdr), BlockMetadata: result.BlockMetadata{
Version: hdr.Version, Size: io.GetVarSize(hdr),
PrevBlockHash: hdr.PrevHash, NextBlockHash: &nextHash,
MerkleRoot: hdr.MerkleRoot, Confirmations: e.chain.BlockHeight() - hdr.Index + 1,
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,
} }
rpc := fmt.Sprintf(rpc, `["`+testHeaderHash+`", 2]`) rpc := fmt.Sprintf(rpc, `["`+testHeaderHash+`", 2]`)