mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-29 23:33:37 +00:00
rpc/block: rework the way Block is JSONized
Our block.Block was JSONized in a bit different fashion than result.Block in its NextConsensus and Index fields. It's not good for notifications because third-party clients would probably expect to see the same format. Also, using completely different Block representation is probably making our client a bit weaker as this representation is harder to use with other neo-go components. So use the same approach we took for Transactions and wrap block.Block which is to be serialized in proper way. Fix `Script` JSONization along the way, 3.0 node wraps it within `witnesses`.
This commit is contained in:
parent
393ce1c230
commit
7633439845
9 changed files with 296 additions and 102 deletions
|
@ -1,6 +1,7 @@
|
||||||
package block
|
package block
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/Workiva/go-datastructures/queue"
|
"github.com/Workiva/go-datastructures/queue"
|
||||||
|
@ -19,10 +20,16 @@ type Block struct {
|
||||||
ConsensusData ConsensusData `json:"consensus_data"`
|
ConsensusData ConsensusData `json:"consensus_data"`
|
||||||
|
|
||||||
// Transaction list.
|
// Transaction list.
|
||||||
Transactions []*transaction.Transaction `json:"tx"`
|
Transactions []*transaction.Transaction
|
||||||
|
|
||||||
// True if this block is created from trimmed data.
|
// True if this block is created from trimmed data.
|
||||||
Trimmed bool `json:"-"`
|
Trimmed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// auxBlock is used for JSON i/o.
|
||||||
|
type auxBlock struct {
|
||||||
|
ConsensusData ConsensusData `json:"consensus_data"`
|
||||||
|
Transactions []*transaction.Transaction `json:"tx"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns the Header of the Block.
|
// Header returns the Header of the Block.
|
||||||
|
@ -179,3 +186,46 @@ func (b *Block) Compare(item queue.Item) int {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements json.Marshaler interface.
|
||||||
|
func (b Block) MarshalJSON() ([]byte, error) {
|
||||||
|
auxb, err := json.Marshal(auxBlock{
|
||||||
|
ConsensusData: b.ConsensusData,
|
||||||
|
Transactions: b.Transactions,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
baseBytes, err := json.Marshal(b.Base)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stitch them together.
|
||||||
|
if baseBytes[len(baseBytes)-1] != '}' || auxb[0] != '{' {
|
||||||
|
return nil, errors.New("can't merge internal jsons")
|
||||||
|
}
|
||||||
|
baseBytes[len(baseBytes)-1] = ','
|
||||||
|
baseBytes = append(baseBytes, auxb[1:]...)
|
||||||
|
return baseBytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements json.Unmarshaler interface.
|
||||||
|
func (b *Block) UnmarshalJSON(data []byte) error {
|
||||||
|
// As Base and auxb are at the same level in json,
|
||||||
|
// do unmarshalling separately for both structs.
|
||||||
|
auxb := new(auxBlock)
|
||||||
|
err := json.Unmarshal(data, auxb)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
base := new(Base)
|
||||||
|
err = json.Unmarshal(data, base)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.Base = *base
|
||||||
|
b.Transactions = auxb.Transactions
|
||||||
|
b.ConsensusData = auxb.ConsensusData
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package block
|
package block
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"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"
|
||||||
|
"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"
|
||||||
)
|
)
|
||||||
|
@ -12,31 +15,31 @@ import (
|
||||||
// Base holds the base info of a block
|
// Base holds the base info of a block
|
||||||
type Base struct {
|
type Base struct {
|
||||||
// Version of the block.
|
// Version of the block.
|
||||||
Version uint32 `json:"version"`
|
Version uint32
|
||||||
|
|
||||||
// hash of the previous block.
|
// hash of the previous block.
|
||||||
PrevHash util.Uint256 `json:"previousblockhash"`
|
PrevHash util.Uint256
|
||||||
|
|
||||||
// Root hash of a transaction list.
|
// Root hash of a transaction list.
|
||||||
MerkleRoot util.Uint256 `json:"merkleroot"`
|
MerkleRoot util.Uint256
|
||||||
|
|
||||||
// Timestamp is a millisecond-precision timestamp.
|
// Timestamp is a millisecond-precision timestamp.
|
||||||
// The time stamp of each block must be later than previous block's time stamp.
|
// The time stamp of each block must be later than previous block's time stamp.
|
||||||
// Generally the difference of two block's time stamp is about 15 seconds and imprecision is allowed.
|
// Generally the difference of two block's time stamp is about 15 seconds and imprecision is allowed.
|
||||||
// The height of the block must be exactly equal to the height of the previous block plus 1.
|
// The height of the block must be exactly equal to the height of the previous block plus 1.
|
||||||
Timestamp uint64 `json:"time"`
|
Timestamp uint64
|
||||||
|
|
||||||
// index/height of the block
|
// index/height of the block
|
||||||
Index uint32 `json:"height"`
|
Index uint32
|
||||||
|
|
||||||
// Contract address of the next miner
|
// Contract address of the next miner
|
||||||
NextConsensus util.Uint160 `json:"next_consensus"`
|
NextConsensus util.Uint160
|
||||||
|
|
||||||
// Padding that is fixed to 1
|
// Padding that is fixed to 1
|
||||||
_ uint8
|
_ uint8
|
||||||
|
|
||||||
// Script used to validate the block
|
// Script used to validate the block
|
||||||
Script transaction.Witness `json:"script"`
|
Script transaction.Witness
|
||||||
|
|
||||||
// Hash of this block, created when binary encoded (double SHA256).
|
// Hash of this block, created when binary encoded (double SHA256).
|
||||||
hash util.Uint256
|
hash util.Uint256
|
||||||
|
@ -45,6 +48,20 @@ type Base struct {
|
||||||
verificationHash util.Uint256
|
verificationHash util.Uint256
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// baseAux is used to marshal/unmarshal to/from JSON, it's almost the same
|
||||||
|
// as original Base, but with Nonce and NextConsensus fields differing and
|
||||||
|
// Hash added.
|
||||||
|
type baseAux struct {
|
||||||
|
Hash util.Uint256 `json:"hash"`
|
||||||
|
Version uint32 `json:"version"`
|
||||||
|
PrevHash 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"`
|
||||||
|
}
|
||||||
|
|
||||||
// Verify verifies the integrity of the Base.
|
// Verify verifies the integrity of the Base.
|
||||||
func (b *Base) Verify() bool {
|
func (b *Base) Verify() bool {
|
||||||
// TODO: Need a persisted blockchain for this.
|
// TODO: Need a persisted blockchain for this.
|
||||||
|
@ -136,3 +153,48 @@ func (b *Base) decodeHashableFields(br *io.BinReader) {
|
||||||
b.createHash()
|
b.createHash()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements json.Marshaler interface.
|
||||||
|
func (b Base) MarshalJSON() ([]byte, error) {
|
||||||
|
aux := baseAux{
|
||||||
|
Hash: b.Hash(),
|
||||||
|
Version: b.Version,
|
||||||
|
PrevHash: b.PrevHash,
|
||||||
|
MerkleRoot: b.MerkleRoot,
|
||||||
|
Timestamp: b.Timestamp,
|
||||||
|
Index: b.Index,
|
||||||
|
NextConsensus: address.Uint160ToString(b.NextConsensus),
|
||||||
|
Witnesses: []transaction.Witness{b.Script},
|
||||||
|
}
|
||||||
|
return json.Marshal(aux)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements json.Unmarshaler interface.
|
||||||
|
func (b *Base) UnmarshalJSON(data []byte) error {
|
||||||
|
var aux = new(baseAux)
|
||||||
|
var nextC util.Uint160
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, aux)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
nextC, err = address.StringToUint160(aux.NextConsensus)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(aux.Witnesses) != 1 {
|
||||||
|
return errors.New("wrong number of witnesses")
|
||||||
|
}
|
||||||
|
b.Version = aux.Version
|
||||||
|
b.PrevHash = aux.PrevHash
|
||||||
|
b.MerkleRoot = aux.MerkleRoot
|
||||||
|
b.Timestamp = aux.Timestamp
|
||||||
|
b.Index = aux.Index
|
||||||
|
b.NextConsensus = nextC
|
||||||
|
b.Script = aux.Witnesses[0]
|
||||||
|
if !aux.Hash.Equals(b.Hash()) {
|
||||||
|
return errors.New("json 'hash' doesn't match block hash")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -172,6 +172,8 @@ func TestBinBlockDecodeEncode(t *testing.T) {
|
||||||
data, err := testserdes.EncodeBinary(&b)
|
data, err := testserdes.EncodeBinary(&b)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, rawtx, hex.EncodeToString(data))
|
assert.Equal(t, rawtx, hex.EncodeToString(data))
|
||||||
|
|
||||||
|
testserdes.MarshalUnmarshalJSON(t, &b, new(Block))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBlockSizeCalculation(t *testing.T) {
|
func TestBlockSizeCalculation(t *testing.T) {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package block
|
package block
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
"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"
|
||||||
|
@ -9,13 +12,19 @@ import (
|
||||||
// ConsensusData represents primary index and nonce of block in the chain.
|
// ConsensusData represents primary index and nonce of block in the chain.
|
||||||
type ConsensusData struct {
|
type ConsensusData struct {
|
||||||
// Primary index
|
// Primary index
|
||||||
PrimaryIndex uint32 `json:"primary"`
|
PrimaryIndex uint32
|
||||||
// Random number
|
// Random number
|
||||||
Nonce uint64 `json:"nonce"`
|
Nonce uint64
|
||||||
// Hash of the ConsensusData (single SHA256)
|
// Hash of the ConsensusData (single SHA256)
|
||||||
hash util.Uint256
|
hash util.Uint256
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// jsonConsensusData is used for JSON I/O of ConsensusData.
|
||||||
|
type jsonConsensusData struct {
|
||||||
|
Primary uint32 `json:"primary"`
|
||||||
|
Nonce string `json:"nonce"`
|
||||||
|
}
|
||||||
|
|
||||||
// DecodeBinary implements Serializable interface.
|
// DecodeBinary implements Serializable interface.
|
||||||
func (c *ConsensusData) DecodeBinary(br *io.BinReader) {
|
func (c *ConsensusData) DecodeBinary(br *io.BinReader) {
|
||||||
c.PrimaryIndex = uint32(br.ReadVarUint())
|
c.PrimaryIndex = uint32(br.ReadVarUint())
|
||||||
|
@ -50,3 +59,28 @@ func (c *ConsensusData) createHash() error {
|
||||||
c.hash = hash.Sha256(b)
|
c.hash = hash.Sha256(b)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements json.Marshaler interface.
|
||||||
|
func (c ConsensusData) MarshalJSON() ([]byte, error) {
|
||||||
|
nonce := strconv.FormatUint(c.Nonce, 16)
|
||||||
|
for len(nonce) < 16 {
|
||||||
|
nonce = "0" + nonce
|
||||||
|
}
|
||||||
|
return json.Marshal(jsonConsensusData{Primary: c.PrimaryIndex, Nonce: nonce})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements json.Unmarshaler interface.
|
||||||
|
func (c *ConsensusData) UnmarshalJSON(data []byte) error {
|
||||||
|
jcd := new(jsonConsensusData)
|
||||||
|
err := json.Unmarshal(data, jcd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nonce, err := strconv.ParseUint(jcd.Nonce, 16, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.PrimaryIndex = jcd.Primary
|
||||||
|
c.Nonce = nonce
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package client
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -156,12 +157,8 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
invoke: func(c *Client) (i interface{}, err error) {
|
invoke: func(c *Client) (i interface{}, err error) {
|
||||||
return c.GetBlockByIndexVerbose(202)
|
return c.GetBlockByIndexVerbose(202)
|
||||||
},
|
},
|
||||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0xcbb73ed9e31dc41a8a222749de475e6ebc2a73b99f73b091a72e0b146110fe86","size":781,"version":0,"nextblockhash":"0x13283c93aec07dc90be3ddd65e2de15e9212f1b3205303f688d6df85129f6b22","previousblockhash":"0x93b540424c1173e487a47582a652686b2885f959ffd895b30e184842403990ef","merkleroot":"0xb8e923148dede20901d6fb225579f6d430cc58f24461d1b0f860ee32abbfcc8d","time":1589300496,"index":202,"consensus_data":{"primary":0,"nonce":"0000000000000457"},"nextconsensus":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","confirmations":6,"script":{"invocation":"0c403620ef8f02d7884c553fb6c54d2fe717cfddd9450886c5fc88a669a29a82fa1a7c715076996567a5a56747f20f10d7e4db071d73b306ccbf17f9a916fcfa1d020c4099e27d87bbb3fb4ce1c77dca85cf3eac46c9c3de87d8022ef7ad2b0a2bb980339293849cf85e5a0a5615ea7bc5bb0a7f28e31f278dc19d628f64c49b888df4c60c40616eefc9286843c2f3f2cf1815988356e409b3f10ffaf60b3468dc0a92dd929cbc8d5da74052c303e7474412f6beaddd551e9056c4e7a5fccdc06107e48f3fe10c40fd2d25d4156e969345c0522669b509e5ced70e4265066eadaf85eea3919d5ded525f8f52d6f0dfa0186c964dd0302fca5bc2dc0540b4ed21085be478c3123996","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"},"tx":[{"txid":"0x96ef00d2efe03101f5b302f7fc3c8fcd22688944bdc83ab99071d77edbb08581","size":254,"type":"ContractTransaction","version":0,"nonce":3,"sender":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","sys_fee":"0","net_fee":"0","valid_until_block":1200,"attributes":[],"cosigners":[],"vin":[{"txid":"0x33e045101301854a0e07ff96a92ca1ba9b23c19501f1b7eb15ae9eea07b5f370","vout":0}],"vout":[{"address":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","asset":"0x1a5e0e3eac2abced7de9ee2de0820a5c85e63756fcdfc29b82fead86a7c07c78","n":0,"value":"99999000"}],"scripts":[{"invocation":"0c402caebbee911a1f159aa05ab40093d086090a817e837f3f87e8b3e47f6b083649137770f6dda0349ddd611bc47402aca457a89b3b7b0076307ab6a47fd57048eb","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"}]}]}}`,
|
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0xcbb73ed9e31dc41a8a222749de475e6ebc2a73b99f73b091a72e0b146110fe86","size":781,"version":0,"nextblockhash":"0x13283c93aec07dc90be3ddd65e2de15e9212f1b3205303f688d6df85129f6b22","previousblockhash":"0x93b540424c1173e487a47582a652686b2885f959ffd895b30e184842403990ef","merkleroot":"0xb8e923148dede20901d6fb225579f6d430cc58f24461d1b0f860ee32abbfcc8d","time":1589300496,"index":202,"consensus_data":{"primary":0,"nonce":"0000000000000457"},"nextconsensus":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","confirmations":6,"witnesses":[{"invocation":"0c403620ef8f02d7884c553fb6c54d2fe717cfddd9450886c5fc88a669a29a82fa1a7c715076996567a5a56747f20f10d7e4db071d73b306ccbf17f9a916fcfa1d020c4099e27d87bbb3fb4ce1c77dca85cf3eac46c9c3de87d8022ef7ad2b0a2bb980339293849cf85e5a0a5615ea7bc5bb0a7f28e31f278dc19d628f64c49b888df4c60c40616eefc9286843c2f3f2cf1815988356e409b3f10ffaf60b3468dc0a92dd929cbc8d5da74052c303e7474412f6beaddd551e9056c4e7a5fccdc06107e48f3fe10c40fd2d25d4156e969345c0522669b509e5ced70e4265066eadaf85eea3919d5ded525f8f52d6f0dfa0186c964dd0302fca5bc2dc0540b4ed21085be478c3123996","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"}],"tx":[{"txid":"0x96ef00d2efe03101f5b302f7fc3c8fcd22688944bdc83ab99071d77edbb08581","size":254,"type":"ContractTransaction","version":0,"nonce":3,"sender":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","sys_fee":"0","net_fee":"0","valid_until_block":1200,"attributes":[],"cosigners":[],"vin":[{"txid":"0x33e045101301854a0e07ff96a92ca1ba9b23c19501f1b7eb15ae9eea07b5f370","vout":0}],"vout":[{"address":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","asset":"0x1a5e0e3eac2abced7de9ee2de0820a5c85e63756fcdfc29b82fead86a7c07c78","n":0,"value":"99999000"}],"scripts":[{"invocation":"0c402caebbee911a1f159aa05ab40093d086090a817e837f3f87e8b3e47f6b083649137770f6dda0349ddd611bc47402aca457a89b3b7b0076307ab6a47fd57048eb","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"}]}]}}`,
|
||||||
result: func(c *Client) interface{} {
|
result: func(c *Client) interface{} {
|
||||||
hash, err := util.Uint256DecodeStringLE("cbb73ed9e31dc41a8a222749de475e6ebc2a73b99f73b091a72e0b146110fe86")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
nextBlockHash, err := util.Uint256DecodeStringLE("13283c93aec07dc90be3ddd65e2de15e9212f1b3205303f688d6df85129f6b22")
|
nextBlockHash, err := util.Uint256DecodeStringLE("13283c93aec07dc90be3ddd65e2de15e9212f1b3205303f688d6df85129f6b22")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -227,28 +224,47 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var nonce uint64
|
||||||
|
i, err := fmt.Sscanf("0000000000000457", "%016x", &nonce)
|
||||||
|
if i != 1 {
|
||||||
|
panic("can't decode nonce")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
nextCon, err := address.StringToUint160("AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
blck := &block.Block{
|
||||||
|
Base: block.Base{
|
||||||
|
Version: 0,
|
||||||
|
PrevHash: prevBlockHash,
|
||||||
|
MerkleRoot: merkleRoot,
|
||||||
|
Timestamp: 1589300496,
|
||||||
|
Index: 202,
|
||||||
|
NextConsensus: nextCon,
|
||||||
|
Script: transaction.Witness{
|
||||||
|
InvocationScript: invScript,
|
||||||
|
VerificationScript: verifScript,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ConsensusData: block.ConsensusData{
|
||||||
|
PrimaryIndex: 0,
|
||||||
|
Nonce: nonce,
|
||||||
|
},
|
||||||
|
Transactions: []*transaction.Transaction{tx},
|
||||||
|
}
|
||||||
// Update hashes for correct result comparison.
|
// Update hashes for correct result comparison.
|
||||||
_ = tx.Hash()
|
_ = tx.Hash()
|
||||||
|
_ = blck.Hash()
|
||||||
return &result.Block{
|
return &result.Block{
|
||||||
Hash: hash,
|
Block: blck,
|
||||||
Size: 781,
|
BlockMetadata: result.BlockMetadata{
|
||||||
Version: 0,
|
Size: 781,
|
||||||
NextBlockHash: &nextBlockHash,
|
Confirmations: 6,
|
||||||
PreviousBlockHash: prevBlockHash,
|
NextBlockHash: &nextBlockHash,
|
||||||
MerkleRoot: merkleRoot,
|
|
||||||
Time: 1589300496,
|
|
||||||
Index: 202,
|
|
||||||
NextConsensus: "AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL",
|
|
||||||
Confirmations: 6,
|
|
||||||
ConsensusData: result.ConsensusData{
|
|
||||||
PrimaryIndex: 0,
|
|
||||||
Nonce: "0000000000000457",
|
|
||||||
},
|
},
|
||||||
Script: transaction.Witness{
|
|
||||||
InvocationScript: invScript,
|
|
||||||
VerificationScript: verifScript,
|
|
||||||
},
|
|
||||||
Tx: []*transaction.Transaction{tx},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -283,12 +299,8 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
}
|
}
|
||||||
return c.GetBlockByHashVerbose(hash)
|
return c.GetBlockByHashVerbose(hash)
|
||||||
},
|
},
|
||||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0xcbb73ed9e31dc41a8a222749de475e6ebc2a73b99f73b091a72e0b146110fe86","size":781,"version":0,"nextblockhash":"0x13283c93aec07dc90be3ddd65e2de15e9212f1b3205303f688d6df85129f6b22","previousblockhash":"0x93b540424c1173e487a47582a652686b2885f959ffd895b30e184842403990ef","merkleroot":"0xb8e923148dede20901d6fb225579f6d430cc58f24461d1b0f860ee32abbfcc8d","time":1589300496,"index":202,"consensus_data":{"primary":0,"nonce":"0000000000000457"},"nextconsensus":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","confirmations":6,"script":{"invocation":"0c403620ef8f02d7884c553fb6c54d2fe717cfddd9450886c5fc88a669a29a82fa1a7c715076996567a5a56747f20f10d7e4db071d73b306ccbf17f9a916fcfa1d020c4099e27d87bbb3fb4ce1c77dca85cf3eac46c9c3de87d8022ef7ad2b0a2bb980339293849cf85e5a0a5615ea7bc5bb0a7f28e31f278dc19d628f64c49b888df4c60c40616eefc9286843c2f3f2cf1815988356e409b3f10ffaf60b3468dc0a92dd929cbc8d5da74052c303e7474412f6beaddd551e9056c4e7a5fccdc06107e48f3fe10c40fd2d25d4156e969345c0522669b509e5ced70e4265066eadaf85eea3919d5ded525f8f52d6f0dfa0186c964dd0302fca5bc2dc0540b4ed21085be478c3123996","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"},"tx":[{"txid":"0x96ef00d2efe03101f5b302f7fc3c8fcd22688944bdc83ab99071d77edbb08581","size":254,"type":"ContractTransaction","version":0,"nonce":3,"sender":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","sys_fee":"0","net_fee":"0","valid_until_block":1200,"attributes":[],"cosigners":[],"vin":[{"txid":"0x33e045101301854a0e07ff96a92ca1ba9b23c19501f1b7eb15ae9eea07b5f370","vout":0}],"vout":[{"address":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","asset":"0x1a5e0e3eac2abced7de9ee2de0820a5c85e63756fcdfc29b82fead86a7c07c78","n":0,"value":"99999000"}],"scripts":[{"invocation":"0c402caebbee911a1f159aa05ab40093d086090a817e837f3f87e8b3e47f6b083649137770f6dda0349ddd611bc47402aca457a89b3b7b0076307ab6a47fd57048eb","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"}]}]}}`,
|
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0xcbb73ed9e31dc41a8a222749de475e6ebc2a73b99f73b091a72e0b146110fe86","size":781,"version":0,"nextblockhash":"0x13283c93aec07dc90be3ddd65e2de15e9212f1b3205303f688d6df85129f6b22","previousblockhash":"0x93b540424c1173e487a47582a652686b2885f959ffd895b30e184842403990ef","merkleroot":"0xb8e923148dede20901d6fb225579f6d430cc58f24461d1b0f860ee32abbfcc8d","time":1589300496,"index":202,"consensus_data":{"primary":0,"nonce":"0000000000000457"},"nextconsensus":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","confirmations":6,"witnesses":[{"invocation":"0c403620ef8f02d7884c553fb6c54d2fe717cfddd9450886c5fc88a669a29a82fa1a7c715076996567a5a56747f20f10d7e4db071d73b306ccbf17f9a916fcfa1d020c4099e27d87bbb3fb4ce1c77dca85cf3eac46c9c3de87d8022ef7ad2b0a2bb980339293849cf85e5a0a5615ea7bc5bb0a7f28e31f278dc19d628f64c49b888df4c60c40616eefc9286843c2f3f2cf1815988356e409b3f10ffaf60b3468dc0a92dd929cbc8d5da74052c303e7474412f6beaddd551e9056c4e7a5fccdc06107e48f3fe10c40fd2d25d4156e969345c0522669b509e5ced70e4265066eadaf85eea3919d5ded525f8f52d6f0dfa0186c964dd0302fca5bc2dc0540b4ed21085be478c3123996","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"}],"tx":[{"txid":"0x96ef00d2efe03101f5b302f7fc3c8fcd22688944bdc83ab99071d77edbb08581","size":254,"type":"ContractTransaction","version":0,"nonce":3,"sender":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","sys_fee":"0","net_fee":"0","valid_until_block":1200,"attributes":[],"cosigners":[],"vin":[{"txid":"0x33e045101301854a0e07ff96a92ca1ba9b23c19501f1b7eb15ae9eea07b5f370","vout":0}],"vout":[{"address":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","asset":"0x1a5e0e3eac2abced7de9ee2de0820a5c85e63756fcdfc29b82fead86a7c07c78","n":0,"value":"99999000"}],"scripts":[{"invocation":"0c402caebbee911a1f159aa05ab40093d086090a817e837f3f87e8b3e47f6b083649137770f6dda0349ddd611bc47402aca457a89b3b7b0076307ab6a47fd57048eb","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"}]}]}}`,
|
||||||
result: func(c *Client) interface{} {
|
result: func(c *Client) interface{} {
|
||||||
hash, err := util.Uint256DecodeStringLE("cbb73ed9e31dc41a8a222749de475e6ebc2a73b99f73b091a72e0b146110fe86")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
nextBlockHash, err := util.Uint256DecodeStringLE("13283c93aec07dc90be3ddd65e2de15e9212f1b3205303f688d6df85129f6b22")
|
nextBlockHash, err := util.Uint256DecodeStringLE("13283c93aec07dc90be3ddd65e2de15e9212f1b3205303f688d6df85129f6b22")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -354,28 +366,47 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var nonce uint64
|
||||||
|
i, err := fmt.Sscanf("0000000000000457", "%016x", &nonce)
|
||||||
|
if i != 1 {
|
||||||
|
panic("can't decode nonce")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
nextCon, err := address.StringToUint160("AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
blck := &block.Block{
|
||||||
|
Base: block.Base{
|
||||||
|
Version: 0,
|
||||||
|
PrevHash: prevBlockHash,
|
||||||
|
MerkleRoot: merkleRoot,
|
||||||
|
Timestamp: 1589300496,
|
||||||
|
Index: 202,
|
||||||
|
NextConsensus: nextCon,
|
||||||
|
Script: transaction.Witness{
|
||||||
|
InvocationScript: invScript,
|
||||||
|
VerificationScript: verifScript,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ConsensusData: block.ConsensusData{
|
||||||
|
PrimaryIndex: 0,
|
||||||
|
Nonce: nonce,
|
||||||
|
},
|
||||||
|
Transactions: []*transaction.Transaction{tx},
|
||||||
|
}
|
||||||
// Update hashes for correct result comparison.
|
// Update hashes for correct result comparison.
|
||||||
_ = tx.Hash()
|
_ = tx.Hash()
|
||||||
|
_ = blck.Hash()
|
||||||
return &result.Block{
|
return &result.Block{
|
||||||
Hash: hash,
|
Block: blck,
|
||||||
Size: 781,
|
BlockMetadata: result.BlockMetadata{
|
||||||
Version: 0,
|
Size: 781,
|
||||||
NextBlockHash: &nextBlockHash,
|
Confirmations: 6,
|
||||||
PreviousBlockHash: prevBlockHash,
|
NextBlockHash: &nextBlockHash,
|
||||||
MerkleRoot: merkleRoot,
|
|
||||||
Time: 1589300496,
|
|
||||||
Index: 202,
|
|
||||||
NextConsensus: "AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL",
|
|
||||||
Confirmations: 6,
|
|
||||||
ConsensusData: result.ConsensusData{
|
|
||||||
PrimaryIndex: 0,
|
|
||||||
Nonce: "0000000000000457",
|
|
||||||
},
|
},
|
||||||
Script: transaction.Witness{
|
|
||||||
InvocationScript: invScript,
|
|
||||||
VerificationScript: verifScript,
|
|
||||||
},
|
|
||||||
Tx: []*transaction.Transaction{tx},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -117,7 +117,7 @@ func TestWSClientEvents(t *testing.T) {
|
||||||
`{"jsonrpc":"2.0","method":"transaction_executed","params":[{"txid":"0xe1cd5e57e721d2a2e05fb1f08721b12057b25ab1dd7fd0f33ee1639932fdfad7","executions":[{"trigger":"Application","contract":"0x0000000000000000000000000000000000000000","vmstate":"HALT","gas_consumed":"2.291","stack":[],"notifications":[{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"636f6e74726163742063616c6c"},{"type":"ByteArray","value":"7472616e73666572"},{"type":"Array","value":[{"type":"ByteArray","value":"769162241eedf97c2481652adf1ba0f5bf57431b"},{"type":"ByteArray","value":"316e851039019d39dfc2c37d6c3fee19fd580987"},{"type":"Integer","value":"1000"}]}]}},{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"7472616e73666572"},{"type":"ByteArray","value":"769162241eedf97c2481652adf1ba0f5bf57431b"},{"type":"ByteArray","value":"316e851039019d39dfc2c37d6c3fee19fd580987"},{"type":"Integer","value":"1000"}]}}]}]}]}`,
|
`{"jsonrpc":"2.0","method":"transaction_executed","params":[{"txid":"0xe1cd5e57e721d2a2e05fb1f08721b12057b25ab1dd7fd0f33ee1639932fdfad7","executions":[{"trigger":"Application","contract":"0x0000000000000000000000000000000000000000","vmstate":"HALT","gas_consumed":"2.291","stack":[],"notifications":[{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"636f6e74726163742063616c6c"},{"type":"ByteArray","value":"7472616e73666572"},{"type":"Array","value":[{"type":"ByteArray","value":"769162241eedf97c2481652adf1ba0f5bf57431b"},{"type":"ByteArray","value":"316e851039019d39dfc2c37d6c3fee19fd580987"},{"type":"Integer","value":"1000"}]}]}},{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"7472616e73666572"},{"type":"ByteArray","value":"769162241eedf97c2481652adf1ba0f5bf57431b"},{"type":"ByteArray","value":"316e851039019d39dfc2c37d6c3fee19fd580987"},{"type":"Integer","value":"1000"}]}}]}]}]}`,
|
||||||
`{"jsonrpc":"2.0","method":"notification_from_execution","params":[{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"636f6e74726163742063616c6c"},{"type":"ByteArray","value":"7472616e73666572"},{"type":"Array","value":[{"type":"ByteArray","value":"769162241eedf97c2481652adf1ba0f5bf57431b"},{"type":"ByteArray","value":"316e851039019d39dfc2c37d6c3fee19fd580987"},{"type":"Integer","value":"1000"}]}]}}]}`,
|
`{"jsonrpc":"2.0","method":"notification_from_execution","params":[{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"636f6e74726163742063616c6c"},{"type":"ByteArray","value":"7472616e73666572"},{"type":"Array","value":[{"type":"ByteArray","value":"769162241eedf97c2481652adf1ba0f5bf57431b"},{"type":"ByteArray","value":"316e851039019d39dfc2c37d6c3fee19fd580987"},{"type":"Integer","value":"1000"}]}]}}]}`,
|
||||||
`{"jsonrpc":"2.0","method":"transaction_added","params":[{"txid":"0xe1cd5e57e721d2a2e05fb1f08721b12057b25ab1dd7fd0f33ee1639932fdfad7","size":277,"type":"InvocationTransaction","version":1,"nonce":9,"sender":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","sys_fee":"0","net_fee":"0.0037721","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x870958fd19ee3f6c7dc3c2df399d013910856e31","scopes":1}],"vin":[],"vout":[],"scripts":[{"invocation":"0c4027727296b84853c5d9e07fb8a40e885246ae25641383b16eefbe92027ecb1635b794aacf6bbfc3e828c73829b14791c483d19eb758b57638e3191393dbf2d288","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"}],"script":"01e8030c14316e851039019d39dfc2c37d6c3fee19fd5809870c14769162241eedf97c2481652adf1ba0f5bf57431b13c00c087472616e736665720c14769162241eedf97c2481652adf1ba0f5bf57431b41627d5b5238"}]}`,
|
`{"jsonrpc":"2.0","method":"transaction_added","params":[{"txid":"0xe1cd5e57e721d2a2e05fb1f08721b12057b25ab1dd7fd0f33ee1639932fdfad7","size":277,"type":"InvocationTransaction","version":1,"nonce":9,"sender":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","sys_fee":"0","net_fee":"0.0037721","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x870958fd19ee3f6c7dc3c2df399d013910856e31","scopes":1}],"vin":[],"vout":[],"scripts":[{"invocation":"0c4027727296b84853c5d9e07fb8a40e885246ae25641383b16eefbe92027ecb1635b794aacf6bbfc3e828c73829b14791c483d19eb758b57638e3191393dbf2d288","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"}],"script":"01e8030c14316e851039019d39dfc2c37d6c3fee19fd5809870c14769162241eedf97c2481652adf1ba0f5bf57431b13c00c087472616e736665720c14769162241eedf97c2481652adf1ba0f5bf57431b41627d5b5238"}]}`,
|
||||||
`{"jsonrpc":"2.0","method":"block_added","params":[{"version":0,"previousblockhash":"0x04f7580b111ec75f0ce68d3a9fd70a0544b4521b4a98541694d8575c548b759e","merkleroot":"0xb2c7230ebee4cb83bc03afadbba413e6bca8fcdeaf9c077bea060918da0e52a1","time":1590006200,"height":207,"next_consensus":"0x4138145d67638db97b402ee0b6751ef16253ecab","script":{"invocation":"0c4063429fca5ff75c964d9e38179c75978e33f8174d91a780c2e825265cf2447281594afdd5f3e216dcaf5ff0693aec83f415996cf224454495495f6bd0a4c5d08f0c4099680903a954278580d8533121c2cd3e53a089817b6a784901ec06178a60b5f1da6e70422bdcadc89029767e08d66ce4180b99334cb2d42f42e4216394af15920c4067d5e362189e48839a24e187c59d46f5d9db862c8a029777f1548b19632bfdc73ad373827ed02369f925e89c2303b64e6b9838dca229949b9b9d3bd4c0c3ed8f0c4021d4c00d4522805883f1db929554441bcbbee127c48f6b7feeeb69a72a78c7f0a75011663e239c0820ef903f36168f42936de10f0ef20681cb735a4b53d0390f","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"},"consensus_data":{"primary":0,"nonce":1111},"tx":[{"txid":"0xf736cd91ab84062a21a09b424346b241987f6245ffe8c2b2db39d595c3c222f7","size":204,"type":"InvocationTransaction","version":1,"nonce":8,"sender":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","sys_fee":"0","net_fee":"0.0030421","valid_until_block":1200,"attributes":[],"cosigners":[],"vin":[],"vout":[],"scripts":[{"invocation":"0c4016e7a112742409cdfaad89dcdbcb52c94c5c1a69dfe5d8b999649eaaa787e31ca496d1734d6ea606c749ad36e9a88892240ae59e0efa7f544e0692124898d512","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"}],"script":"10c00c04696e69740c14769162241eedf97c2481652adf1ba0f5bf57431b41627d5b52"},{"txid":"0xe1cd5e57e721d2a2e05fb1f08721b12057b25ab1dd7fd0f33ee1639932fdfad7","size":277,"type":"InvocationTransaction","version":1,"nonce":9,"sender":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","sys_fee":"0","net_fee":"0.0037721","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x870958fd19ee3f6c7dc3c2df399d013910856e31","scopes":1}],"vin":[],"vout":[],"scripts":[{"invocation":"0c4027727296b84853c5d9e07fb8a40e885246ae25641383b16eefbe92027ecb1635b794aacf6bbfc3e828c73829b14791c483d19eb758b57638e3191393dbf2d288","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"}],"script":"01e8030c14316e851039019d39dfc2c37d6c3fee19fd5809870c14769162241eedf97c2481652adf1ba0f5bf57431b13c00c087472616e736665720c14769162241eedf97c2481652adf1ba0f5bf57431b41627d5b5238"}]}]}`,
|
`{"jsonrpc":"2.0","method":"block_added","params":[{"hash":"0x239fea00c54c2f6812612874183b72bef4473fcdf68bf8da08d74fd5b6cab030","version":0,"previousblockhash":"0x04f7580b111ec75f0ce68d3a9fd70a0544b4521b4a98541694d8575c548b759e","merkleroot":"0xb2c7230ebee4cb83bc03afadbba413e6bca8fcdeaf9c077bea060918da0e52a1","time":1590006200,"index":207,"nextconsensus":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","witnesses":[{"invocation":"0c4063429fca5ff75c964d9e38179c75978e33f8174d91a780c2e825265cf2447281594afdd5f3e216dcaf5ff0693aec83f415996cf224454495495f6bd0a4c5d08f0c4099680903a954278580d8533121c2cd3e53a089817b6a784901ec06178a60b5f1da6e70422bdcadc89029767e08d66ce4180b99334cb2d42f42e4216394af15920c4067d5e362189e48839a24e187c59d46f5d9db862c8a029777f1548b19632bfdc73ad373827ed02369f925e89c2303b64e6b9838dca229949b9b9d3bd4c0c3ed8f0c4021d4c00d4522805883f1db929554441bcbbee127c48f6b7feeeb69a72a78c7f0a75011663e239c0820ef903f36168f42936de10f0ef20681cb735a4b53d0390f","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"}],"consensus_data":{"primary":0,"nonce":"0000000000000457"},"tx":[{"txid":"0xf736cd91ab84062a21a09b424346b241987f6245ffe8c2b2db39d595c3c222f7","size":204,"type":"InvocationTransaction","version":1,"nonce":8,"sender":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","sys_fee":"0","net_fee":"0.0030421","valid_until_block":1200,"attributes":[],"cosigners":[],"vin":[],"vout":[],"scripts":[{"invocation":"0c4016e7a112742409cdfaad89dcdbcb52c94c5c1a69dfe5d8b999649eaaa787e31ca496d1734d6ea606c749ad36e9a88892240ae59e0efa7f544e0692124898d512","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"}],"script":"10c00c04696e69740c14769162241eedf97c2481652adf1ba0f5bf57431b41627d5b52"},{"txid":"0xe1cd5e57e721d2a2e05fb1f08721b12057b25ab1dd7fd0f33ee1639932fdfad7","size":277,"type":"InvocationTransaction","version":1,"nonce":9,"sender":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","sys_fee":"0","net_fee":"0.0037721","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x870958fd19ee3f6c7dc3c2df399d013910856e31","scopes":1}],"vin":[],"vout":[],"scripts":[{"invocation":"0c4027727296b84853c5d9e07fb8a40e885246ae25641383b16eefbe92027ecb1635b794aacf6bbfc3e828c73829b14791c483d19eb758b57638e3191393dbf2d288","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"}],"script":"01e8030c14316e851039019d39dfc2c37d6c3fee19fd5809870c14769162241eedf97c2481652adf1ba0f5bf57431b13c00c087472616e736665720c14769162241eedf97c2481652adf1ba0f5bf57431b41627d5b5238"}]}]}`,
|
||||||
`{"jsonrpc":"2.0","method":"event_missed","params":[]}`,
|
`{"jsonrpc":"2.0","method":"event_missed","params":[]}`,
|
||||||
}
|
}
|
||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
|
|
@ -1,65 +1,40 @@
|
||||||
package result
|
package result
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// ConsensusData is a wrapper for block.ConsensusData
|
|
||||||
ConsensusData struct {
|
|
||||||
PrimaryIndex uint32 `json:"primary"`
|
|
||||||
Nonce string `json:"nonce"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Block wrapper used for the representation of
|
// Block wrapper used for the representation of
|
||||||
// block.Block / block.Base on the RPC Server.
|
// block.Block / block.Base on the RPC Server.
|
||||||
Block struct {
|
Block struct {
|
||||||
Hash util.Uint256 `json:"hash"`
|
*block.Block
|
||||||
Size int `json:"size"`
|
BlockMetadata
|
||||||
Version uint32 `json:"version"`
|
}
|
||||||
NextBlockHash *util.Uint256 `json:"nextblockhash,omitempty"`
|
|
||||||
PreviousBlockHash util.Uint256 `json:"previousblockhash"`
|
|
||||||
MerkleRoot util.Uint256 `json:"merkleroot"`
|
|
||||||
Time uint64 `json:"time"`
|
|
||||||
Index uint32 `json:"index"`
|
|
||||||
ConsensusData ConsensusData `json:"consensus_data"`
|
|
||||||
NextConsensus string `json:"nextconsensus"`
|
|
||||||
|
|
||||||
Confirmations uint32 `json:"confirmations"`
|
// BlockMetadata is an additional metadata added to standard
|
||||||
|
// block.Block.
|
||||||
Script transaction.Witness `json:"script"`
|
BlockMetadata struct {
|
||||||
|
Size int `json:"size"`
|
||||||
Tx []*transaction.Transaction `json:"tx"`
|
NextBlockHash *util.Uint256 `json:"nextblockhash,omitempty"`
|
||||||
|
Confirmations uint32 `json:"confirmations"`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewBlock creates a new Block wrapper.
|
// NewBlock creates a new Block wrapper.
|
||||||
func NewBlock(b *block.Block, chain blockchainer.Blockchainer) Block {
|
func NewBlock(b *block.Block, chain blockchainer.Blockchainer) Block {
|
||||||
res := Block{
|
res := Block{
|
||||||
Version: b.Version,
|
Block: b,
|
||||||
Hash: b.Hash(),
|
BlockMetadata: BlockMetadata{
|
||||||
Size: io.GetVarSize(b),
|
Size: io.GetVarSize(b),
|
||||||
PreviousBlockHash: b.PrevHash,
|
Confirmations: chain.BlockHeight() - b.Index - 1,
|
||||||
MerkleRoot: b.MerkleRoot,
|
|
||||||
Time: b.Timestamp,
|
|
||||||
Index: b.Index,
|
|
||||||
ConsensusData: ConsensusData{
|
|
||||||
PrimaryIndex: b.ConsensusData.PrimaryIndex,
|
|
||||||
Nonce: fmt.Sprintf("%016x", b.ConsensusData.Nonce),
|
|
||||||
},
|
},
|
||||||
NextConsensus: address.Uint160ToString(b.NextConsensus),
|
|
||||||
Confirmations: chain.BlockHeight() - b.Index - 1,
|
|
||||||
|
|
||||||
Script: b.Script,
|
|
||||||
|
|
||||||
Tx: b.Transactions,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hash := chain.GetHeaderHash(int(b.Index) + 1)
|
hash := chain.GetHeaderHash(int(b.Index) + 1)
|
||||||
|
@ -69,3 +44,44 @@ func NewBlock(b *block.Block, chain blockchainer.Blockchainer) Block {
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements json.Marshaler interface.
|
||||||
|
func (b Block) MarshalJSON() ([]byte, error) {
|
||||||
|
output, err := json.Marshal(b.BlockMetadata)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
baseBytes, err := json.Marshal(b.Block)
|
||||||
|
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 (b *Block) 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)
|
||||||
|
base := new(block.Block)
|
||||||
|
err := json.Unmarshal(data, meta)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(data, base)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.Block = base
|
||||||
|
b.BlockMetadata = *meta
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -384,9 +384,8 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
block, err := e.chain.GetBlock(e.chain.GetHeaderHash(3))
|
block, err := e.chain.GetBlock(e.chain.GetHeaderHash(3))
|
||||||
require.NoErrorf(t, err, "could not get block")
|
require.NoErrorf(t, err, "could not get block")
|
||||||
|
|
||||||
assert.Equal(t, block.Hash(), res.Hash)
|
assert.Equal(t, block.Hash(), res.Hash())
|
||||||
for i := range res.Tx {
|
for i, tx := range res.Transactions {
|
||||||
tx := res.Tx[i]
|
|
||||||
require.Equal(t, transaction.ContractType, tx.Type)
|
require.Equal(t, transaction.ContractType, tx.Type)
|
||||||
|
|
||||||
actualTx := block.Transactions[i]
|
actualTx := block.Transactions[i]
|
||||||
|
|
|
@ -228,7 +228,7 @@ func TestFilteredSubscriptions(t *testing.T) {
|
||||||
resp := getNotification(t, respMsgs)
|
resp := getNotification(t, respMsgs)
|
||||||
rmap := resp.Payload[0].(map[string]interface{})
|
rmap := resp.Payload[0].(map[string]interface{})
|
||||||
if resp.Event == response.BlockEventID {
|
if resp.Event == response.BlockEventID {
|
||||||
index := rmap["height"].(float64)
|
index := rmap["index"].(float64)
|
||||||
if uint32(index) == lastBlock {
|
if uint32(index) == lastBlock {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue