forked from TrueCloudLab/neoneo-go
Merge pull request #898 from nspcc-dev/neo3/block_format
core: change block format to neo3
This commit is contained in:
commit
ec2218698f
41 changed files with 377 additions and 449 deletions
2
go.mod
2
go.mod
|
@ -7,7 +7,7 @@ require (
|
||||||
github.com/go-redis/redis v6.10.2+incompatible
|
github.com/go-redis/redis v6.10.2+incompatible
|
||||||
github.com/go-yaml/yaml v2.1.0+incompatible
|
github.com/go-yaml/yaml v2.1.0+incompatible
|
||||||
github.com/mr-tron/base58 v1.1.2
|
github.com/mr-tron/base58 v1.1.2
|
||||||
github.com/nspcc-dev/dbft v0.0.0-20200303183127-36d3da79c682
|
github.com/nspcc-dev/dbft v0.0.0-20200427132226-05feeca847dd
|
||||||
github.com/nspcc-dev/rfc6979 v0.2.0
|
github.com/nspcc-dev/rfc6979 v0.2.0
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/prometheus/client_golang v1.2.1
|
github.com/prometheus/client_golang v1.2.1
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -131,6 +131,14 @@ github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1 h1:yEx9WznS+rjE0jl0
|
||||||
github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1/go.mod h1:O0qtn62prQSqizzoagHmuuKoz8QMkU3SzBoKdEvm3aQ=
|
github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1/go.mod h1:O0qtn62prQSqizzoagHmuuKoz8QMkU3SzBoKdEvm3aQ=
|
||||||
github.com/nspcc-dev/dbft v0.0.0-20200303183127-36d3da79c682 h1:63OWUolW4GcjJR7cThq8hLnMLTwL+sjO3Qf4fo4sx8w=
|
github.com/nspcc-dev/dbft v0.0.0-20200303183127-36d3da79c682 h1:63OWUolW4GcjJR7cThq8hLnMLTwL+sjO3Qf4fo4sx8w=
|
||||||
github.com/nspcc-dev/dbft v0.0.0-20200303183127-36d3da79c682/go.mod h1:1FYQXSbb6/9HQIkoF8XO7W/S8N7AZRkBsgwbcXRvk0E=
|
github.com/nspcc-dev/dbft v0.0.0-20200303183127-36d3da79c682/go.mod h1:1FYQXSbb6/9HQIkoF8XO7W/S8N7AZRkBsgwbcXRvk0E=
|
||||||
|
github.com/nspcc-dev/dbft v0.0.0-20200427132226-05feeca847dd h1:4XKbXahJWlhjVx2cETQz9edHQfe3BQ2JjNdvSKFBelY=
|
||||||
|
github.com/nspcc-dev/dbft v0.0.0-20200427132226-05feeca847dd/go.mod h1:1FYQXSbb6/9HQIkoF8XO7W/S8N7AZRkBsgwbcXRvk0E=
|
||||||
|
github.com/nspcc-dev/dbft v0.0.0-20200427132226-15a7927772a4 h1:3cFSp4v2u9+S7K1GdLUOP1680EiGEHSBvSI6G2n8XzY=
|
||||||
|
github.com/nspcc-dev/dbft v0.0.0-20200427132226-15a7927772a4/go.mod h1:1FYQXSbb6/9HQIkoF8XO7W/S8N7AZRkBsgwbcXRvk0E=
|
||||||
|
github.com/nspcc-dev/dbft v0.0.0-20200427132226-342f23599814 h1:iNqBioi0RU2VX9UiGl/GfQKBbZrDWq5KSxQG+dgTaqo=
|
||||||
|
github.com/nspcc-dev/dbft v0.0.0-20200427132226-342f23599814/go.mod h1:1FYQXSbb6/9HQIkoF8XO7W/S8N7AZRkBsgwbcXRvk0E=
|
||||||
|
github.com/nspcc-dev/dbft v0.0.0-20200427132226-660464796c11 h1:sledsmRo0wzgWNCZir5/CeM0PjhHVP8khnGtOfBCFWk=
|
||||||
|
github.com/nspcc-dev/dbft v0.0.0-20200427132226-660464796c11/go.mod h1:1FYQXSbb6/9HQIkoF8XO7W/S8N7AZRkBsgwbcXRvk0E=
|
||||||
github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg=
|
github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg=
|
||||||
github.com/nspcc-dev/neofs-crypto v0.2.0 h1:ftN+59WqxSWz/RCgXYOfhmltOOqU+udsNQSvN6wkFck=
|
github.com/nspcc-dev/neofs-crypto v0.2.0 h1:ftN+59WqxSWz/RCgXYOfhmltOOqU+udsNQSvN6wkFck=
|
||||||
github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA=
|
github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA=
|
||||||
|
|
|
@ -58,44 +58,23 @@ func (n *neoBlock) SetTransactions(txes []block.Transaction) {
|
||||||
// Version implements block.Block interface.
|
// Version implements block.Block interface.
|
||||||
func (n *neoBlock) Version() uint32 { return n.Block.Version }
|
func (n *neoBlock) Version() uint32 { return n.Block.Version }
|
||||||
|
|
||||||
// SetVersion implements block.Block interface.
|
|
||||||
func (n *neoBlock) SetVersion(v uint32) { n.Block.Version = v }
|
|
||||||
|
|
||||||
// PrevHash implements block.Block interface.
|
// PrevHash implements block.Block interface.
|
||||||
func (n *neoBlock) PrevHash() util.Uint256 { return n.Block.PrevHash }
|
func (n *neoBlock) PrevHash() util.Uint256 { return n.Block.PrevHash }
|
||||||
|
|
||||||
// SetPrevHash implements block.Block interface.
|
|
||||||
func (n *neoBlock) SetPrevHash(h util.Uint256) { n.Block.PrevHash = h }
|
|
||||||
|
|
||||||
// MerkleRoot implements block.Block interface.
|
// MerkleRoot implements block.Block interface.
|
||||||
func (n *neoBlock) MerkleRoot() util.Uint256 { return n.Block.MerkleRoot }
|
func (n *neoBlock) MerkleRoot() util.Uint256 { return n.Block.MerkleRoot }
|
||||||
|
|
||||||
// SetMerkleRoot implements block.Block interface.
|
|
||||||
func (n *neoBlock) SetMerkleRoot(r util.Uint256) { n.Block.MerkleRoot = r }
|
|
||||||
|
|
||||||
// Timestamp implements block.Block interface.
|
// Timestamp implements block.Block interface.
|
||||||
func (n *neoBlock) Timestamp() uint32 { return n.Block.Timestamp }
|
func (n *neoBlock) Timestamp() uint64 { return n.Block.Timestamp * 1000000 }
|
||||||
|
|
||||||
// SetTimestamp implements block.Block interface.
|
|
||||||
func (n *neoBlock) SetTimestamp(ts uint32) { n.Block.Timestamp = ts }
|
|
||||||
|
|
||||||
// Index implements block.Block interface.
|
// Index implements block.Block interface.
|
||||||
func (n *neoBlock) Index() uint32 { return n.Block.Index }
|
func (n *neoBlock) Index() uint32 { return n.Block.Index }
|
||||||
|
|
||||||
// SetIndex implements block.Block interface.
|
|
||||||
func (n *neoBlock) SetIndex(i uint32) { n.Block.Index = i }
|
|
||||||
|
|
||||||
// ConsensusData implements block.Block interface.
|
// ConsensusData implements block.Block interface.
|
||||||
func (n *neoBlock) ConsensusData() uint64 { return n.Block.ConsensusData }
|
func (n *neoBlock) ConsensusData() uint64 { return n.Block.ConsensusData.Nonce }
|
||||||
|
|
||||||
// SetConsensusData implements block.Block interface.
|
|
||||||
func (n *neoBlock) SetConsensusData(nonce uint64) { n.Block.ConsensusData = nonce }
|
|
||||||
|
|
||||||
// NextConsensus implements block.Block interface.
|
// NextConsensus implements block.Block interface.
|
||||||
func (n *neoBlock) NextConsensus() util.Uint160 { return n.Block.NextConsensus }
|
func (n *neoBlock) NextConsensus() util.Uint160 { return n.Block.NextConsensus }
|
||||||
|
|
||||||
// SetNextConsensus implements block.Block interface.
|
|
||||||
func (n *neoBlock) SetNextConsensus(h util.Uint160) { n.Block.NextConsensus = h }
|
|
||||||
|
|
||||||
// Signature implements block.Block interface.
|
// Signature implements block.Block interface.
|
||||||
func (n *neoBlock) Signature() []byte { return n.signature }
|
func (n *neoBlock) Signature() []byte { return n.signature }
|
||||||
|
|
|
@ -22,28 +22,29 @@ func TestNeoBlock_Sign(t *testing.T) {
|
||||||
func TestNeoBlock_Setters(t *testing.T) {
|
func TestNeoBlock_Setters(t *testing.T) {
|
||||||
b := new(neoBlock)
|
b := new(neoBlock)
|
||||||
|
|
||||||
b.SetVersion(1)
|
b.Block.Version = 1
|
||||||
require.EqualValues(t, 1, b.Version())
|
require.EqualValues(t, 1, b.Version())
|
||||||
|
|
||||||
b.SetIndex(12)
|
b.Block.Index = 12
|
||||||
require.EqualValues(t, 12, b.Index())
|
require.EqualValues(t, 12, b.Index())
|
||||||
|
|
||||||
b.SetTimestamp(777)
|
b.Block.Timestamp = 777
|
||||||
require.EqualValues(t, 777, b.Timestamp())
|
// 777ms -> 777000000ns
|
||||||
|
require.EqualValues(t, 777000000, b.Timestamp())
|
||||||
|
|
||||||
b.SetConsensusData(456)
|
b.Block.ConsensusData.Nonce = 456
|
||||||
require.EqualValues(t, 456, b.ConsensusData())
|
require.EqualValues(t, 456, b.ConsensusData())
|
||||||
|
|
||||||
b.SetMerkleRoot(util.Uint256{1, 2, 3, 4})
|
b.Block.MerkleRoot = util.Uint256{1, 2, 3, 4}
|
||||||
require.Equal(t, util.Uint256{1, 2, 3, 4}, b.MerkleRoot())
|
require.Equal(t, util.Uint256{1, 2, 3, 4}, b.MerkleRoot())
|
||||||
|
|
||||||
b.SetNextConsensus(util.Uint160{9, 2})
|
b.Block.NextConsensus = util.Uint160{9, 2}
|
||||||
require.Equal(t, util.Uint160{9, 2}, b.NextConsensus())
|
require.Equal(t, util.Uint160{9, 2}, b.NextConsensus())
|
||||||
|
|
||||||
b.SetPrevHash(util.Uint256{9, 8, 7})
|
b.Block.PrevHash = util.Uint256{9, 8, 7}
|
||||||
require.Equal(t, util.Uint256{9, 8, 7}, b.PrevHash())
|
require.Equal(t, util.Uint256{9, 8, 7}, b.PrevHash())
|
||||||
|
|
||||||
txx := []block.Transaction{transaction.NewMinerTX()}
|
txx := []block.Transaction{transaction.NewIssueTX()}
|
||||||
b.SetTransactions(txx)
|
b.SetTransactions(txx)
|
||||||
require.Equal(t, txx, b.Transactions())
|
require.Equal(t, txx, b.Transactions())
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,14 @@ package consensus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/rand"
|
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nspcc-dev/dbft"
|
"github.com/nspcc-dev/dbft"
|
||||||
"github.com/nspcc-dev/dbft/block"
|
"github.com/nspcc-dev/dbft/block"
|
||||||
"github.com/nspcc-dev/dbft/crypto"
|
"github.com/nspcc-dev/dbft/crypto"
|
||||||
|
"github.com/nspcc-dev/dbft/merkle"
|
||||||
"github.com/nspcc-dev/dbft/payload"
|
"github.com/nspcc-dev/dbft/payload"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core"
|
|
||||||
coreb "github.com/nspcc-dev/neo-go/pkg/core/block"
|
coreb "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/mempool"
|
"github.com/nspcc-dev/neo-go/pkg/core/mempool"
|
||||||
|
@ -136,7 +135,7 @@ func NewService(cfg Config) (Service, error) {
|
||||||
dbft.WithVerifyBlock(srv.verifyBlock),
|
dbft.WithVerifyBlock(srv.verifyBlock),
|
||||||
dbft.WithGetBlock(srv.getBlock),
|
dbft.WithGetBlock(srv.getBlock),
|
||||||
dbft.WithWatchOnly(func() bool { return false }),
|
dbft.WithWatchOnly(func() bool { return false }),
|
||||||
dbft.WithNewBlock(func() block.Block { return new(neoBlock) }),
|
dbft.WithNewBlockFromContext(newBlockFromContext),
|
||||||
dbft.WithCurrentHeight(cfg.Chain.BlockHeight),
|
dbft.WithCurrentHeight(cfg.Chain.BlockHeight),
|
||||||
dbft.WithCurrentBlockHash(cfg.Chain.CurrentBlockHash),
|
dbft.WithCurrentBlockHash(cfg.Chain.CurrentBlockHash),
|
||||||
dbft.WithGetValidators(srv.getValidators),
|
dbft.WithGetValidators(srv.getValidators),
|
||||||
|
@ -276,7 +275,6 @@ func (s *service) OnPayload(cp *Payload) {
|
||||||
switch cp.Type() {
|
switch cp.Type() {
|
||||||
case payload.PrepareRequestType:
|
case payload.PrepareRequestType:
|
||||||
req := cp.GetPrepareRequest().(*prepareRequest)
|
req := cp.GetPrepareRequest().(*prepareRequest)
|
||||||
s.txx.Add(&req.minerTx)
|
|
||||||
s.lastProposal = req.transactionHashes
|
s.lastProposal = req.transactionHashes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,12 +314,6 @@ func (s *service) GetPayload(h util.Uint256) *Payload {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) broadcast(p payload.ConsensusPayload) {
|
func (s *service) broadcast(p payload.ConsensusPayload) {
|
||||||
switch p.Type() {
|
|
||||||
case payload.PrepareRequestType:
|
|
||||||
pr := p.GetPrepareRequest().(*prepareRequest)
|
|
||||||
pr.minerTx = *s.txx.Get(pr.transactionHashes[0]).(*transaction.Transaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := p.(*Payload).Sign(s.dbft.Priv.(*privateKey)); err != nil {
|
if err := p.(*Payload).Sign(s.dbft.Priv.(*privateKey)); err != nil {
|
||||||
s.log.Warn("can't sign consensus payload", zap.Error(err))
|
s.log.Warn("can't sign consensus payload", zap.Error(err))
|
||||||
}
|
}
|
||||||
|
@ -442,40 +434,11 @@ func (s *service) getVerifiedTx(count int) []block.Transaction {
|
||||||
txx = s.Config.Chain.ApplyPolicyToTxSet(txx)
|
txx = s.Config.Chain.ApplyPolicyToTxSet(txx)
|
||||||
}
|
}
|
||||||
|
|
||||||
res := make([]block.Transaction, len(txx)+1)
|
res := make([]block.Transaction, len(txx))
|
||||||
var netFee util.Fixed8
|
|
||||||
for i := range txx {
|
for i := range txx {
|
||||||
res[i+1] = txx[i].Tx
|
res[i] = txx[i].Tx
|
||||||
netFee += txx[i].Fee
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var txOuts []transaction.Output
|
|
||||||
if netFee != 0 {
|
|
||||||
sh := s.wallet.GetChangeAddress()
|
|
||||||
if sh.Equals(util.Uint160{}) {
|
|
||||||
pk := s.dbft.Pub.(*publicKey)
|
|
||||||
sh = pk.GetScriptHash()
|
|
||||||
}
|
|
||||||
txOuts = []transaction.Output{{
|
|
||||||
AssetID: core.UtilityTokenID(),
|
|
||||||
Amount: netFee,
|
|
||||||
ScriptHash: sh,
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
minerTx := transaction.NewMinerTX()
|
|
||||||
minerTx.Outputs = txOuts
|
|
||||||
minerTx.ValidUntilBlock = s.dbft.BlockIndex
|
|
||||||
minerTx.Nonce = rand.Uint32()
|
|
||||||
res[0] = minerTx
|
|
||||||
|
|
||||||
if tx, _, _ := s.Chain.GetTransaction(res[0].Hash()); tx == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s.txx.Add(res[0])
|
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,3 +479,30 @@ func convertKeys(validators []crypto.PublicKey) (pubs []*keys.PublicKey) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newBlockFromContext(ctx *dbft.Context) block.Block {
|
||||||
|
block := new(neoBlock)
|
||||||
|
if ctx.TransactionHashes == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
block.Block.Timestamp = ctx.Timestamp / 1000000
|
||||||
|
block.Block.Index = ctx.BlockIndex
|
||||||
|
block.Block.NextConsensus = ctx.NextConsensus
|
||||||
|
block.Block.PrevHash = ctx.PrevHash
|
||||||
|
block.Block.Version = ctx.Version
|
||||||
|
block.Block.ConsensusData.Nonce = ctx.Nonce
|
||||||
|
|
||||||
|
primaryIndex := uint32(ctx.PrimaryIndex)
|
||||||
|
block.Block.ConsensusData.PrimaryIndex = primaryIndex
|
||||||
|
consensusData := coreb.ConsensusData{
|
||||||
|
PrimaryIndex: primaryIndex,
|
||||||
|
Nonce: ctx.Nonce,
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ctx.TransactionHashes) != 0 {
|
||||||
|
mt := merkle.NewMerkleTree(append([]util.Uint256{consensusData.Hash()}, ctx.TransactionHashes...)...)
|
||||||
|
block.Block.MerkleRoot = mt.Root().Hash
|
||||||
|
}
|
||||||
|
return block
|
||||||
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
|
|
||||||
func TestNewService(t *testing.T) {
|
func TestNewService(t *testing.T) {
|
||||||
srv := newTestService(t)
|
srv := newTestService(t)
|
||||||
tx := transaction.NewMinerTX()
|
tx := transaction.NewContractTX()
|
||||||
tx.ValidUntilBlock = 1
|
tx.ValidUntilBlock = 1
|
||||||
addSender(t, tx)
|
addSender(t, tx)
|
||||||
signTx(t, tx)
|
signTx(t, tx)
|
||||||
|
@ -30,8 +30,8 @@ func TestNewService(t *testing.T) {
|
||||||
|
|
||||||
var txx []block.Transaction
|
var txx []block.Transaction
|
||||||
require.NotPanics(t, func() { txx = srv.getVerifiedTx(1) })
|
require.NotPanics(t, func() { txx = srv.getVerifiedTx(1) })
|
||||||
require.Len(t, txx, 2)
|
require.Len(t, txx, 1)
|
||||||
require.Equal(t, tx, txx[1])
|
require.Equal(t, tx, txx[0])
|
||||||
srv.Chain.Close()
|
srv.Chain.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,8 @@ func TestService_GetVerified(t *testing.T) {
|
||||||
srv := newTestService(t)
|
srv := newTestService(t)
|
||||||
var txs []*transaction.Transaction
|
var txs []*transaction.Transaction
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
tx := transaction.NewMinerTXWithNonce(123 + uint32(i))
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = 123 + uint32(i)
|
||||||
tx.ValidUntilBlock = 1
|
tx.ValidUntilBlock = 1
|
||||||
txs = append(txs, tx)
|
txs = append(txs, tx)
|
||||||
}
|
}
|
||||||
|
@ -52,7 +53,9 @@ func TestService_GetVerified(t *testing.T) {
|
||||||
p := new(Payload)
|
p := new(Payload)
|
||||||
p.message = &message{}
|
p.message = &message{}
|
||||||
p.SetType(payload.PrepareRequestType)
|
p.SetType(payload.PrepareRequestType)
|
||||||
p.SetPayload(&prepareRequest{transactionHashes: hashes, minerTx: *transaction.NewMinerTXWithNonce(999)})
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = 999
|
||||||
|
p.SetPayload(&prepareRequest{transactionHashes: hashes})
|
||||||
p.SetValidatorIndex(1)
|
p.SetValidatorIndex(1)
|
||||||
|
|
||||||
priv, _ := getTestValidator(1)
|
priv, _ := getTestValidator(1)
|
||||||
|
@ -65,8 +68,8 @@ func TestService_GetVerified(t *testing.T) {
|
||||||
|
|
||||||
t.Run("new transactions will be proposed in case of failure", func(t *testing.T) {
|
t.Run("new transactions will be proposed in case of failure", func(t *testing.T) {
|
||||||
txx := srv.getVerifiedTx(10)
|
txx := srv.getVerifiedTx(10)
|
||||||
require.Equal(t, 2, len(txx), "there is only 1 tx in mempool")
|
require.Equal(t, 1, len(txx), "there is only 1 tx in mempool")
|
||||||
require.Equal(t, txs[3], txx[1])
|
require.Equal(t, txs[3], txx[0])
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("more than half of the last proposal will be reused", func(t *testing.T) {
|
t.Run("more than half of the last proposal will be reused", func(t *testing.T) {
|
||||||
|
@ -117,7 +120,8 @@ func TestService_getTx(t *testing.T) {
|
||||||
srv := newTestService(t)
|
srv := newTestService(t)
|
||||||
|
|
||||||
t.Run("transaction in mempool", func(t *testing.T) {
|
t.Run("transaction in mempool", func(t *testing.T) {
|
||||||
tx := transaction.NewMinerTXWithNonce(1234)
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = 1234
|
||||||
tx.ValidUntilBlock = 1
|
tx.ValidUntilBlock = 1
|
||||||
addSender(t, tx)
|
addSender(t, tx)
|
||||||
signTx(t, tx)
|
signTx(t, tx)
|
||||||
|
@ -133,7 +137,8 @@ func TestService_getTx(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("transaction in local cache", func(t *testing.T) {
|
t.Run("transaction in local cache", func(t *testing.T) {
|
||||||
tx := transaction.NewMinerTXWithNonce(4321)
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = 4321
|
||||||
tx.ValidUntilBlock = 1
|
tx.ValidUntilBlock = 1
|
||||||
h := tx.Hash()
|
h := tx.Hash()
|
||||||
|
|
||||||
|
|
|
@ -243,14 +243,12 @@ func randomPrepareRequest(t *testing.T) *prepareRequest {
|
||||||
const txCount = 3
|
const txCount = 3
|
||||||
|
|
||||||
req := &prepareRequest{
|
req := &prepareRequest{
|
||||||
timestamp: rand.Uint32(),
|
timestamp: rand.Uint64(),
|
||||||
nonce: rand.Uint64(),
|
nonce: rand.Uint64(),
|
||||||
transactionHashes: make([]util.Uint256, txCount),
|
transactionHashes: make([]util.Uint256, txCount),
|
||||||
minerTx: *transaction.NewMinerTX(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
req.transactionHashes[0] = req.minerTx.Hash()
|
for i := 0; i < txCount; i++ {
|
||||||
for i := 1; i < txCount; i++ {
|
|
||||||
req.transactionHashes[i] = random.Uint256()
|
req.transactionHashes[i] = random.Uint256()
|
||||||
}
|
}
|
||||||
req.nextConsensus = random.Uint160()
|
req.nextConsensus = random.Uint160()
|
||||||
|
|
|
@ -2,17 +2,15 @@ package consensus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/dbft/payload"
|
"github.com/nspcc-dev/dbft/payload"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
// prepareRequest represents dBFT prepareRequest message.
|
// prepareRequest represents dBFT prepareRequest message.
|
||||||
type prepareRequest struct {
|
type prepareRequest struct {
|
||||||
timestamp uint32
|
timestamp uint64
|
||||||
nonce uint64
|
nonce uint64
|
||||||
transactionHashes []util.Uint256
|
transactionHashes []util.Uint256
|
||||||
minerTx transaction.Transaction
|
|
||||||
nextConsensus util.Uint160
|
nextConsensus util.Uint160
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,27 +18,25 @@ var _ payload.PrepareRequest = (*prepareRequest)(nil)
|
||||||
|
|
||||||
// EncodeBinary implements io.Serializable interface.
|
// EncodeBinary implements io.Serializable interface.
|
||||||
func (p *prepareRequest) EncodeBinary(w *io.BinWriter) {
|
func (p *prepareRequest) EncodeBinary(w *io.BinWriter) {
|
||||||
w.WriteU32LE(p.timestamp)
|
w.WriteU64LE(p.timestamp)
|
||||||
w.WriteU64LE(p.nonce)
|
w.WriteU64LE(p.nonce)
|
||||||
w.WriteBytes(p.nextConsensus[:])
|
w.WriteBytes(p.nextConsensus[:])
|
||||||
w.WriteArray(p.transactionHashes)
|
w.WriteArray(p.transactionHashes)
|
||||||
p.minerTx.EncodeBinary(w)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeBinary implements io.Serializable interface.
|
// DecodeBinary implements io.Serializable interface.
|
||||||
func (p *prepareRequest) DecodeBinary(r *io.BinReader) {
|
func (p *prepareRequest) DecodeBinary(r *io.BinReader) {
|
||||||
p.timestamp = r.ReadU32LE()
|
p.timestamp = r.ReadU64LE()
|
||||||
p.nonce = r.ReadU64LE()
|
p.nonce = r.ReadU64LE()
|
||||||
r.ReadBytes(p.nextConsensus[:])
|
r.ReadBytes(p.nextConsensus[:])
|
||||||
r.ReadArray(&p.transactionHashes)
|
r.ReadArray(&p.transactionHashes)
|
||||||
p.minerTx.DecodeBinary(r)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timestamp implements payload.PrepareRequest interface.
|
// Timestamp implements payload.PrepareRequest interface.
|
||||||
func (p *prepareRequest) Timestamp() uint32 { return p.timestamp }
|
func (p *prepareRequest) Timestamp() uint64 { return p.timestamp * 1000000 }
|
||||||
|
|
||||||
// SetTimestamp implements payload.PrepareRequest interface.
|
// SetTimestamp implements payload.PrepareRequest interface.
|
||||||
func (p *prepareRequest) SetTimestamp(ts uint32) { p.timestamp = ts }
|
func (p *prepareRequest) SetTimestamp(ts uint64) { p.timestamp = ts / 1000000 }
|
||||||
|
|
||||||
// Nonce implements payload.PrepareRequest interface.
|
// Nonce implements payload.PrepareRequest interface.
|
||||||
func (p *prepareRequest) Nonce() uint64 { return p.nonce }
|
func (p *prepareRequest) Nonce() uint64 { return p.nonce }
|
||||||
|
|
|
@ -12,7 +12,12 @@ func TestPrepareRequest_Setters(t *testing.T) {
|
||||||
var p prepareRequest
|
var p prepareRequest
|
||||||
|
|
||||||
p.SetTimestamp(123)
|
p.SetTimestamp(123)
|
||||||
require.EqualValues(t, 123, p.Timestamp())
|
// 123ns -> 0ms -> 0ns
|
||||||
|
require.EqualValues(t, 0, p.Timestamp())
|
||||||
|
|
||||||
|
p.SetTimestamp(1230000)
|
||||||
|
// 1230000ns -> 1ms -> 1000000ns
|
||||||
|
require.EqualValues(t, 1000000, p.Timestamp())
|
||||||
|
|
||||||
p.SetNextConsensus(util.Uint160{5, 6, 7})
|
p.SetNextConsensus(util.Uint160{5, 6, 7})
|
||||||
require.Equal(t, util.Uint160{5, 6, 7}, p.NextConsensus())
|
require.Equal(t, util.Uint160{5, 6, 7}, p.NextConsensus())
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
|
|
||||||
"github.com/nspcc-dev/dbft/crypto"
|
"github.com/nspcc-dev/dbft/crypto"
|
||||||
"github.com/nspcc-dev/dbft/payload"
|
"github.com/nspcc-dev/dbft/payload"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -32,7 +31,6 @@ func TestRecoveryMessage_Setters(t *testing.T) {
|
||||||
timestamp: 87,
|
timestamp: 87,
|
||||||
nonce: 321,
|
nonce: 321,
|
||||||
transactionHashes: []util.Uint256{{1}},
|
transactionHashes: []util.Uint256{{1}},
|
||||||
minerTx: *transaction.NewMinerTX(),
|
|
||||||
nextConsensus: util.Uint160{1, 2},
|
nextConsensus: util.Uint160{1, 2},
|
||||||
}
|
}
|
||||||
p1 := new(Payload)
|
p1 := new(Payload)
|
||||||
|
|
|
@ -2,7 +2,6 @@ package block
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/Workiva/go-datastructures/queue"
|
"github.com/Workiva/go-datastructures/queue"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
|
@ -16,6 +15,9 @@ type Block struct {
|
||||||
// The base of the block.
|
// The base of the block.
|
||||||
Base
|
Base
|
||||||
|
|
||||||
|
// Primary index and nonce
|
||||||
|
ConsensusData ConsensusData `json:"consensus_data"`
|
||||||
|
|
||||||
// Transaction list.
|
// Transaction list.
|
||||||
Transactions []*transaction.Transaction `json:"tx"`
|
Transactions []*transaction.Transaction `json:"tx"`
|
||||||
|
|
||||||
|
@ -30,10 +32,12 @@ func (b *Block) Header() *Header {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func merkleTreeFromTransactions(txes []*transaction.Transaction) (*hash.MerkleTree, error) {
|
// computeMerkleTree computes Merkle tree based on actual block's data.
|
||||||
hashes := make([]util.Uint256, len(txes))
|
func (b *Block) computeMerkleTree() (*hash.MerkleTree, error) {
|
||||||
for i, tx := range txes {
|
hashes := make([]util.Uint256, len(b.Transactions)+1)
|
||||||
hashes[i] = tx.Hash()
|
hashes[0] = b.ConsensusData.Hash()
|
||||||
|
for i, tx := range b.Transactions {
|
||||||
|
hashes[i+1] = tx.Hash()
|
||||||
}
|
}
|
||||||
|
|
||||||
return hash.NewMerkleTree(hashes)
|
return hash.NewMerkleTree(hashes)
|
||||||
|
@ -41,7 +45,7 @@ func merkleTreeFromTransactions(txes []*transaction.Transaction) (*hash.MerkleTr
|
||||||
|
|
||||||
// RebuildMerkleRoot rebuilds the merkleroot of the block.
|
// RebuildMerkleRoot rebuilds the merkleroot of the block.
|
||||||
func (b *Block) RebuildMerkleRoot() error {
|
func (b *Block) RebuildMerkleRoot() error {
|
||||||
merkle, err := merkleTreeFromTransactions(b.Transactions)
|
merkle, err := b.computeMerkleTree()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -52,21 +56,18 @@ func (b *Block) RebuildMerkleRoot() error {
|
||||||
|
|
||||||
// Verify verifies the integrity of the block.
|
// Verify verifies the integrity of the block.
|
||||||
func (b *Block) Verify() error {
|
func (b *Block) Verify() error {
|
||||||
// There has to be some transaction inside.
|
if b.Transactions != nil {
|
||||||
if len(b.Transactions) == 0 {
|
hashes := map[util.Uint256]bool{}
|
||||||
return errors.New("no transactions")
|
for _, tx := range b.Transactions {
|
||||||
}
|
if !hashes[tx.Hash()] {
|
||||||
// The first TX has to be a miner transaction.
|
hashes[tx.Hash()] = true
|
||||||
if b.Transactions[0].Type != transaction.MinerType {
|
} else {
|
||||||
return fmt.Errorf("the first transaction is %s", b.Transactions[0].Type)
|
return errors.New("transaction duplication is not allowed")
|
||||||
}
|
|
||||||
// If the first TX is a minerTX then all others cant.
|
|
||||||
for _, tx := range b.Transactions[1:] {
|
|
||||||
if tx.Type == transaction.MinerType {
|
|
||||||
return fmt.Errorf("miner transaction %s is not the first one", tx.Hash().StringLE())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
merkle, err := merkleTreeFromTransactions(b.Transactions)
|
}
|
||||||
|
|
||||||
|
merkle, err := b.computeMerkleTree()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -92,13 +93,19 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) {
|
||||||
|
|
||||||
block.Script.DecodeBinary(br)
|
block.Script.DecodeBinary(br)
|
||||||
|
|
||||||
lenTX := br.ReadVarUint()
|
lenHashes := br.ReadVarUint()
|
||||||
|
if lenHashes > 0 {
|
||||||
|
var consensusDataHash util.Uint256
|
||||||
|
consensusDataHash.DecodeBinary(br)
|
||||||
|
lenTX := lenHashes - 1
|
||||||
block.Transactions = make([]*transaction.Transaction, lenTX)
|
block.Transactions = make([]*transaction.Transaction, lenTX)
|
||||||
for i := 0; i < int(lenTX); i++ {
|
for i := 0; i < int(lenTX); i++ {
|
||||||
var hash util.Uint256
|
var hash util.Uint256
|
||||||
hash.DecodeBinary(br)
|
hash.DecodeBinary(br)
|
||||||
block.Transactions[i] = transaction.NewTrimmedTX(hash)
|
block.Transactions[i] = transaction.NewTrimmedTX(hash)
|
||||||
}
|
}
|
||||||
|
block.ConsensusData.DecodeBinary(br)
|
||||||
|
}
|
||||||
|
|
||||||
return block, br.Err
|
return block, br.Err
|
||||||
}
|
}
|
||||||
|
@ -112,14 +119,20 @@ func (b *Block) Trim() ([]byte, error) {
|
||||||
buf.WriteB(1)
|
buf.WriteB(1)
|
||||||
b.Script.EncodeBinary(buf.BinWriter)
|
b.Script.EncodeBinary(buf.BinWriter)
|
||||||
|
|
||||||
buf.WriteVarUint(uint64(len(b.Transactions)))
|
buf.WriteVarUint(uint64(len(b.Transactions)) + 1)
|
||||||
|
hash := b.ConsensusData.Hash()
|
||||||
|
hash.EncodeBinary(buf.BinWriter)
|
||||||
|
|
||||||
for _, tx := range b.Transactions {
|
for _, tx := range b.Transactions {
|
||||||
h := tx.Hash()
|
h := tx.Hash()
|
||||||
h.EncodeBinary(buf.BinWriter)
|
h.EncodeBinary(buf.BinWriter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.ConsensusData.EncodeBinary(buf.BinWriter)
|
||||||
if buf.Err != nil {
|
if buf.Err != nil {
|
||||||
return nil, buf.Err
|
return nil, buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf.Bytes(), nil
|
return buf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,14 +140,31 @@ func (b *Block) Trim() ([]byte, error) {
|
||||||
// Serializable interface.
|
// Serializable interface.
|
||||||
func (b *Block) DecodeBinary(br *io.BinReader) {
|
func (b *Block) DecodeBinary(br *io.BinReader) {
|
||||||
b.Base.DecodeBinary(br)
|
b.Base.DecodeBinary(br)
|
||||||
br.ReadArray(&b.Transactions)
|
contentsCount := br.ReadVarUint()
|
||||||
|
if contentsCount == 0 {
|
||||||
|
br.Err = errors.New("invalid block format")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b.ConsensusData.DecodeBinary(br)
|
||||||
|
txes := make([]*transaction.Transaction, contentsCount-1)
|
||||||
|
for i := 0; i < int(contentsCount)-1; i++ {
|
||||||
|
tx := new(transaction.Transaction)
|
||||||
|
tx.DecodeBinary(br)
|
||||||
|
txes[i] = tx
|
||||||
|
}
|
||||||
|
b.Transactions = txes
|
||||||
|
br.Err = b.Verify()
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeBinary encodes the block to the given BinWriter, implementing
|
// EncodeBinary encodes the block to the given BinWriter, implementing
|
||||||
// Serializable interface.
|
// Serializable interface.
|
||||||
func (b *Block) EncodeBinary(bw *io.BinWriter) {
|
func (b *Block) EncodeBinary(bw *io.BinWriter) {
|
||||||
b.Base.EncodeBinary(bw)
|
b.Base.EncodeBinary(bw)
|
||||||
bw.WriteArray(b.Transactions)
|
bw.WriteVarUint(uint64(len(b.Transactions) + 1))
|
||||||
|
b.ConsensusData.EncodeBinary(bw)
|
||||||
|
for i := 0; i < len(b.Transactions); i++ {
|
||||||
|
b.Transactions[i].EncodeBinary(bw)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare implements the queue Item interface.
|
// Compare implements the queue Item interface.
|
||||||
|
|
|
@ -20,17 +20,15 @@ type Base struct {
|
||||||
// Root hash of a transaction list.
|
// Root hash of a transaction list.
|
||||||
MerkleRoot util.Uint256 `json:"merkleroot"`
|
MerkleRoot util.Uint256 `json:"merkleroot"`
|
||||||
|
|
||||||
|
// 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 uint32 `json:"time"`
|
Timestamp uint64 `json:"time"`
|
||||||
|
|
||||||
// index/height of the block
|
// index/height of the block
|
||||||
Index uint32 `json:"height"`
|
Index uint32 `json:"height"`
|
||||||
|
|
||||||
// Random number also called nonce
|
|
||||||
ConsensusData uint64 `json:"nonce"`
|
|
||||||
|
|
||||||
// Contract address of the next miner
|
// Contract address of the next miner
|
||||||
NextConsensus util.Uint160 `json:"next_consensus"`
|
NextConsensus util.Uint160 `json:"next_consensus"`
|
||||||
|
|
||||||
|
@ -117,9 +115,8 @@ func (b *Base) encodeHashableFields(bw *io.BinWriter) {
|
||||||
bw.WriteU32LE(b.Version)
|
bw.WriteU32LE(b.Version)
|
||||||
bw.WriteBytes(b.PrevHash[:])
|
bw.WriteBytes(b.PrevHash[:])
|
||||||
bw.WriteBytes(b.MerkleRoot[:])
|
bw.WriteBytes(b.MerkleRoot[:])
|
||||||
bw.WriteU32LE(b.Timestamp)
|
bw.WriteU64LE(b.Timestamp)
|
||||||
bw.WriteU32LE(b.Index)
|
bw.WriteU32LE(b.Index)
|
||||||
bw.WriteU64LE(b.ConsensusData)
|
|
||||||
bw.WriteBytes(b.NextConsensus[:])
|
bw.WriteBytes(b.NextConsensus[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,9 +126,8 @@ func (b *Base) decodeHashableFields(br *io.BinReader) {
|
||||||
b.Version = br.ReadU32LE()
|
b.Version = br.ReadU32LE()
|
||||||
br.ReadBytes(b.PrevHash[:])
|
br.ReadBytes(b.PrevHash[:])
|
||||||
br.ReadBytes(b.MerkleRoot[:])
|
br.ReadBytes(b.MerkleRoot[:])
|
||||||
b.Timestamp = br.ReadU32LE()
|
b.Timestamp = br.ReadU64LE()
|
||||||
b.Index = br.ReadU32LE()
|
b.Index = br.ReadU32LE()
|
||||||
b.ConsensusData = br.ReadU64LE()
|
|
||||||
br.ReadBytes(b.NextConsensus[:])
|
br.ReadBytes(b.NextConsensus[:])
|
||||||
|
|
||||||
// Make the hash of the block here so we dont need to do this
|
// Make the hash of the block here so we dont need to do this
|
||||||
|
|
|
@ -71,17 +71,19 @@ func newDumbBlock() *Block {
|
||||||
Version: 0,
|
Version: 0,
|
||||||
PrevHash: hash.Sha256([]byte("a")),
|
PrevHash: hash.Sha256([]byte("a")),
|
||||||
MerkleRoot: hash.Sha256([]byte("b")),
|
MerkleRoot: hash.Sha256([]byte("b")),
|
||||||
Timestamp: uint32(100500),
|
Timestamp: 100500,
|
||||||
Index: 1,
|
Index: 1,
|
||||||
ConsensusData: 1111,
|
|
||||||
NextConsensus: hash.Hash160([]byte("a")),
|
NextConsensus: hash.Hash160([]byte("a")),
|
||||||
Script: transaction.Witness{
|
Script: transaction.Witness{
|
||||||
VerificationScript: []byte{0x51}, // PUSH1
|
VerificationScript: []byte{0x51}, // PUSH1
|
||||||
InvocationScript: []byte{0x61}, // NOP
|
InvocationScript: []byte{0x61}, // NOP
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ConsensusData: ConsensusData{
|
||||||
|
PrimaryIndex: 0,
|
||||||
|
Nonce: 1111,
|
||||||
|
},
|
||||||
Transactions: []*transaction.Transaction{
|
Transactions: []*transaction.Transaction{
|
||||||
transaction.NewMinerTX(),
|
|
||||||
transaction.NewIssueTX(),
|
transaction.NewIssueTX(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -99,25 +101,9 @@ func TestBlockVerify(t *testing.T) {
|
||||||
assert.Nil(t, block.RebuildMerkleRoot())
|
assert.Nil(t, block.RebuildMerkleRoot())
|
||||||
assert.Nil(t, block.Verify())
|
assert.Nil(t, block.Verify())
|
||||||
|
|
||||||
block.Transactions = []*transaction.Transaction{
|
block.Transactions = []*transaction.Transaction{}
|
||||||
transaction.NewIssueTX(),
|
|
||||||
transaction.NewMinerTX(),
|
|
||||||
}
|
|
||||||
assert.NoError(t, block.RebuildMerkleRoot())
|
assert.NoError(t, block.RebuildMerkleRoot())
|
||||||
assert.NotNil(t, block.Verify())
|
assert.Nil(t, block.Verify())
|
||||||
|
|
||||||
block.Transactions = []*transaction.Transaction{
|
|
||||||
transaction.NewIssueTX(),
|
|
||||||
transaction.NewMinerTX(),
|
|
||||||
}
|
|
||||||
assert.NoError(t, block.RebuildMerkleRoot())
|
|
||||||
assert.NotNil(t, block.Verify())
|
|
||||||
block.Transactions = []*transaction.Transaction{
|
|
||||||
transaction.NewMinerTX(),
|
|
||||||
transaction.NewIssueTX(),
|
|
||||||
transaction.NewIssueTX(),
|
|
||||||
}
|
|
||||||
assert.NotNil(t, block.Verify())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO NEO3.0: Update binary
|
//TODO NEO3.0: Update binary
|
||||||
|
|
52
pkg/core/block/consensus_data.go
Normal file
52
pkg/core/block/consensus_data.go
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
package block
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ConsensusData represents primary index and nonce of block in the chain.
|
||||||
|
type ConsensusData struct {
|
||||||
|
// Primary index
|
||||||
|
PrimaryIndex uint32 `json:"primary"`
|
||||||
|
// Random number
|
||||||
|
Nonce uint64 `json:"nonce"`
|
||||||
|
// Hash of the ConsensusData (single SHA256)
|
||||||
|
hash util.Uint256
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeBinary implements Serializable interface.
|
||||||
|
func (c *ConsensusData) DecodeBinary(br *io.BinReader) {
|
||||||
|
c.PrimaryIndex = uint32(br.ReadVarUint())
|
||||||
|
c.Nonce = br.ReadU64LE()
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeBinary encodes implements Serializable interface.
|
||||||
|
func (c *ConsensusData) EncodeBinary(bw *io.BinWriter) {
|
||||||
|
bw.WriteVarUint(uint64(c.PrimaryIndex))
|
||||||
|
bw.WriteU64LE(c.Nonce)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash returns the hash of the consensus data.
|
||||||
|
func (c *ConsensusData) Hash() util.Uint256 {
|
||||||
|
if c.hash.Equals(util.Uint256{}) {
|
||||||
|
if c.createHash() != nil {
|
||||||
|
panic("failed to compute hash!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c.hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// createHash creates the hash of the consensus data.
|
||||||
|
func (c *ConsensusData) createHash() error {
|
||||||
|
buf := io.NewBufBinWriter()
|
||||||
|
c.EncodeBinary(buf.BinWriter)
|
||||||
|
if buf.Err != nil {
|
||||||
|
return buf.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
b := buf.Bytes()
|
||||||
|
c.hash = hash.Sha256(b)
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -16,9 +16,8 @@ func TestHeaderEncodeDecode(t *testing.T) {
|
||||||
Version: 0,
|
Version: 0,
|
||||||
PrevHash: hash.Sha256([]byte("prevhash")),
|
PrevHash: hash.Sha256([]byte("prevhash")),
|
||||||
MerkleRoot: hash.Sha256([]byte("merkleroot")),
|
MerkleRoot: hash.Sha256([]byte("merkleroot")),
|
||||||
Timestamp: uint32(time.Now().UTC().Unix()),
|
Timestamp: uint64(time.Now().UTC().Unix() * 1000),
|
||||||
Index: 3445,
|
Index: 3445,
|
||||||
ConsensusData: 394949,
|
|
||||||
NextConsensus: util.Uint160{},
|
NextConsensus: util.Uint160{},
|
||||||
Script: transaction.Witness{
|
Script: transaction.Witness{
|
||||||
InvocationScript: []byte{0x10},
|
InvocationScript: []byte{0x10},
|
||||||
|
@ -34,7 +33,6 @@ func TestHeaderEncodeDecode(t *testing.T) {
|
||||||
assert.Equal(t, header.PrevHash, headerDecode.PrevHash, "expected both prev hashes to be equal")
|
assert.Equal(t, header.PrevHash, headerDecode.PrevHash, "expected both prev hashes to be equal")
|
||||||
assert.Equal(t, header.MerkleRoot, headerDecode.MerkleRoot, "expected both merkle roots to be equal")
|
assert.Equal(t, header.MerkleRoot, headerDecode.MerkleRoot, "expected both merkle roots to be equal")
|
||||||
assert.Equal(t, header.Index, headerDecode.Index, "expected both indexes to be equal")
|
assert.Equal(t, header.Index, headerDecode.Index, "expected both indexes to be equal")
|
||||||
assert.Equal(t, header.ConsensusData, headerDecode.ConsensusData, "expected both consensus data fields to be equal")
|
|
||||||
assert.Equal(t, header.NextConsensus, headerDecode.NextConsensus, "expected both next consensus fields to be equal")
|
assert.Equal(t, header.NextConsensus, headerDecode.NextConsensus, "expected both next consensus fields to be equal")
|
||||||
assert.Equal(t, header.Script.InvocationScript, headerDecode.Script.InvocationScript, "expected equal invocation scripts")
|
assert.Equal(t, header.Script.InvocationScript, headerDecode.Script.InvocationScript, "expected equal invocation scripts")
|
||||||
assert.Equal(t, header.Script.VerificationScript, headerDecode.Script.VerificationScript, "expected equal verification scripts")
|
assert.Equal(t, header.Script.VerificationScript, headerDecode.Script.VerificationScript, "expected equal verification scripts")
|
||||||
|
|
|
@ -914,9 +914,6 @@ func (bc *Blockchain) GetBlock(hash util.Uint256) (*block.Block, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(block.Transactions) == 0 {
|
|
||||||
return nil, fmt.Errorf("only header is available")
|
|
||||||
}
|
|
||||||
for _, tx := range block.Transactions {
|
for _, tx := range block.Transactions {
|
||||||
stx, _, err := bc.dao.GetTransaction(tx.Hash())
|
stx, _, err := bc.dao.GetTransaction(tx.Hash())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1118,7 +1115,7 @@ func (bc *Blockchain) FeePerByte(t *transaction.Transaction) util.Fixed8 {
|
||||||
// NetworkFee returns network fee.
|
// NetworkFee returns network fee.
|
||||||
func (bc *Blockchain) NetworkFee(t *transaction.Transaction) util.Fixed8 {
|
func (bc *Blockchain) NetworkFee(t *transaction.Transaction) util.Fixed8 {
|
||||||
// https://github.com/neo-project/neo/blob/master-2.x/neo/Network/P2P/Payloads/ClaimTransaction.cs#L16
|
// https://github.com/neo-project/neo/blob/master-2.x/neo/Network/P2P/Payloads/ClaimTransaction.cs#L16
|
||||||
if t.Type == transaction.ClaimType || t.Type == transaction.MinerType {
|
if t.Type == transaction.ClaimType {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1455,7 +1452,7 @@ func (bc *Blockchain) verifyResults(t *transaction.Transaction, results []*trans
|
||||||
}
|
}
|
||||||
|
|
||||||
switch t.Type {
|
switch t.Type {
|
||||||
case transaction.MinerType, transaction.ClaimType:
|
case transaction.ClaimType:
|
||||||
for _, r := range resultsIssue {
|
for _, r := range resultsIssue {
|
||||||
if r.AssetID != UtilityTokenID() {
|
if r.AssetID != UtilityTokenID() {
|
||||||
return errors.New("miner or claim tx issues non-utility tokens")
|
return errors.New("miner or claim tx issues non-utility tokens")
|
||||||
|
|
|
@ -97,7 +97,7 @@ func TestScriptFromWitness(t *testing.T) {
|
||||||
|
|
||||||
func TestGetHeader(t *testing.T) {
|
func TestGetHeader(t *testing.T) {
|
||||||
bc := newTestChain(t)
|
bc := newTestChain(t)
|
||||||
tx := transaction.NewMinerTX()
|
tx := transaction.NewContractTX()
|
||||||
tx.ValidUntilBlock = bc.BlockHeight() + 1
|
tx.ValidUntilBlock = bc.BlockHeight() + 1
|
||||||
assert.Nil(t, addSender(tx))
|
assert.Nil(t, addSender(tx))
|
||||||
assert.Nil(t, signTx(bc, tx))
|
assert.Nil(t, signTx(bc, tx))
|
||||||
|
|
|
@ -61,12 +61,15 @@ func newBlock(cfg config.ProtocolConfiguration, index uint32, prev util.Uint256,
|
||||||
Base: block.Base{
|
Base: block.Base{
|
||||||
Version: 0,
|
Version: 0,
|
||||||
PrevHash: prev,
|
PrevHash: prev,
|
||||||
Timestamp: uint32(time.Now().UTC().Unix()) + index,
|
Timestamp: uint64(time.Now().UTC().Unix()) + uint64(index),
|
||||||
Index: index,
|
Index: index,
|
||||||
ConsensusData: 1111,
|
|
||||||
NextConsensus: witness.ScriptHash(),
|
NextConsensus: witness.ScriptHash(),
|
||||||
Script: witness,
|
Script: witness,
|
||||||
},
|
},
|
||||||
|
ConsensusData: block.ConsensusData{
|
||||||
|
PrimaryIndex: 0,
|
||||||
|
Nonce: 1111,
|
||||||
|
},
|
||||||
Transactions: txs,
|
Transactions: txs,
|
||||||
}
|
}
|
||||||
_ = b.RebuildMerkleRoot()
|
_ = b.RebuildMerkleRoot()
|
||||||
|
@ -80,17 +83,7 @@ func (bc *Blockchain) genBlocks(n int) ([]*block.Block, error) {
|
||||||
lastHash := bc.topBlock.Load().(*block.Block).Hash()
|
lastHash := bc.topBlock.Load().(*block.Block).Hash()
|
||||||
lastIndex := bc.topBlock.Load().(*block.Block).Index
|
lastIndex := bc.topBlock.Load().(*block.Block).Index
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
minerTx := transaction.NewMinerTXWithNonce(uint32(1234 + i))
|
blocks[i] = newBlock(bc.config, uint32(i)+lastIndex+1, lastHash)
|
||||||
minerTx.ValidUntilBlock = lastIndex + uint32(i) + 1
|
|
||||||
err := addSender(minerTx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = signTx(bc, minerTx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
blocks[i] = newBlock(bc.config, uint32(i)+lastIndex+1, lastHash, minerTx)
|
|
||||||
if err := bc.AddBlock(blocks[i]); err != nil {
|
if err := bc.AddBlock(blocks[i]); err != nil {
|
||||||
return blocks, err
|
return blocks, err
|
||||||
}
|
}
|
||||||
|
@ -130,17 +123,19 @@ func newDumbBlock() *block.Block {
|
||||||
Version: 0,
|
Version: 0,
|
||||||
PrevHash: hash.Sha256([]byte("a")),
|
PrevHash: hash.Sha256([]byte("a")),
|
||||||
MerkleRoot: hash.Sha256([]byte("b")),
|
MerkleRoot: hash.Sha256([]byte("b")),
|
||||||
Timestamp: uint32(100500),
|
Timestamp: 100500,
|
||||||
Index: 1,
|
Index: 1,
|
||||||
ConsensusData: 1111,
|
|
||||||
NextConsensus: hash.Hash160([]byte("a")),
|
NextConsensus: hash.Hash160([]byte("a")),
|
||||||
Script: transaction.Witness{
|
Script: transaction.Witness{
|
||||||
VerificationScript: []byte{0x51}, // PUSH1
|
VerificationScript: []byte{0x51}, // PUSH1
|
||||||
InvocationScript: []byte{0x61}, // NOP
|
InvocationScript: []byte{0x61}, // NOP
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ConsensusData: block.ConsensusData{
|
||||||
|
PrimaryIndex: 0,
|
||||||
|
Nonce: 1111,
|
||||||
|
},
|
||||||
Transactions: []*transaction.Transaction{
|
Transactions: []*transaction.Transaction{
|
||||||
{Type: transaction.MinerType},
|
|
||||||
{Type: transaction.IssueType},
|
{Type: transaction.IssueType},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -175,13 +170,6 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
return testNonce
|
return testNonce
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates new miner tx with specified validUntilBlock field
|
|
||||||
nextMinerTx := func(validUntilBlock uint32) *transaction.Transaction {
|
|
||||||
minerTx := transaction.NewMinerTXWithNonce(getNextNonce())
|
|
||||||
minerTx.ValidUntilBlock = validUntilBlock
|
|
||||||
return minerTx
|
|
||||||
}
|
|
||||||
|
|
||||||
var neoAmount = util.Fixed8FromInt64(99999000)
|
var neoAmount = util.Fixed8FromInt64(99999000)
|
||||||
var neoRemainder = util.Fixed8FromInt64(100000000) - neoAmount
|
var neoRemainder = util.Fixed8FromInt64(100000000) - neoAmount
|
||||||
bc := newTestChain(t)
|
bc := newTestChain(t)
|
||||||
|
@ -195,8 +183,8 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
// use output of issue tx from genesis block as an input
|
// use output of issue tx from genesis block as an input
|
||||||
genesisBlock, err := bc.GetBlock(bc.GetHeaderHash(0))
|
genesisBlock, err := bc.GetBlock(bc.GetHeaderHash(0))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 5, len(genesisBlock.Transactions))
|
require.Equal(t, 4, len(genesisBlock.Transactions))
|
||||||
h := genesisBlock.Transactions[3].Hash()
|
h := genesisBlock.Transactions[2].Hash()
|
||||||
txMoveNeo.AddInput(&transaction.Input{
|
txMoveNeo.AddInput(&transaction.Input{
|
||||||
PrevHash: h,
|
PrevHash: h,
|
||||||
PrevIndex: 0,
|
PrevIndex: 0,
|
||||||
|
@ -219,12 +207,8 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
Position: 1,
|
Position: 1,
|
||||||
})
|
})
|
||||||
txMoveNeo.Data = new(transaction.ContractTX)
|
txMoveNeo.Data = new(transaction.ContractTX)
|
||||||
|
require.NoError(t, signTx(bc, txMoveNeo))
|
||||||
minerTx := nextMinerTx(validUntilBlock)
|
b := bc.newBlock(txMoveNeo)
|
||||||
minerTx.Sender = neoOwner
|
|
||||||
|
|
||||||
require.NoError(t, signTx(bc, minerTx, txMoveNeo))
|
|
||||||
b := bc.newBlock(minerTx, txMoveNeo)
|
|
||||||
require.NoError(t, bc.AddBlock(b))
|
require.NoError(t, bc.AddBlock(b))
|
||||||
t.Logf("txMoveNeo: %s", txMoveNeo.Hash().StringLE())
|
t.Logf("txMoveNeo: %s", txMoveNeo.Hash().StringLE())
|
||||||
|
|
||||||
|
@ -258,10 +242,7 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
})
|
})
|
||||||
txNeoRound.Data = new(transaction.ContractTX)
|
txNeoRound.Data = new(transaction.ContractTX)
|
||||||
require.NoError(t, acc0.SignTx(txNeoRound))
|
require.NoError(t, acc0.SignTx(txNeoRound))
|
||||||
minerTx = nextMinerTx(validUntilBlock)
|
b = bc.newBlock(txNeoRound)
|
||||||
minerTx.Sender = priv0ScriptHash
|
|
||||||
require.NoError(t, acc0.SignTx(minerTx))
|
|
||||||
b = bc.newBlock(minerTx, txNeoRound)
|
|
||||||
require.NoError(t, bc.AddBlock(b))
|
require.NoError(t, bc.AddBlock(b))
|
||||||
t.Logf("txNeoRound: %s", txNeoRound.Hash().StringLE())
|
t.Logf("txNeoRound: %s", txNeoRound.Hash().StringLE())
|
||||||
|
|
||||||
|
@ -285,10 +266,7 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
Position: 0,
|
Position: 0,
|
||||||
})
|
})
|
||||||
require.NoError(t, acc0.SignTx(txClaim))
|
require.NoError(t, acc0.SignTx(txClaim))
|
||||||
minerTx = nextMinerTx(validUntilBlock)
|
b = bc.newBlock(txClaim)
|
||||||
minerTx.Sender = priv0ScriptHash
|
|
||||||
require.NoError(t, acc0.SignTx(minerTx))
|
|
||||||
b = bc.newBlock(minerTx, txClaim)
|
|
||||||
require.NoError(t, bc.AddBlock(b))
|
require.NoError(t, bc.AddBlock(b))
|
||||||
t.Logf("txClaim: %s", txClaim.Hash().StringLE())
|
t.Logf("txClaim: %s", txClaim.Hash().StringLE())
|
||||||
|
|
||||||
|
@ -331,10 +309,7 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
})
|
})
|
||||||
gasOwned -= invFee
|
gasOwned -= invFee
|
||||||
require.NoError(t, acc0.SignTx(txDeploy))
|
require.NoError(t, acc0.SignTx(txDeploy))
|
||||||
minerTx = nextMinerTx(validUntilBlock)
|
b = bc.newBlock(txDeploy)
|
||||||
minerTx.Sender = priv0ScriptHash
|
|
||||||
require.NoError(t, acc0.SignTx(minerTx))
|
|
||||||
b = bc.newBlock(minerTx, txDeploy)
|
|
||||||
require.NoError(t, bc.AddBlock(b))
|
require.NoError(t, bc.AddBlock(b))
|
||||||
t.Logf("txDeploy: %s", txDeploy.Hash().StringLE())
|
t.Logf("txDeploy: %s", txDeploy.Hash().StringLE())
|
||||||
|
|
||||||
|
@ -347,10 +322,7 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
txInv.ValidUntilBlock = validUntilBlock
|
txInv.ValidUntilBlock = validUntilBlock
|
||||||
txInv.Sender = priv0ScriptHash
|
txInv.Sender = priv0ScriptHash
|
||||||
require.NoError(t, acc0.SignTx(txInv))
|
require.NoError(t, acc0.SignTx(txInv))
|
||||||
minerTx = nextMinerTx(validUntilBlock)
|
b = bc.newBlock(txInv)
|
||||||
minerTx.Sender = priv0ScriptHash
|
|
||||||
require.NoError(t, acc0.SignTx(minerTx))
|
|
||||||
b = bc.newBlock(minerTx, txInv)
|
|
||||||
require.NoError(t, bc.AddBlock(b))
|
require.NoError(t, bc.AddBlock(b))
|
||||||
t.Logf("txInv: %s", txInv.Hash().StringLE())
|
t.Logf("txInv: %s", txInv.Hash().StringLE())
|
||||||
|
|
||||||
|
@ -376,10 +348,7 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
require.NoError(t, acc0.SignTx(txNeo0to1))
|
require.NoError(t, acc0.SignTx(txNeo0to1))
|
||||||
minerTx = nextMinerTx(validUntilBlock)
|
b = bc.newBlock(txNeo0to1)
|
||||||
minerTx.Sender = priv0ScriptHash
|
|
||||||
require.NoError(t, acc0.SignTx(minerTx))
|
|
||||||
b = bc.newBlock(minerTx, txNeo0to1)
|
|
||||||
require.NoError(t, bc.AddBlock(b))
|
require.NoError(t, bc.AddBlock(b))
|
||||||
|
|
||||||
sh := hash.Hash160(avm)
|
sh := hash.Hash160(avm)
|
||||||
|
@ -396,10 +365,7 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
transferTx.Sender = priv0ScriptHash
|
transferTx.Sender = priv0ScriptHash
|
||||||
require.NoError(t, acc0.SignTx(transferTx))
|
require.NoError(t, acc0.SignTx(transferTx))
|
||||||
|
|
||||||
minerTx = nextMinerTx(validUntilBlock)
|
b = bc.newBlock(initTx, transferTx)
|
||||||
minerTx.Sender = priv0ScriptHash
|
|
||||||
require.NoError(t, acc0.SignTx(minerTx))
|
|
||||||
b = bc.newBlock(minerTx, initTx, transferTx)
|
|
||||||
require.NoError(t, bc.AddBlock(b))
|
require.NoError(t, bc.AddBlock(b))
|
||||||
|
|
||||||
transferTx = newNEP5Transfer(sh, priv0.GetScriptHash(), priv1.GetScriptHash(), 123)
|
transferTx = newNEP5Transfer(sh, priv0.GetScriptHash(), priv1.GetScriptHash(), 123)
|
||||||
|
@ -408,10 +374,7 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
transferTx.Sender = priv0ScriptHash
|
transferTx.Sender = priv0ScriptHash
|
||||||
require.NoError(t, acc0.SignTx(transferTx))
|
require.NoError(t, acc0.SignTx(transferTx))
|
||||||
|
|
||||||
minerTx = nextMinerTx(validUntilBlock)
|
b = bc.newBlock(transferTx)
|
||||||
minerTx.Sender = priv0ScriptHash
|
|
||||||
require.NoError(t, acc0.SignTx(minerTx))
|
|
||||||
b = bc.newBlock(minerTx, transferTx)
|
|
||||||
require.NoError(t, bc.AddBlock(b))
|
require.NoError(t, bc.AddBlock(b))
|
||||||
|
|
||||||
if saveChain {
|
if saveChain {
|
||||||
|
|
|
@ -48,16 +48,6 @@ func headerGetVersion(ic *interop.Context, v *vm.VM) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// headerGetConsensusData returns consensus data from the header.
|
|
||||||
func headerGetConsensusData(ic *interop.Context, v *vm.VM) error {
|
|
||||||
header, err := popHeaderFromVM(v)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
v.Estack().PushVal(header.ConsensusData)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// headerGetMerkleRoot returns version from the header.
|
// headerGetMerkleRoot returns version from the header.
|
||||||
func headerGetMerkleRoot(ic *interop.Context, v *vm.VM) error {
|
func headerGetMerkleRoot(ic *interop.Context, v *vm.VM) error {
|
||||||
header, err := popHeaderFromVM(v)
|
header, err := popHeaderFromVM(v)
|
||||||
|
|
|
@ -136,16 +136,6 @@ func TestHeaderGetVersion_Negative(t *testing.T) {
|
||||||
require.Errorf(t, err, "value is not a header or block")
|
require.Errorf(t, err, "value is not a header or block")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHeaderGetConsensusData(t *testing.T) {
|
|
||||||
v, block, context, chain := createVMAndPushBlock(t)
|
|
||||||
defer chain.Close()
|
|
||||||
|
|
||||||
err := headerGetConsensusData(context, v)
|
|
||||||
require.NoError(t, err)
|
|
||||||
value := v.Estack().Pop().Value().(*big.Int)
|
|
||||||
require.Equal(t, block.ConsensusData, value.Uint64())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHeaderGetMerkleRoot(t *testing.T) {
|
func TestHeaderGetMerkleRoot(t *testing.T) {
|
||||||
v, block, context, chain := createVMAndPushBlock(t)
|
v, block, context, chain := createVMAndPushBlock(t)
|
||||||
defer chain.Close()
|
defer chain.Close()
|
||||||
|
|
|
@ -151,7 +151,6 @@ var neoInterops = []interop.Function{
|
||||||
{Name: "Neo.Enumerator.Create", Func: enumerator.Create, Price: 1},
|
{Name: "Neo.Enumerator.Create", Func: enumerator.Create, Price: 1},
|
||||||
{Name: "Neo.Enumerator.Next", Func: enumerator.Next, Price: 1},
|
{Name: "Neo.Enumerator.Next", Func: enumerator.Next, Price: 1},
|
||||||
{Name: "Neo.Enumerator.Value", Func: enumerator.Value, Price: 1},
|
{Name: "Neo.Enumerator.Value", Func: enumerator.Value, Price: 1},
|
||||||
{Name: "Neo.Header.GetConsensusData", Func: headerGetConsensusData, Price: 1},
|
|
||||||
{Name: "Neo.Header.GetHash", Func: headerGetHash, Price: 1},
|
{Name: "Neo.Header.GetHash", Func: headerGetHash, Price: 1},
|
||||||
{Name: "Neo.Header.GetIndex", Func: headerGetIndex, Price: 1},
|
{Name: "Neo.Header.GetIndex", Func: headerGetIndex, Price: 1},
|
||||||
{Name: "Neo.Header.GetMerkleRoot", Func: headerGetMerkleRoot, Price: 1},
|
{Name: "Neo.Header.GetMerkleRoot", Func: headerGetMerkleRoot, Price: 1},
|
||||||
|
@ -229,7 +228,6 @@ var neoInterops = []interop.Function{
|
||||||
{Name: "AntShares.Contract.GetScript", Func: contractGetScript, Price: 1},
|
{Name: "AntShares.Contract.GetScript", Func: contractGetScript, Price: 1},
|
||||||
{Name: "AntShares.Contract.GetStorageContext", Func: contractGetStorageContext, Price: 1},
|
{Name: "AntShares.Contract.GetStorageContext", Func: contractGetStorageContext, Price: 1},
|
||||||
{Name: "AntShares.Contract.Migrate", Func: contractMigrate, Price: 0},
|
{Name: "AntShares.Contract.Migrate", Func: contractMigrate, Price: 0},
|
||||||
{Name: "AntShares.Header.GetConsensusData", Func: headerGetConsensusData, Price: 1},
|
|
||||||
{Name: "AntShares.Header.GetHash", Func: headerGetHash, Price: 1},
|
{Name: "AntShares.Header.GetHash", Func: headerGetHash, Price: 1},
|
||||||
{Name: "AntShares.Header.GetMerkleRoot", Func: headerGetMerkleRoot, Price: 1},
|
{Name: "AntShares.Header.GetMerkleRoot", Func: headerGetMerkleRoot, Price: 1},
|
||||||
{Name: "AntShares.Header.GetNextConsensus", Func: headerGetNextConsensus, Price: 1},
|
{Name: "AntShares.Header.GetNextConsensus", Func: headerGetNextConsensus, Price: 1},
|
||||||
|
|
|
@ -51,7 +51,6 @@ func TestUnexpectedNonInterops(t *testing.T) {
|
||||||
contractGetScript,
|
contractGetScript,
|
||||||
contractGetStorageContext,
|
contractGetStorageContext,
|
||||||
contractIsPayable,
|
contractIsPayable,
|
||||||
headerGetConsensusData,
|
|
||||||
headerGetHash,
|
headerGetHash,
|
||||||
headerGetIndex,
|
headerGetIndex,
|
||||||
headerGetMerkleRoot,
|
headerGetMerkleRoot,
|
||||||
|
|
|
@ -36,7 +36,8 @@ func (fs *FeerStub) SystemFee(*transaction.Transaction) util.Fixed8 {
|
||||||
|
|
||||||
func testMemPoolAddRemoveWithFeer(t *testing.T, fs Feer) {
|
func testMemPoolAddRemoveWithFeer(t *testing.T, fs Feer) {
|
||||||
mp := NewMemPool(10)
|
mp := NewMemPool(10)
|
||||||
tx := transaction.NewMinerTXWithNonce(0)
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = 0
|
||||||
_, _, ok := mp.TryGetValue(tx.Hash())
|
_, _, ok := mp.TryGetValue(tx.Hash())
|
||||||
require.Equal(t, false, ok)
|
require.Equal(t, false, ok)
|
||||||
require.NoError(t, mp.Add(tx, fs))
|
require.NoError(t, mp.Add(tx, fs))
|
||||||
|
@ -72,8 +73,8 @@ func TestMemPoolAddRemoveWithInputsAndClaims(t *testing.T) {
|
||||||
mpLessClaims := func(i, j int) bool {
|
mpLessClaims := func(i, j int) bool {
|
||||||
return mp.claims[i].Cmp(mp.claims[j]) < 0
|
return mp.claims[i].Cmp(mp.claims[j]) < 0
|
||||||
}
|
}
|
||||||
|
txm1 := transaction.NewContractTX()
|
||||||
txm1 := transaction.NewMinerTXWithNonce(1)
|
txm1.Nonce = 1
|
||||||
txc1, claim1 := newClaimTX()
|
txc1, claim1 := newClaimTX()
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
txm1.Inputs = append(txm1.Inputs, transaction.Input{PrevHash: hash1, PrevIndex: uint16(100 - i)})
|
txm1.Inputs = append(txm1.Inputs, transaction.Input{PrevHash: hash1, PrevIndex: uint16(100 - i)})
|
||||||
|
@ -87,7 +88,8 @@ func TestMemPoolAddRemoveWithInputsAndClaims(t *testing.T) {
|
||||||
assert.Equal(t, len(claim1.Claims), len(mp.claims))
|
assert.Equal(t, len(claim1.Claims), len(mp.claims))
|
||||||
assert.True(t, sort.SliceIsSorted(mp.claims, mpLessClaims))
|
assert.True(t, sort.SliceIsSorted(mp.claims, mpLessClaims))
|
||||||
|
|
||||||
txm2 := transaction.NewMinerTXWithNonce(1)
|
txm2 := transaction.NewContractTX()
|
||||||
|
txm2.Nonce = 1
|
||||||
txc2, claim2 := newClaimTX()
|
txc2, claim2 := newClaimTX()
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
txm2.Inputs = append(txm2.Inputs, transaction.Input{PrevHash: hash2, PrevIndex: uint16(i)})
|
txm2.Inputs = append(txm2.Inputs, transaction.Input{PrevHash: hash2, PrevIndex: uint16(i)})
|
||||||
|
@ -128,19 +130,22 @@ func TestMemPoolAddRemoveWithInputsAndClaims(t *testing.T) {
|
||||||
|
|
||||||
func TestMemPoolVerifyInputs(t *testing.T) {
|
func TestMemPoolVerifyInputs(t *testing.T) {
|
||||||
mp := NewMemPool(10)
|
mp := NewMemPool(10)
|
||||||
tx := transaction.NewMinerTXWithNonce(1)
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = 1
|
||||||
inhash1 := random.Uint256()
|
inhash1 := random.Uint256()
|
||||||
tx.Inputs = append(tx.Inputs, transaction.Input{PrevHash: inhash1, PrevIndex: 0})
|
tx.Inputs = append(tx.Inputs, transaction.Input{PrevHash: inhash1, PrevIndex: 0})
|
||||||
require.Equal(t, true, mp.Verify(tx))
|
require.Equal(t, true, mp.Verify(tx))
|
||||||
require.NoError(t, mp.Add(tx, &FeerStub{}))
|
require.NoError(t, mp.Add(tx, &FeerStub{}))
|
||||||
|
|
||||||
tx2 := transaction.NewMinerTXWithNonce(2)
|
tx2 := transaction.NewContractTX()
|
||||||
|
tx2.Nonce = 2
|
||||||
inhash2 := random.Uint256()
|
inhash2 := random.Uint256()
|
||||||
tx2.Inputs = append(tx2.Inputs, transaction.Input{PrevHash: inhash2, PrevIndex: 0})
|
tx2.Inputs = append(tx2.Inputs, transaction.Input{PrevHash: inhash2, PrevIndex: 0})
|
||||||
require.Equal(t, true, mp.Verify(tx2))
|
require.Equal(t, true, mp.Verify(tx2))
|
||||||
require.NoError(t, mp.Add(tx2, &FeerStub{}))
|
require.NoError(t, mp.Add(tx2, &FeerStub{}))
|
||||||
|
|
||||||
tx3 := transaction.NewMinerTXWithNonce(3)
|
tx3 := transaction.NewContractTX()
|
||||||
|
tx3.Nonce = 3
|
||||||
// Different index number, but the same PrevHash as in tx1.
|
// Different index number, but the same PrevHash as in tx1.
|
||||||
tx3.Inputs = append(tx3.Inputs, transaction.Input{PrevHash: inhash1, PrevIndex: 1})
|
tx3.Inputs = append(tx3.Inputs, transaction.Input{PrevHash: inhash1, PrevIndex: 1})
|
||||||
require.Equal(t, true, mp.Verify(tx3))
|
require.Equal(t, true, mp.Verify(tx3))
|
||||||
|
@ -211,7 +216,8 @@ func TestOverCapacity(t *testing.T) {
|
||||||
mp := NewMemPool(mempoolSize)
|
mp := NewMemPool(mempoolSize)
|
||||||
|
|
||||||
for i := 0; i < mempoolSize; i++ {
|
for i := 0; i < mempoolSize; i++ {
|
||||||
tx := transaction.NewMinerTXWithNonce(uint32(i))
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = uint32(i)
|
||||||
require.NoError(t, mp.Add(tx, fs))
|
require.NoError(t, mp.Add(tx, fs))
|
||||||
}
|
}
|
||||||
txcnt := uint32(mempoolSize)
|
txcnt := uint32(mempoolSize)
|
||||||
|
@ -231,7 +237,8 @@ func TestOverCapacity(t *testing.T) {
|
||||||
// Fees are also prioritized.
|
// Fees are also prioritized.
|
||||||
fs.netFee = util.Fixed8FromFloat(0.0001)
|
fs.netFee = util.Fixed8FromFloat(0.0001)
|
||||||
for i := 0; i < mempoolSize-1; i++ {
|
for i := 0; i < mempoolSize-1; i++ {
|
||||||
tx := transaction.NewMinerTXWithNonce(txcnt)
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = txcnt
|
||||||
txcnt++
|
txcnt++
|
||||||
require.NoError(t, mp.Add(tx, fs))
|
require.NoError(t, mp.Add(tx, fs))
|
||||||
require.Equal(t, mempoolSize, mp.Count())
|
require.Equal(t, mempoolSize, mp.Count())
|
||||||
|
@ -239,7 +246,8 @@ func TestOverCapacity(t *testing.T) {
|
||||||
}
|
}
|
||||||
// Less prioritized txes are not allowed anymore.
|
// Less prioritized txes are not allowed anymore.
|
||||||
fs.netFee = util.Fixed8FromFloat(0.00001)
|
fs.netFee = util.Fixed8FromFloat(0.00001)
|
||||||
tx := transaction.NewMinerTXWithNonce(txcnt)
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = txcnt
|
||||||
txcnt++
|
txcnt++
|
||||||
require.Error(t, mp.Add(tx, fs))
|
require.Error(t, mp.Add(tx, fs))
|
||||||
require.Equal(t, mempoolSize, mp.Count())
|
require.Equal(t, mempoolSize, mp.Count())
|
||||||
|
@ -250,7 +258,8 @@ func TestOverCapacity(t *testing.T) {
|
||||||
|
|
||||||
// Low net fee, but higher per-byte fee is still a better combination.
|
// Low net fee, but higher per-byte fee is still a better combination.
|
||||||
fs.perByteFee = util.Fixed8FromFloat(0.001)
|
fs.perByteFee = util.Fixed8FromFloat(0.001)
|
||||||
tx = transaction.NewMinerTXWithNonce(txcnt)
|
tx = transaction.NewContractTX()
|
||||||
|
tx.Nonce = txcnt
|
||||||
txcnt++
|
txcnt++
|
||||||
require.NoError(t, mp.Add(tx, fs))
|
require.NoError(t, mp.Add(tx, fs))
|
||||||
require.Equal(t, mempoolSize, mp.Count())
|
require.Equal(t, mempoolSize, mp.Count())
|
||||||
|
@ -259,7 +268,8 @@ func TestOverCapacity(t *testing.T) {
|
||||||
// High priority always wins over low priority.
|
// High priority always wins over low priority.
|
||||||
fs.lowPriority = false
|
fs.lowPriority = false
|
||||||
for i := 0; i < mempoolSize; i++ {
|
for i := 0; i < mempoolSize; i++ {
|
||||||
tx := transaction.NewMinerTXWithNonce(txcnt)
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = txcnt
|
||||||
txcnt++
|
txcnt++
|
||||||
require.NoError(t, mp.Add(tx, fs))
|
require.NoError(t, mp.Add(tx, fs))
|
||||||
require.Equal(t, mempoolSize, mp.Count())
|
require.Equal(t, mempoolSize, mp.Count())
|
||||||
|
@ -267,7 +277,8 @@ func TestOverCapacity(t *testing.T) {
|
||||||
}
|
}
|
||||||
// Good luck with low priority now.
|
// Good luck with low priority now.
|
||||||
fs.lowPriority = true
|
fs.lowPriority = true
|
||||||
tx = transaction.NewMinerTXWithNonce(txcnt)
|
tx = transaction.NewContractTX()
|
||||||
|
tx.Nonce = txcnt
|
||||||
require.Error(t, mp.Add(tx, fs))
|
require.Error(t, mp.Add(tx, fs))
|
||||||
require.Equal(t, mempoolSize, mp.Count())
|
require.Equal(t, mempoolSize, mp.Count())
|
||||||
require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes)))
|
require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes)))
|
||||||
|
@ -280,7 +291,8 @@ func TestGetVerified(t *testing.T) {
|
||||||
|
|
||||||
txes := make([]*transaction.Transaction, 0, mempoolSize)
|
txes := make([]*transaction.Transaction, 0, mempoolSize)
|
||||||
for i := 0; i < mempoolSize; i++ {
|
for i := 0; i < mempoolSize; i++ {
|
||||||
tx := transaction.NewMinerTXWithNonce(uint32(i))
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = uint32(i)
|
||||||
txes = append(txes, tx)
|
txes = append(txes, tx)
|
||||||
require.NoError(t, mp.Add(tx, fs))
|
require.NoError(t, mp.Add(tx, fs))
|
||||||
}
|
}
|
||||||
|
@ -305,7 +317,8 @@ func TestRemoveStale(t *testing.T) {
|
||||||
txes1 := make([]*transaction.Transaction, 0, mempoolSize/2)
|
txes1 := make([]*transaction.Transaction, 0, mempoolSize/2)
|
||||||
txes2 := make([]*transaction.Transaction, 0, mempoolSize/2)
|
txes2 := make([]*transaction.Transaction, 0, mempoolSize/2)
|
||||||
for i := 0; i < mempoolSize; i++ {
|
for i := 0; i < mempoolSize; i++ {
|
||||||
tx := transaction.NewMinerTXWithNonce(uint32(i))
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = uint32(i)
|
||||||
if i%2 == 0 {
|
if i%2 == 0 {
|
||||||
txes1 = append(txes1, tx)
|
txes1 = append(txes1, tx)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,7 +2,6 @@ package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/rand"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
|
@ -90,13 +89,11 @@ func TestNativeContract_Invoke(t *testing.T) {
|
||||||
emit.AppCallWithOperationAndArgs(w.BinWriter, tn.Metadata().Hash, "sum", int64(14), int64(28))
|
emit.AppCallWithOperationAndArgs(w.BinWriter, tn.Metadata().Hash, "sum", int64(14), int64(28))
|
||||||
script := w.Bytes()
|
script := w.Bytes()
|
||||||
tx := transaction.NewInvocationTX(script, 0)
|
tx := transaction.NewInvocationTX(script, 0)
|
||||||
mn := transaction.NewMinerTXWithNonce(rand.Uint32())
|
|
||||||
validUntil := chain.blockHeight + 1
|
validUntil := chain.blockHeight + 1
|
||||||
tx.ValidUntilBlock = validUntil
|
tx.ValidUntilBlock = validUntil
|
||||||
mn.ValidUntilBlock = validUntil
|
require.NoError(t, addSender(tx))
|
||||||
require.NoError(t, addSender(tx, mn))
|
require.NoError(t, signTx(chain, tx))
|
||||||
require.NoError(t, signTx(chain, tx, mn))
|
b := chain.newBlock(tx)
|
||||||
b := chain.newBlock(mn, tx)
|
|
||||||
require.NoError(t, chain.AddBlock(b))
|
require.NoError(t, chain.AddBlock(b))
|
||||||
|
|
||||||
res, err := chain.GetAppExecResult(tx.Hash())
|
res, err := chain.GetAppExecResult(tx.Hash())
|
||||||
|
|
|
@ -20,7 +20,7 @@ type NEP5TransferLog struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NEP5TransferSize is a size of a marshaled NEP5Transfer struct in bytes.
|
// NEP5TransferSize is a size of a marshaled NEP5Transfer struct in bytes.
|
||||||
const NEP5TransferSize = util.Uint160Size*3 + 8 + 4 + 4 + util.Uint256Size
|
const NEP5TransferSize = util.Uint160Size*3 + 8 + 4 + 8 + util.Uint256Size
|
||||||
|
|
||||||
// NEP5Transfer represents a single NEP5 Transfer event.
|
// NEP5Transfer represents a single NEP5 Transfer event.
|
||||||
type NEP5Transfer struct {
|
type NEP5Transfer struct {
|
||||||
|
@ -36,7 +36,7 @@ type NEP5Transfer struct {
|
||||||
// Block is a number of block when the event occured.
|
// Block is a number of block when the event occured.
|
||||||
Block uint32
|
Block uint32
|
||||||
// Timestamp is the timestamp of the block where transfer occured.
|
// Timestamp is the timestamp of the block where transfer occured.
|
||||||
Timestamp uint32
|
Timestamp uint64
|
||||||
// Tx is a hash the transaction.
|
// Tx is a hash the transaction.
|
||||||
Tx util.Uint256
|
Tx util.Uint256
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ func (t *NEP5Transfer) EncodeBinary(w *io.BinWriter) {
|
||||||
w.WriteBytes(t.From[:])
|
w.WriteBytes(t.From[:])
|
||||||
w.WriteBytes(t.To[:])
|
w.WriteBytes(t.To[:])
|
||||||
w.WriteU32LE(t.Block)
|
w.WriteU32LE(t.Block)
|
||||||
w.WriteU32LE(t.Timestamp)
|
w.WriteU64LE(t.Timestamp)
|
||||||
w.WriteU64LE(uint64(t.Amount))
|
w.WriteU64LE(uint64(t.Amount))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +146,6 @@ func (t *NEP5Transfer) DecodeBinary(r *io.BinReader) {
|
||||||
r.ReadBytes(t.From[:])
|
r.ReadBytes(t.From[:])
|
||||||
r.ReadBytes(t.To[:])
|
r.ReadBytes(t.To[:])
|
||||||
t.Block = r.ReadU32LE()
|
t.Block = r.ReadU32LE()
|
||||||
t.Timestamp = r.ReadU32LE()
|
t.Timestamp = r.ReadU64LE()
|
||||||
t.Amount = int64(r.ReadU64LE())
|
t.Amount = int64(r.ReadU64LE())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
package transaction
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// MinerTX represents a miner transaction.
|
|
||||||
type MinerTX struct{}
|
|
||||||
|
|
||||||
// NewMinerTX creates Transaction of MinerType type.
|
|
||||||
func NewMinerTX() *Transaction {
|
|
||||||
return NewMinerTXWithNonce(rand.Uint32())
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMinerTXWithNonce creates Transaction of MinerType type with specified nonce.
|
|
||||||
func NewMinerTXWithNonce(nonce uint32) *Transaction {
|
|
||||||
return &Transaction{
|
|
||||||
Type: MinerType,
|
|
||||||
Version: 0,
|
|
||||||
Nonce: nonce,
|
|
||||||
Data: &MinerTX{},
|
|
||||||
Attributes: []Attribute{},
|
|
||||||
Inputs: []Input{},
|
|
||||||
Outputs: []Output{},
|
|
||||||
Scripts: []Witness{},
|
|
||||||
Trimmed: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeBinary implements Serializable interface.
|
|
||||||
func (tx *MinerTX) DecodeBinary(r *io.BinReader) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeBinary implements Serializable interface.
|
|
||||||
func (tx *MinerTX) EncodeBinary(w *io.BinWriter) {
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
package transaction
|
|
||||||
|
|
||||||
// TODO NEO3.0: Update binary
|
|
||||||
/*
|
|
||||||
func TestEncodeDecodeMiner(t *testing.T) {
|
|
||||||
// transaction from mainnet a1f219dc6be4c35eca172e65e02d4591045220221b1543f1a4b67b9e9442c264
|
|
||||||
rawtx := "0000fcd30e22000001e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c60c8000000000000001f72e68b4e39602912106d53b229378a082784b200"
|
|
||||||
tx := decodeTransaction(rawtx, t)
|
|
||||||
assert.Equal(t, MinerType, tx.Type)
|
|
||||||
assert.IsType(t, tx.Data, &MinerTX{})
|
|
||||||
assert.Equal(t, 0, int(tx.Version))
|
|
||||||
assert.Equal(t, uint32(571397116), tx.Nonce)
|
|
||||||
|
|
||||||
assert.Equal(t, "a1f219dc6be4c35eca172e65e02d4591045220221b1543f1a4b67b9e9442c264", tx.Hash().StringLE())
|
|
||||||
|
|
||||||
// Encode
|
|
||||||
data, err := testserdes.EncodeBinary(tx)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, rawtx, hex.EncodeToString(data))
|
|
||||||
}
|
|
||||||
*/
|
|
|
@ -148,9 +148,6 @@ func (t *Transaction) decodeData(r *io.BinReader) {
|
||||||
case InvocationType:
|
case InvocationType:
|
||||||
t.Data = &InvocationTX{Version: t.Version}
|
t.Data = &InvocationTX{Version: t.Version}
|
||||||
t.Data.(*InvocationTX).DecodeBinary(r)
|
t.Data.(*InvocationTX).DecodeBinary(r)
|
||||||
case MinerType:
|
|
||||||
t.Data = &MinerTX{}
|
|
||||||
t.Data.(*MinerTX).DecodeBinary(r)
|
|
||||||
case ClaimType:
|
case ClaimType:
|
||||||
t.Data = &ClaimTX{}
|
t.Data = &ClaimTX{}
|
||||||
t.Data.(*ClaimTX).DecodeBinary(r)
|
t.Data.(*ClaimTX).DecodeBinary(r)
|
||||||
|
@ -335,8 +332,6 @@ func (t *Transaction) UnmarshalJSON(data []byte) error {
|
||||||
}
|
}
|
||||||
t.Sender = sender
|
t.Sender = sender
|
||||||
switch tx.Type {
|
switch tx.Type {
|
||||||
case MinerType:
|
|
||||||
t.Data = &MinerTX{}
|
|
||||||
case ClaimType:
|
case ClaimType:
|
||||||
t.Data = &ClaimTX{
|
t.Data = &ClaimTX{
|
||||||
Claims: tx.Claims,
|
Claims: tx.Claims,
|
||||||
|
|
|
@ -120,12 +120,6 @@ func TestMarshalUnmarshalJSONContractTX(t *testing.T) {
|
||||||
testserdes.MarshalUnmarshalJSON(t, tx, new(Transaction))
|
testserdes.MarshalUnmarshalJSON(t, tx, new(Transaction))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMarshalUnmarshalJSONMinerTX(t *testing.T) {
|
|
||||||
tx := NewMinerTX()
|
|
||||||
|
|
||||||
testserdes.MarshalUnmarshalJSON(t, tx, new(Transaction))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMarshalUnmarshalJSONClaimTX(t *testing.T) {
|
func TestMarshalUnmarshalJSONClaimTX(t *testing.T) {
|
||||||
tx := &Transaction{
|
tx := &Transaction{
|
||||||
Type: ClaimType,
|
Type: ClaimType,
|
||||||
|
|
|
@ -11,7 +11,6 @@ type TXType uint8
|
||||||
|
|
||||||
// Constants for all valid transaction types.
|
// Constants for all valid transaction types.
|
||||||
const (
|
const (
|
||||||
MinerType TXType = 0x00
|
|
||||||
IssueType TXType = 0x01
|
IssueType TXType = 0x01
|
||||||
ClaimType TXType = 0x02
|
ClaimType TXType = 0x02
|
||||||
RegisterType TXType = 0x40
|
RegisterType TXType = 0x40
|
||||||
|
@ -22,8 +21,6 @@ const (
|
||||||
// String implements the stringer interface.
|
// String implements the stringer interface.
|
||||||
func (t TXType) String() string {
|
func (t TXType) String() string {
|
||||||
switch t {
|
switch t {
|
||||||
case MinerType:
|
|
||||||
return "MinerTransaction"
|
|
||||||
case IssueType:
|
case IssueType:
|
||||||
return "IssueTransaction"
|
return "IssueTransaction"
|
||||||
case ClaimType:
|
case ClaimType:
|
||||||
|
@ -58,8 +55,6 @@ func (t *TXType) UnmarshalJSON(data []byte) error {
|
||||||
// TXTypeFromString searches for TXType by string name.
|
// TXTypeFromString searches for TXType by string name.
|
||||||
func TXTypeFromString(jsonString string) (TXType, error) {
|
func TXTypeFromString(jsonString string) (TXType, error) {
|
||||||
switch jsonString = strings.TrimSpace(jsonString); jsonString {
|
switch jsonString = strings.TrimSpace(jsonString); jsonString {
|
||||||
case "MinerTransaction":
|
|
||||||
return MinerType, nil
|
|
||||||
case "IssueTransaction":
|
case "IssueTransaction":
|
||||||
return IssueType, nil
|
return IssueType, nil
|
||||||
case "ClaimTransaction":
|
case "ClaimTransaction":
|
||||||
|
|
|
@ -41,9 +41,8 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
|
||||||
base := block.Base{
|
base := block.Base{
|
||||||
Version: 0,
|
Version: 0,
|
||||||
PrevHash: util.Uint256{},
|
PrevHash: util.Uint256{},
|
||||||
Timestamp: uint32(time.Date(2016, 7, 15, 15, 8, 21, 0, time.UTC).Unix()),
|
Timestamp: uint64(time.Date(2016, 7, 15, 15, 8, 21, 0, time.UTC).Unix()),
|
||||||
Index: 0,
|
Index: 0,
|
||||||
ConsensusData: 2083236893,
|
|
||||||
NextConsensus: nextConsensus,
|
NextConsensus: nextConsensus,
|
||||||
Script: transaction.Witness{
|
Script: transaction.Witness{
|
||||||
InvocationScript: []byte{},
|
InvocationScript: []byte{},
|
||||||
|
@ -60,9 +59,6 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
|
||||||
}
|
}
|
||||||
scriptOut := hash.Hash160(rawScript)
|
scriptOut := hash.Hash160(rawScript)
|
||||||
|
|
||||||
minerTx := transaction.NewMinerTXWithNonce(2083236893)
|
|
||||||
minerTx.Sender = hash.Hash160([]byte{byte(opcode.PUSH1)})
|
|
||||||
|
|
||||||
issueTx := transaction.NewIssueTX()
|
issueTx := transaction.NewIssueTX()
|
||||||
// TODO NEO3.0: nonce should be constant to avoid variability of genesis block
|
// TODO NEO3.0: nonce should be constant to avoid variability of genesis block
|
||||||
issueTx.Nonce = 0
|
issueTx.Nonce = 0
|
||||||
|
@ -84,12 +80,15 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
|
||||||
b := &block.Block{
|
b := &block.Block{
|
||||||
Base: base,
|
Base: base,
|
||||||
Transactions: []*transaction.Transaction{
|
Transactions: []*transaction.Transaction{
|
||||||
minerTx,
|
|
||||||
&governingTokenTX,
|
&governingTokenTX,
|
||||||
&utilityTokenTX,
|
&utilityTokenTX,
|
||||||
issueTx,
|
issueTx,
|
||||||
deployNativeContracts(),
|
deployNativeContracts(),
|
||||||
},
|
},
|
||||||
|
ConsensusData: block.ConsensusData{
|
||||||
|
PrimaryIndex: 0,
|
||||||
|
Nonce: 2083236893,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = b.RebuildMerkleRoot(); err != nil {
|
if err = b.RebuildMerkleRoot(); err != nil {
|
||||||
|
|
|
@ -20,7 +20,7 @@ func TestGenesisBlockMainNet(t *testing.T) {
|
||||||
// have been changed. Consequently, hash of the genesis block has been changed.
|
// have been changed. Consequently, hash of the genesis block has been changed.
|
||||||
// Update expected genesis block hash for better times.
|
// Update expected genesis block hash for better times.
|
||||||
// Old hash is "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf"
|
// Old hash is "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf"
|
||||||
expect := "094c2c2db5dcb868d85aa4d652aed23bc67e7166f53223a228e382265b1be84b"
|
expect := "16ffda4cc6a9b0a0ca63f1571f7724418c43f014e2eb4e8614b4938ccf0f20f6"
|
||||||
assert.Equal(t, expect, block.Hash().StringLE())
|
assert.Equal(t, expect, block.Hash().StringLE())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package payload
|
package payload
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||||
|
@ -65,6 +64,8 @@ func testHeadersEncodeDecode(t *testing.T, headers *Headers, expected int, limit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO NEO3.0: Update binary
|
||||||
|
/*
|
||||||
func TestBinEncodeDecode(t *testing.T) {
|
func TestBinEncodeDecode(t *testing.T) {
|
||||||
rawBlockHeaders := "010000000026b3c3df4dc1602a3b0e6989248b23275b5e4014a159af5dce69e16d4ab75f00f439321a51f425a530820cfe4d715bfd835b49687e87772f2c4737b8bc586dca7fda03580a000000bf14ff160228f0c059e75d652b5d3827bf04c165bbe9ef95cca4bf5501fd45014036fdd23248880c1c311bcd97df04fe6d740dc1bf340c26915f0466e31e81c039012eca7a760270389e04b58b99820fe49cf8c24c9afc65d696b4d3f406a1e6b5405172a9b461e68dd399c8716de11d31f7dd2ec3be327c636b024562db6ac5df1cffdbee74c994736fd49803234d2baffbc0054f28ba5ec76494a467b4106955bb4084af7746d269241628c667003e9d39288b190ad5cef218ada625cbba8be411bb153828d8d3634e8f586638e2448425bc5b671be69800392ccbdebc945a5099c7406f6a11824105ecad345e525957053e77fbc0119d6b3fa7f854527e816cfce0d95dac66888e07e8990c95103d8e46124aac16f152e088520d7ec8325e3a2456f840e5b77ef0e3c410b347ccaf8a87516d10b88d436563c80712153273993afc320ec49b638225f58de464a1345e62a564b398939f96f6f4b7cf21b583609f85495af1552102486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a7021024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d2102aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e2103b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c2103b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a2102ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba5542102df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e89509357ae00"
|
rawBlockHeaders := "010000000026b3c3df4dc1602a3b0e6989248b23275b5e4014a159af5dce69e16d4ab75f00f439321a51f425a530820cfe4d715bfd835b49687e87772f2c4737b8bc586dca7fda03580a000000bf14ff160228f0c059e75d652b5d3827bf04c165bbe9ef95cca4bf5501fd45014036fdd23248880c1c311bcd97df04fe6d740dc1bf340c26915f0466e31e81c039012eca7a760270389e04b58b99820fe49cf8c24c9afc65d696b4d3f406a1e6b5405172a9b461e68dd399c8716de11d31f7dd2ec3be327c636b024562db6ac5df1cffdbee74c994736fd49803234d2baffbc0054f28ba5ec76494a467b4106955bb4084af7746d269241628c667003e9d39288b190ad5cef218ada625cbba8be411bb153828d8d3634e8f586638e2448425bc5b671be69800392ccbdebc945a5099c7406f6a11824105ecad345e525957053e77fbc0119d6b3fa7f854527e816cfce0d95dac66888e07e8990c95103d8e46124aac16f152e088520d7ec8325e3a2456f840e5b77ef0e3c410b347ccaf8a87516d10b88d436563c80712153273993afc320ec49b638225f58de464a1345e62a564b398939f96f6f4b7cf21b583609f85495af1552102486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a7021024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d2102aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e2103b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c2103b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a2102ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba5542102df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e89509357ae00"
|
||||||
|
|
||||||
|
@ -84,3 +85,4 @@ func TestBinEncodeDecode(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, hex.EncodeToString(rawBlockBytes), hex.EncodeToString(data))
|
assert.Equal(t, hex.EncodeToString(rawBlockBytes), hex.EncodeToString(data))
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -803,9 +803,6 @@ func (s *Server) relayBlock(b *block.Block) {
|
||||||
|
|
||||||
// verifyAndPoolTX verifies the TX and adds it to the local mempool.
|
// verifyAndPoolTX verifies the TX and adds it to the local mempool.
|
||||||
func (s *Server) verifyAndPoolTX(t *transaction.Transaction) RelayReason {
|
func (s *Server) verifyAndPoolTX(t *transaction.Transaction) RelayReason {
|
||||||
if t.Type == transaction.MinerType {
|
|
||||||
return RelayInvalid
|
|
||||||
}
|
|
||||||
if err := s.chain.PoolTx(t); err != nil {
|
if err := s.chain.PoolTx(t); err != nil {
|
||||||
switch err {
|
switch err {
|
||||||
case core.ErrAlreadyExists:
|
case core.ErrAlreadyExists:
|
||||||
|
|
|
@ -136,17 +136,17 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
invoke: func(c *Client) (interface{}, error) {
|
invoke: func(c *Client) (interface{}, error) {
|
||||||
return c.GetBlockByIndex(5)
|
return c.GetBlockByIndex(5)
|
||||||
},
|
},
|
||||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"00000000b3aa04926a237abc2e54808fb10b5ca2394ae5ccfff17d60c1e393cfd418ed8f265f271088384b2f696e34bea0c8e02cf226351800c0866c1586be521536e579997c9d5e050000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd040140a6cc2c7fdee4f8fd97f84114d04edda16a37a4c088da9d5be3233e118fccdf73c0305d2cbd15ea0dbcedb594fec3044844e8f59f236ded7fccb1eda2eee2c76740197eba5d648d650ca1d73b8c0a0c7cdc22d31d7b2564764729d271e7ff6378c4f2228f657d65fec530f2af6cdc7af3bc2ab17a7b8175376601fb17ec951faf074038222bb0430f7808d333be3fb8e5b93c490dbb07e6c085350ba64cb7de61127067d1825de30915964dbb345f3b902d61dbf9a294c11ff6459000648f0dc4e66740926854a25b9ea87d7fffe0253bf2bcb3d153434cc0a8ba166136d16aef9a3de70ba3704ba3103a26d01c2bdbeb7262a19bbceab6a7487beba5e55f7ee768a0808b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae010000d5040000be48d3a3f5d10013ab9ffee489706078714f1ea20500000000000001fd040140f50121bb6ec9d8e0d1c15eea66b2ff7b51bb1bc4b3da27d9eac1d46b59e6a319bb1db4eb710c7f1931b0c2deaa2389a0fc3fe8c761cec40906b7973450c43173402dc082417a6815e722216de0b857eda6c846bf435088d543d2ab89f1dd92488e87b4d2c6508b0db945cbe6968e85c1c6d57274bfc898e82876c5cb08613da5d64053100f0162a41709a37305c300e7d6ac0d46575aab98dade7375b8d9ca980086594f1288dc68da0e0e42913d1c68024f63442a79c9478971d3ad93c5467ec53040a1c3a772a88b09cba8cc8ec3b46c0c0db6ac86519a7fd7db29b43d34e804a22d8839eaeb35e2a1e05d591fbad4ae290b90c6dc02dddbe28b2b3bf0fec2a337dd8b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae"}`,
|
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"000000005b25cf560918b13cc7a10071cf616426a103d58498171567aaa116af69179aa3c05c359ade4316392d69d5ca01f8860f8bdebbe1a8f752edd68d9a6a2d204fe752cca25e0000000005000000e903736ceceeceae1806eee0e3ec61e7cce476ce01fd08010c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf894130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb020057040000000000008000d5040000e903736ceceeceae1806eee0e3ec61e7cce476ce0500000000000001fd08010c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab794130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"}`,
|
||||||
result: func(c *Client) interface{} { return &block.Block{} },
|
result: func(c *Client) interface{} { return &block.Block{} },
|
||||||
check: func(t *testing.T, c *Client, result interface{}) {
|
check: func(t *testing.T, c *Client, result interface{}) {
|
||||||
res, ok := result.(*block.Block)
|
res, ok := result.(*block.Block)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
assert.Equal(t, uint32(0), res.Version)
|
assert.Equal(t, uint32(0), res.Version)
|
||||||
assert.Equal(t, "66d1c140fbdc0eaa47e69a6a9c5034ebc3a449db98da565191ab863d1a079906", res.Hash().StringLE())
|
assert.Equal(t, "81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb", res.Hash().StringLE())
|
||||||
assert.Equal(t, "8fed18d4cf93e3c1607df1ffcce54a39a25c0bb18f80542ebc7a236a9204aab3", res.PrevHash.StringLE())
|
assert.Equal(t, "a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b", res.PrevHash.StringLE())
|
||||||
assert.Equal(t, "79e5361552be86156c86c000183526f22ce0c8a0be346e692f4b388810275f26", res.MerkleRoot.StringLE())
|
assert.Equal(t, "e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0", res.MerkleRoot.StringLE())
|
||||||
assert.Equal(t, 1, len(res.Transactions))
|
assert.Equal(t, 1, len(res.Transactions))
|
||||||
assert.Equal(t, "79e5361552be86156c86c000183526f22ce0c8a0be346e692f4b388810275f26", res.Transactions[0].Hash().StringLE())
|
assert.Equal(t, "69d95138263dc54c07826ef1d76f9eb32ff6bf7fc3fc3281194b46ec7683ceb3", res.Transactions[0].Hash().StringLE())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -154,45 +154,46 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
invoke: func(c *Client) (i interface{}, err error) {
|
invoke: func(c *Client) (i interface{}, err error) {
|
||||||
return c.GetBlockByIndexVerbose(5)
|
return c.GetBlockByIndexVerbose(5)
|
||||||
},
|
},
|
||||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0x66d1c140fbdc0eaa47e69a6a9c5034ebc3a449db98da565191ab863d1a079906","size":946,"version":0,"nextblockhash":"0xf6749a5eb21273ec67951afd22282f002e605e210678c2fa765dbecf0124bd1a","previousblockhash":"0x8fed18d4cf93e3c1607df1ffcce54a39a25c0bb18f80542ebc7a236a9204aab3","merkleroot":"0x79e5361552be86156c86c000183526f22ce0c8a0be346e692f4b388810275f26","time":1587379353,"index":5,"nonce":"0000000000000457","nextconsensus":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","confirmations":203,"script":{"invocation":"40a6cc2c7fdee4f8fd97f84114d04edda16a37a4c088da9d5be3233e118fccdf73c0305d2cbd15ea0dbcedb594fec3044844e8f59f236ded7fccb1eda2eee2c76740197eba5d648d650ca1d73b8c0a0c7cdc22d31d7b2564764729d271e7ff6378c4f2228f657d65fec530f2af6cdc7af3bc2ab17a7b8175376601fb17ec951faf074038222bb0430f7808d333be3fb8e5b93c490dbb07e6c085350ba64cb7de61127067d1825de30915964dbb345f3b902d61dbf9a294c11ff6459000648f0dc4e66740926854a25b9ea87d7fffe0253bf2bcb3d153434cc0a8ba166136d16aef9a3de70ba3704ba3103a26d01c2bdbeb7262a19bbceab6a7487beba5e55f7ee768a080","verification":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae"},"tx":[{"sys_fee":"0","net_fee":"0","txid":"0x79e5361552be86156c86c000183526f22ce0c8a0be346e692f4b388810275f26","size":437,"type":"MinerTransaction","version":0,"nonce":1237,"sender":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","valid_until_block":5,"attributes":[],"vin":[],"vout":[],"scripts":[{"invocation":"40f50121bb6ec9d8e0d1c15eea66b2ff7b51bb1bc4b3da27d9eac1d46b59e6a319bb1db4eb710c7f1931b0c2deaa2389a0fc3fe8c761cec40906b7973450c43173402dc082417a6815e722216de0b857eda6c846bf435088d543d2ab89f1dd92488e87b4d2c6508b0db945cbe6968e85c1c6d57274bfc898e82876c5cb08613da5d64053100f0162a41709a37305c300e7d6ac0d46575aab98dade7375b8d9ca980086594f1288dc68da0e0e42913d1c68024f63442a79c9478971d3ad93c5467ec53040a1c3a772a88b09cba8cc8ec3b46c0c0db6ac86519a7fd7db29b43d34e804a22d8839eaeb35e2a1e05d591fbad4ae290b90c6dc02dddbe28b2b3bf0fec2a337dd","verification":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae"}]}]}}`,
|
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0x81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb","size":977,"version":0,"nextblockhash":"0xd08e408909ae24de3470a3f231f966e15719910cb7b1a30f356b3e784c1ddf6a","previousblockhash":"0xa39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b","merkleroot":"0xe74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0","time":1587727442,"index":5,"consensus_data":{"primary":0,"nonce":"0000000000000457"},"nextconsensus":"Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy","confirmations":203,"script":{"invocation":"0c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf8","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"},"tx":[{"sys_fee":"0","net_fee":"0","txid":"0x69d95138263dc54c07826ef1d76f9eb32ff6bf7fc3fc3281194b46ec7683ceb3","size":450,"type":"ContractTransaction","version":0,"nonce":1237,"sender":"Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy","valid_until_block":5,"attributes":[],"vin":[],"vout":[],"scripts":[{"invocation":"0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"}]}]}}`,
|
||||||
result: func(c *Client) interface{} {
|
result: func(c *Client) interface{} {
|
||||||
hash, err := util.Uint256DecodeStringLE("66d1c140fbdc0eaa47e69a6a9c5034ebc3a449db98da565191ab863d1a079906")
|
hash, err := util.Uint256DecodeStringLE("81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
nextBlockHash, err := util.Uint256DecodeStringLE("f6749a5eb21273ec67951afd22282f002e605e210678c2fa765dbecf0124bd1a")
|
nextBlockHash, err := util.Uint256DecodeStringLE("d08e408909ae24de3470a3f231f966e15719910cb7b1a30f356b3e784c1ddf6a")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
prevBlockHash, err := util.Uint256DecodeStringLE("8fed18d4cf93e3c1607df1ffcce54a39a25c0bb18f80542ebc7a236a9204aab3")
|
prevBlockHash, err := util.Uint256DecodeStringLE("a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
merkleRoot, err := util.Uint256DecodeStringLE("79e5361552be86156c86c000183526f22ce0c8a0be346e692f4b388810275f26")
|
merkleRoot, err := util.Uint256DecodeStringLE("e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
invScript, err := hex.DecodeString("40a6cc2c7fdee4f8fd97f84114d04edda16a37a4c088da9d5be3233e118fccdf73c0305d2cbd15ea0dbcedb594fec3044844e8f59f236ded7fccb1eda2eee2c76740197eba5d648d650ca1d73b8c0a0c7cdc22d31d7b2564764729d271e7ff6378c4f2228f657d65fec530f2af6cdc7af3bc2ab17a7b8175376601fb17ec951faf074038222bb0430f7808d333be3fb8e5b93c490dbb07e6c085350ba64cb7de61127067d1825de30915964dbb345f3b902d61dbf9a294c11ff6459000648f0dc4e66740926854a25b9ea87d7fffe0253bf2bcb3d153434cc0a8ba166136d16aef9a3de70ba3704ba3103a26d01c2bdbeb7262a19bbceab6a7487beba5e55f7ee768a080")
|
invScript, err := hex.DecodeString("0c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf8")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
verifScript, err := hex.DecodeString("532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae")
|
verifScript, err := hex.DecodeString("130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
sender, err := address.StringToUint160("AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU")
|
sender, err := address.StringToUint160("Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
txInvScript, err := hex.DecodeString("40f50121bb6ec9d8e0d1c15eea66b2ff7b51bb1bc4b3da27d9eac1d46b59e6a319bb1db4eb710c7f1931b0c2deaa2389a0fc3fe8c761cec40906b7973450c43173402dc082417a6815e722216de0b857eda6c846bf435088d543d2ab89f1dd92488e87b4d2c6508b0db945cbe6968e85c1c6d57274bfc898e82876c5cb08613da5d64053100f0162a41709a37305c300e7d6ac0d46575aab98dade7375b8d9ca980086594f1288dc68da0e0e42913d1c68024f63442a79c9478971d3ad93c5467ec53040a1c3a772a88b09cba8cc8ec3b46c0c0db6ac86519a7fd7db29b43d34e804a22d8839eaeb35e2a1e05d591fbad4ae290b90c6dc02dddbe28b2b3bf0fec2a337dd")
|
txInvScript, err := hex.DecodeString("0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
txVerifScript, err := hex.DecodeString("532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae")
|
txVerifScript, err := hex.DecodeString("130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
tx := transaction.NewMinerTXWithNonce(1237)
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = 1237
|
||||||
tx.ValidUntilBlock = 5
|
tx.ValidUntilBlock = 5
|
||||||
tx.Sender = sender
|
tx.Sender = sender
|
||||||
tx.Scripts = []transaction.Witness{
|
tx.Scripts = []transaction.Witness{
|
||||||
|
@ -205,16 +206,19 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
_ = tx.Hash()
|
_ = tx.Hash()
|
||||||
return &result.Block{
|
return &result.Block{
|
||||||
Hash: hash,
|
Hash: hash,
|
||||||
Size: 946,
|
Size: 977,
|
||||||
Version: 0,
|
Version: 0,
|
||||||
NextBlockHash: &nextBlockHash,
|
NextBlockHash: &nextBlockHash,
|
||||||
PreviousBlockHash: prevBlockHash,
|
PreviousBlockHash: prevBlockHash,
|
||||||
MerkleRoot: merkleRoot,
|
MerkleRoot: merkleRoot,
|
||||||
Time: 1587379353,
|
Time: 1587727442,
|
||||||
Index: 5,
|
Index: 5,
|
||||||
Nonce: "0000000000000457",
|
NextConsensus: "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
|
||||||
NextConsensus: "AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU",
|
|
||||||
Confirmations: 203,
|
Confirmations: 203,
|
||||||
|
ConsensusData: result.ConsensusData{
|
||||||
|
PrimaryIndex: 0,
|
||||||
|
Nonce: "0000000000000457",
|
||||||
|
},
|
||||||
Script: transaction.Witness{
|
Script: transaction.Witness{
|
||||||
InvocationScript: invScript,
|
InvocationScript: invScript,
|
||||||
VerificationScript: verifScript,
|
VerificationScript: verifScript,
|
||||||
|
@ -232,73 +236,74 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
{
|
{
|
||||||
name: "byHash_positive",
|
name: "byHash_positive",
|
||||||
invoke: func(c *Client) (interface{}, error) {
|
invoke: func(c *Client) (interface{}, error) {
|
||||||
hash, err := util.Uint256DecodeStringLE("0699071a3d86ab915156da98db49a4c3eb34509c6a9ae647aa0edcfb40c1d166")
|
hash, err := util.Uint256DecodeStringLE("e9f71b58764157f1e2c3e29f217e654b57956ee7c8a60496b03ea85e39084b42")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return c.GetBlockByHash(hash)
|
return c.GetBlockByHash(hash)
|
||||||
},
|
},
|
||||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"00000000b3aa04926a237abc2e54808fb10b5ca2394ae5ccfff17d60c1e393cfd418ed8f265f271088384b2f696e34bea0c8e02cf226351800c0866c1586be521536e579997c9d5e050000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd040140a6cc2c7fdee4f8fd97f84114d04edda16a37a4c088da9d5be3233e118fccdf73c0305d2cbd15ea0dbcedb594fec3044844e8f59f236ded7fccb1eda2eee2c76740197eba5d648d650ca1d73b8c0a0c7cdc22d31d7b2564764729d271e7ff6378c4f2228f657d65fec530f2af6cdc7af3bc2ab17a7b8175376601fb17ec951faf074038222bb0430f7808d333be3fb8e5b93c490dbb07e6c085350ba64cb7de61127067d1825de30915964dbb345f3b902d61dbf9a294c11ff6459000648f0dc4e66740926854a25b9ea87d7fffe0253bf2bcb3d153434cc0a8ba166136d16aef9a3de70ba3704ba3103a26d01c2bdbeb7262a19bbceab6a7487beba5e55f7ee768a0808b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae010000d5040000be48d3a3f5d10013ab9ffee489706078714f1ea20500000000000001fd040140f50121bb6ec9d8e0d1c15eea66b2ff7b51bb1bc4b3da27d9eac1d46b59e6a319bb1db4eb710c7f1931b0c2deaa2389a0fc3fe8c761cec40906b7973450c43173402dc082417a6815e722216de0b857eda6c846bf435088d543d2ab89f1dd92488e87b4d2c6508b0db945cbe6968e85c1c6d57274bfc898e82876c5cb08613da5d64053100f0162a41709a37305c300e7d6ac0d46575aab98dade7375b8d9ca980086594f1288dc68da0e0e42913d1c68024f63442a79c9478971d3ad93c5467ec53040a1c3a772a88b09cba8cc8ec3b46c0c0db6ac86519a7fd7db29b43d34e804a22d8839eaeb35e2a1e05d591fbad4ae290b90c6dc02dddbe28b2b3bf0fec2a337dd8b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae"}`,
|
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"000000005b25cf560918b13cc7a10071cf616426a103d58498171567aaa116af69179aa3c05c359ade4316392d69d5ca01f8860f8bdebbe1a8f752edd68d9a6a2d204fe752cca25e0000000005000000e903736ceceeceae1806eee0e3ec61e7cce476ce01fd08010c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf894130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb020057040000000000008000d5040000e903736ceceeceae1806eee0e3ec61e7cce476ce0500000000000001fd08010c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab794130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"}`,
|
||||||
result: func(c *Client) interface{} { return &block.Block{} },
|
result: func(c *Client) interface{} { return &block.Block{} },
|
||||||
check: func(t *testing.T, c *Client, result interface{}) {
|
check: func(t *testing.T, c *Client, result interface{}) {
|
||||||
res, ok := result.(*block.Block)
|
res, ok := result.(*block.Block)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
assert.Equal(t, uint32(0), res.Version)
|
assert.Equal(t, uint32(0), res.Version)
|
||||||
assert.Equal(t, "66d1c140fbdc0eaa47e69a6a9c5034ebc3a449db98da565191ab863d1a079906", res.Hash().StringLE())
|
assert.Equal(t, "81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb", res.Hash().StringLE())
|
||||||
assert.Equal(t, "8fed18d4cf93e3c1607df1ffcce54a39a25c0bb18f80542ebc7a236a9204aab3", res.PrevHash.StringLE())
|
assert.Equal(t, "a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b", res.PrevHash.StringLE())
|
||||||
assert.Equal(t, "79e5361552be86156c86c000183526f22ce0c8a0be346e692f4b388810275f26", res.MerkleRoot.StringLE())
|
assert.Equal(t, "e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0", res.MerkleRoot.StringLE())
|
||||||
assert.Equal(t, 1, len(res.Transactions))
|
assert.Equal(t, 1, len(res.Transactions))
|
||||||
assert.Equal(t, "79e5361552be86156c86c000183526f22ce0c8a0be346e692f4b388810275f26", res.Transactions[0].Hash().StringLE())
|
assert.Equal(t, "69d95138263dc54c07826ef1d76f9eb32ff6bf7fc3fc3281194b46ec7683ceb3", res.Transactions[0].Hash().StringLE())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "byHash_verbose_positive",
|
name: "byHash_verbose_positive",
|
||||||
invoke: func(c *Client) (i interface{}, err error) {
|
invoke: func(c *Client) (i interface{}, err error) {
|
||||||
hash, err := util.Uint256DecodeStringLE("0699071a3d86ab915156da98db49a4c3eb34509c6a9ae647aa0edcfb40c1d166")
|
hash, err := util.Uint256DecodeStringLE("bb09d40563c7141215b024b0959aec00a3ab316248c2ee31f32ea4c3cf4db781")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return c.GetBlockByHashVerbose(hash)
|
return c.GetBlockByHashVerbose(hash)
|
||||||
},
|
},
|
||||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0x66d1c140fbdc0eaa47e69a6a9c5034ebc3a449db98da565191ab863d1a079906","size":946,"version":0,"nextblockhash":"0xf6749a5eb21273ec67951afd22282f002e605e210678c2fa765dbecf0124bd1a","previousblockhash":"0x8fed18d4cf93e3c1607df1ffcce54a39a25c0bb18f80542ebc7a236a9204aab3","merkleroot":"0x79e5361552be86156c86c000183526f22ce0c8a0be346e692f4b388810275f26","time":1587379353,"index":5,"nonce":"0000000000000457","nextconsensus":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","confirmations":203,"script":{"invocation":"40a6cc2c7fdee4f8fd97f84114d04edda16a37a4c088da9d5be3233e118fccdf73c0305d2cbd15ea0dbcedb594fec3044844e8f59f236ded7fccb1eda2eee2c76740197eba5d648d650ca1d73b8c0a0c7cdc22d31d7b2564764729d271e7ff6378c4f2228f657d65fec530f2af6cdc7af3bc2ab17a7b8175376601fb17ec951faf074038222bb0430f7808d333be3fb8e5b93c490dbb07e6c085350ba64cb7de61127067d1825de30915964dbb345f3b902d61dbf9a294c11ff6459000648f0dc4e66740926854a25b9ea87d7fffe0253bf2bcb3d153434cc0a8ba166136d16aef9a3de70ba3704ba3103a26d01c2bdbeb7262a19bbceab6a7487beba5e55f7ee768a080","verification":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae"},"tx":[{"sys_fee":"0","net_fee":"0","txid":"0x79e5361552be86156c86c000183526f22ce0c8a0be346e692f4b388810275f26","size":437,"type":"MinerTransaction","version":0,"nonce":1237,"sender":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","valid_until_block":5,"attributes":[],"vin":[],"vout":[],"scripts":[{"invocation":"40f50121bb6ec9d8e0d1c15eea66b2ff7b51bb1bc4b3da27d9eac1d46b59e6a319bb1db4eb710c7f1931b0c2deaa2389a0fc3fe8c761cec40906b7973450c43173402dc082417a6815e722216de0b857eda6c846bf435088d543d2ab89f1dd92488e87b4d2c6508b0db945cbe6968e85c1c6d57274bfc898e82876c5cb08613da5d64053100f0162a41709a37305c300e7d6ac0d46575aab98dade7375b8d9ca980086594f1288dc68da0e0e42913d1c68024f63442a79c9478971d3ad93c5467ec53040a1c3a772a88b09cba8cc8ec3b46c0c0db6ac86519a7fd7db29b43d34e804a22d8839eaeb35e2a1e05d591fbad4ae290b90c6dc02dddbe28b2b3bf0fec2a337dd","verification":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae"}]}]}}`,
|
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0x81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb","size":977,"version":0,"nextblockhash":"0xd08e408909ae24de3470a3f231f966e15719910cb7b1a30f356b3e784c1ddf6a","previousblockhash":"0xa39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b","merkleroot":"0xe74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0","time":1587727442,"index":5,"consensus_data":{"primary":0,"nonce":"0000000000000457"},"nextconsensus":"Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy","confirmations":203,"script":{"invocation":"0c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf8","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"},"tx":[{"sys_fee":"0","net_fee":"0","txid":"0x69d95138263dc54c07826ef1d76f9eb32ff6bf7fc3fc3281194b46ec7683ceb3","size":450,"type":"ContractTransaction","version":0,"nonce":1237,"sender":"Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy","valid_until_block":5,"attributes":[],"vin":[],"vout":[],"scripts":[{"invocation":"0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"}]}]}}`,
|
||||||
result: func(c *Client) interface{} {
|
result: func(c *Client) interface{} {
|
||||||
hash, err := util.Uint256DecodeStringLE("66d1c140fbdc0eaa47e69a6a9c5034ebc3a449db98da565191ab863d1a079906")
|
hash, err := util.Uint256DecodeStringLE("81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
nextBlockHash, err := util.Uint256DecodeStringLE("f6749a5eb21273ec67951afd22282f002e605e210678c2fa765dbecf0124bd1a")
|
nextBlockHash, err := util.Uint256DecodeStringLE("d08e408909ae24de3470a3f231f966e15719910cb7b1a30f356b3e784c1ddf6a")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
prevBlockHash, err := util.Uint256DecodeStringLE("8fed18d4cf93e3c1607df1ffcce54a39a25c0bb18f80542ebc7a236a9204aab3")
|
prevBlockHash, err := util.Uint256DecodeStringLE("a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
merkleRoot, err := util.Uint256DecodeStringLE("79e5361552be86156c86c000183526f22ce0c8a0be346e692f4b388810275f26")
|
merkleRoot, err := util.Uint256DecodeStringLE("e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
invScript, err := hex.DecodeString("40a6cc2c7fdee4f8fd97f84114d04edda16a37a4c088da9d5be3233e118fccdf73c0305d2cbd15ea0dbcedb594fec3044844e8f59f236ded7fccb1eda2eee2c76740197eba5d648d650ca1d73b8c0a0c7cdc22d31d7b2564764729d271e7ff6378c4f2228f657d65fec530f2af6cdc7af3bc2ab17a7b8175376601fb17ec951faf074038222bb0430f7808d333be3fb8e5b93c490dbb07e6c085350ba64cb7de61127067d1825de30915964dbb345f3b902d61dbf9a294c11ff6459000648f0dc4e66740926854a25b9ea87d7fffe0253bf2bcb3d153434cc0a8ba166136d16aef9a3de70ba3704ba3103a26d01c2bdbeb7262a19bbceab6a7487beba5e55f7ee768a080")
|
invScript, err := hex.DecodeString("0c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf8")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
verifScript, err := hex.DecodeString("532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae")
|
verifScript, err := hex.DecodeString("130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
sender, err := address.StringToUint160("AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU")
|
sender, err := address.StringToUint160("Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
txInvScript, err := hex.DecodeString("40f50121bb6ec9d8e0d1c15eea66b2ff7b51bb1bc4b3da27d9eac1d46b59e6a319bb1db4eb710c7f1931b0c2deaa2389a0fc3fe8c761cec40906b7973450c43173402dc082417a6815e722216de0b857eda6c846bf435088d543d2ab89f1dd92488e87b4d2c6508b0db945cbe6968e85c1c6d57274bfc898e82876c5cb08613da5d64053100f0162a41709a37305c300e7d6ac0d46575aab98dade7375b8d9ca980086594f1288dc68da0e0e42913d1c68024f63442a79c9478971d3ad93c5467ec53040a1c3a772a88b09cba8cc8ec3b46c0c0db6ac86519a7fd7db29b43d34e804a22d8839eaeb35e2a1e05d591fbad4ae290b90c6dc02dddbe28b2b3bf0fec2a337dd")
|
txInvScript, err := hex.DecodeString("0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
txVerifScript, err := hex.DecodeString("532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae")
|
txVerifScript, err := hex.DecodeString("130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
tx := transaction.NewMinerTXWithNonce(1237)
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = 1237
|
||||||
tx.ValidUntilBlock = 5
|
tx.ValidUntilBlock = 5
|
||||||
tx.Sender = sender
|
tx.Sender = sender
|
||||||
tx.Scripts = []transaction.Witness{
|
tx.Scripts = []transaction.Witness{
|
||||||
|
@ -311,16 +316,19 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
_ = tx.Hash()
|
_ = tx.Hash()
|
||||||
return &result.Block{
|
return &result.Block{
|
||||||
Hash: hash,
|
Hash: hash,
|
||||||
Size: 946,
|
Size: 977,
|
||||||
Version: 0,
|
Version: 0,
|
||||||
NextBlockHash: &nextBlockHash,
|
NextBlockHash: &nextBlockHash,
|
||||||
PreviousBlockHash: prevBlockHash,
|
PreviousBlockHash: prevBlockHash,
|
||||||
MerkleRoot: merkleRoot,
|
MerkleRoot: merkleRoot,
|
||||||
Time: 1587379353,
|
Time: 1587727442,
|
||||||
Index: 5,
|
Index: 5,
|
||||||
Nonce: "0000000000000457",
|
NextConsensus: "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
|
||||||
NextConsensus: "AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU",
|
|
||||||
Confirmations: 203,
|
Confirmations: 203,
|
||||||
|
ConsensusData: result.ConsensusData{
|
||||||
|
PrimaryIndex: 0,
|
||||||
|
Nonce: "0000000000000457",
|
||||||
|
},
|
||||||
Script: transaction.Witness{
|
Script: transaction.Witness{
|
||||||
InvocationScript: invScript,
|
InvocationScript: invScript,
|
||||||
VerificationScript: verifScript,
|
VerificationScript: verifScript,
|
||||||
|
@ -368,21 +376,21 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
invoke: func(c *Client) (interface{}, error) {
|
invoke: func(c *Client) (interface{}, error) {
|
||||||
hash, err := util.Uint256DecodeStringLE("e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c")
|
hash, err := util.Uint256DecodeStringLE("68e4bd688b852e807eef13a0ff7da7b02223e359a35153667e88f9cb4a3b0801")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return c.GetBlockHeader(hash)
|
return c.GetBlockHeader(hash)
|
||||||
},
|
},
|
||||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"00000000999086db552ba8f84734bddca55b25a8d3d8c5f866f941209169c38d35376e99b29ffa96224227f5e033c9a291bceef2724429d596c3a6944cafd6995fdb6dcbe013dd5b010000004ded49fea284b451be48d3a3f5d10013ab9ffee489706078714f1ea201c340356a91d94e398170e47447d6a0f60aa5470e209782a5452403115a49166db3e1c4a3898122db19f779c30f8ccd0b7d401acdf71eda340655e4ae5237a64961bf4034dd47955e5a71627dafc39dd92999140e9eaeec6b11dbb2b313efa3f1093ed915b4455e199c69ec53778f94ffc236b92f8b97fff97a1f6bbb3770c0c0b3844a40fbe743bd5c90b2f5255e0b073281d7aeb2fb516572f36bec8446bcc37ac755cbf10d08b16c95644db1b2dddc2df5daa377880b20198fc7b967ac6e76474b22df8b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae00"}`,
|
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"00000000d039da5e49d63eb0533437d24ff8ceb6aeacf88680599c39f0ffca8948dfcdb94a3def1fca91cf45d69358414e3be77f7621e557f4cebbdb79a47d3cf56ac007f920a05e0000000001000000d60ac443bb800fb08261e75fa5925d747d48586101fd04014055041db6a59c99ab98137cc57e1e56a0a89856a311b2d2fc0aec76ec714c7616edc8fc5c9b81b27f25b7db1a61f64be0730a9cc103efcea1195cc3fe55843e264027e49c647f48bb08d3c32b79ee3432005ea577d7e497f78b46f1e81858848f961b557fb42a92e8eb4433fed203c917cbebb2138a31ed86750fb769d1e70956c0404c20054aa8bd45b520cba9410a9dd6c256481066bb657d7793fbba5551898c91b6dde81285fac841753ccfdd3193d08f19d5431313fa0d926ca965072a5fa3384026b0705078409bcc62fb98bb985edc387edeaaeba37bb7642d88a90762b2c2a62d9b61d53c097d548a368e450c4d995a178d5af28d4c93698233c52de05e3f0094534c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e4c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd624c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc24c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee6995450683073b3bb00"}`,
|
||||||
result: func(c *Client) interface{} { return &block.Header{} },
|
result: func(c *Client) interface{} { return &block.Header{} },
|
||||||
check: func(t *testing.T, c *Client, result interface{}) {
|
check: func(t *testing.T, c *Client, result interface{}) {
|
||||||
res, ok := result.(*block.Header)
|
res, ok := result.(*block.Header)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
assert.Equal(t, uint32(0), res.Version)
|
assert.Equal(t, uint32(0), res.Version)
|
||||||
assert.Equal(t, "e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c", res.Hash().StringLE())
|
assert.Equal(t, "68e4bd688b852e807eef13a0ff7da7b02223e359a35153667e88f9cb4a3b0801", res.Hash().StringLE())
|
||||||
assert.Equal(t, "996e37358dc369912041f966f8c5d8d3a8255ba5dcbd3447f8a82b55db869099", res.PrevHash.StringLE())
|
assert.Equal(t, "b9cddf4889cafff0399c598086f8acaeb6cef84fd2373453b03ed6495eda39d0", res.PrevHash.StringLE())
|
||||||
assert.Equal(t, "cb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2", res.MerkleRoot.StringLE())
|
assert.Equal(t, "07c06af53c7da479dbbbcef457e521767fe73b4e415893d645cf91ca1fef3d4a", res.MerkleRoot.StringLE())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -429,7 +437,6 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
MerkleRoot: merkleRoot,
|
MerkleRoot: merkleRoot,
|
||||||
Timestamp: 1541215200,
|
Timestamp: 1541215200,
|
||||||
Index: 1,
|
Index: 1,
|
||||||
Nonce: "51b484a2fe49ed4d",
|
|
||||||
NextConsensus: "AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU",
|
NextConsensus: "AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU",
|
||||||
Confirmations: 20061,
|
Confirmations: 20061,
|
||||||
Script: transaction.Witness{
|
Script: transaction.Witness{
|
||||||
|
@ -646,51 +653,52 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
invoke: func(c *Client) (i interface{}, err error) {
|
invoke: func(c *Client) (i interface{}, err error) {
|
||||||
hash, err := util.Uint256DecodeStringLE("265f271088384b2f696e34bea0c8e02cf226351800c0866c1586be521536e579")
|
hash, err := util.Uint256DecodeStringLE("b3ce8376ec464b198132fcc37fbff62fb39e6fd7f16e82074cc53d263851d969")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return c.GetRawTransaction(hash)
|
return c.GetRawTransaction(hash)
|
||||||
},
|
},
|
||||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"0000d5040000be48d3a3f5d10013ab9ffee489706078714f1ea20500000000000001fd040140f50121bb6ec9d8e0d1c15eea66b2ff7b51bb1bc4b3da27d9eac1d46b59e6a319bb1db4eb710c7f1931b0c2deaa2389a0fc3fe8c761cec40906b7973450c43173402dc082417a6815e722216de0b857eda6c846bf435088d543d2ab89f1dd92488e87b4d2c6508b0db945cbe6968e85c1c6d57274bfc898e82876c5cb08613da5d64053100f0162a41709a37305c300e7d6ac0d46575aab98dade7375b8d9ca980086594f1288dc68da0e0e42913d1c68024f63442a79c9478971d3ad93c5467ec53040a1c3a772a88b09cba8cc8ec3b46c0c0db6ac86519a7fd7db29b43d34e804a22d8839eaeb35e2a1e05d591fbad4ae290b90c6dc02dddbe28b2b3bf0fec2a337dd8b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae"}`,
|
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"8000d5040000e903736ceceeceae1806eee0e3ec61e7cce476ce0500000000000001fd08010c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab794130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"}`,
|
||||||
result: func(c *Client) interface{} { return &transaction.Transaction{} },
|
result: func(c *Client) interface{} { return &transaction.Transaction{} },
|
||||||
check: func(t *testing.T, c *Client, result interface{}) {
|
check: func(t *testing.T, c *Client, result interface{}) {
|
||||||
res, ok := result.(*transaction.Transaction)
|
res, ok := result.(*transaction.Transaction)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
assert.Equal(t, uint8(0), res.Version)
|
assert.Equal(t, uint8(0), res.Version)
|
||||||
assert.Equal(t, "265f271088384b2f696e34bea0c8e02cf226351800c0866c1586be521536e579", res.Hash().StringBE())
|
assert.Equal(t, "b3ce8376ec464b198132fcc37fbff62fb39e6fd7f16e82074cc53d263851d969", res.Hash().StringBE())
|
||||||
assert.Equal(t, transaction.MinerType, res.Type)
|
assert.Equal(t, transaction.ContractType, res.Type)
|
||||||
assert.Equal(t, false, res.Trimmed)
|
assert.Equal(t, false, res.Trimmed)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "verbose_positive",
|
name: "verbose_positive",
|
||||||
invoke: func(c *Client) (interface{}, error) {
|
invoke: func(c *Client) (interface{}, error) {
|
||||||
hash, err := util.Uint256DecodeStringLE("265f271088384b2f696e34bea0c8e02cf226351800c0866c1586be521536e579")
|
hash, err := util.Uint256DecodeStringLE("b3ce8376ec464b198132fcc37fbff62fb39e6fd7f16e82074cc53d263851d969")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return c.GetRawTransactionVerbose(hash)
|
return c.GetRawTransactionVerbose(hash)
|
||||||
},
|
},
|
||||||
serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"sys_fee":"0","net_fee":"0","blockhash":"0x66d1c140fbdc0eaa47e69a6a9c5034ebc3a449db98da565191ab863d1a079906","confirmations":205,"blocktime":1587379353,"txid":"0x79e5361552be86156c86c000183526f22ce0c8a0be346e692f4b388810275f26","size":437,"type":"MinerTransaction","version":0,"nonce":1237,"sender":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","valid_until_block":5,"attributes":[],"vin":[],"vout":[],"scripts":[{"invocation":"40f50121bb6ec9d8e0d1c15eea66b2ff7b51bb1bc4b3da27d9eac1d46b59e6a319bb1db4eb710c7f1931b0c2deaa2389a0fc3fe8c761cec40906b7973450c43173402dc082417a6815e722216de0b857eda6c846bf435088d543d2ab89f1dd92488e87b4d2c6508b0db945cbe6968e85c1c6d57274bfc898e82876c5cb08613da5d64053100f0162a41709a37305c300e7d6ac0d46575aab98dade7375b8d9ca980086594f1288dc68da0e0e42913d1c68024f63442a79c9478971d3ad93c5467ec53040a1c3a772a88b09cba8cc8ec3b46c0c0db6ac86519a7fd7db29b43d34e804a22d8839eaeb35e2a1e05d591fbad4ae290b90c6dc02dddbe28b2b3bf0fec2a337dd","verification":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae"}]}}`,
|
serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"sys_fee":"0","net_fee":"0","blockhash":"0x81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb","confirmations":205,"blocktime":1587727442,"txid":"0x69d95138263dc54c07826ef1d76f9eb32ff6bf7fc3fc3281194b46ec7683ceb3","size":450,"type":"ContractTransaction","version":0,"nonce":1237,"sender":"Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy","valid_until_block":5,"attributes":[],"vin":[],"vout":[],"scripts":[{"invocation":"0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb"}]}}`,
|
||||||
result: func(c *Client) interface{} {
|
result: func(c *Client) interface{} {
|
||||||
blockHash, err := util.Uint256DecodeStringLE("66d1c140fbdc0eaa47e69a6a9c5034ebc3a449db98da565191ab863d1a079906")
|
blockHash, err := util.Uint256DecodeStringLE("81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
sender, err := address.StringToUint160("AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU")
|
sender, err := address.StringToUint160("Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
invocation, err := hex.DecodeString("40f50121bb6ec9d8e0d1c15eea66b2ff7b51bb1bc4b3da27d9eac1d46b59e6a319bb1db4eb710c7f1931b0c2deaa2389a0fc3fe8c761cec40906b7973450c43173402dc082417a6815e722216de0b857eda6c846bf435088d543d2ab89f1dd92488e87b4d2c6508b0db945cbe6968e85c1c6d57274bfc898e82876c5cb08613da5d64053100f0162a41709a37305c300e7d6ac0d46575aab98dade7375b8d9ca980086594f1288dc68da0e0e42913d1c68024f63442a79c9478971d3ad93c5467ec53040a1c3a772a88b09cba8cc8ec3b46c0c0db6ac86519a7fd7db29b43d34e804a22d8839eaeb35e2a1e05d591fbad4ae290b90c6dc02dddbe28b2b3bf0fec2a337dd")
|
invocation, err := hex.DecodeString("0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
verification, err := hex.DecodeString("532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae")
|
verification, err := hex.DecodeString("130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
tx := transaction.NewMinerTXWithNonce(1237)
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = 1237
|
||||||
tx.ValidUntilBlock = 5
|
tx.ValidUntilBlock = 5
|
||||||
tx.Sender = sender
|
tx.Sender = sender
|
||||||
tx.Scripts = []transaction.Witness{
|
tx.Scripts = []transaction.Witness{
|
||||||
|
@ -709,7 +717,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
NetFee: 0,
|
NetFee: 0,
|
||||||
Blockhash: blockHash,
|
Blockhash: blockHash,
|
||||||
Confirmations: 205,
|
Confirmations: 205,
|
||||||
Timestamp: uint32(1587379353),
|
Timestamp: uint64(1587727442),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -904,7 +912,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
invoke: func(c *Client) (interface{}, error) {
|
invoke: func(c *Client) (interface{}, error) {
|
||||||
return nil, c.SendRawTransaction(transaction.NewMinerTX())
|
return nil, c.SendRawTransaction(transaction.NewContractTX())
|
||||||
},
|
},
|
||||||
serverResponse: `{"jsonrpc":"2.0","id":1,"result":true}`,
|
serverResponse: `{"jsonrpc":"2.0","id":1,"result":true}`,
|
||||||
result: func(c *Client) interface{} {
|
result: func(c *Client) interface{} {
|
||||||
|
@ -1025,7 +1033,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{
|
||||||
{
|
{
|
||||||
name: "sendrawtransaction_bad_server_answer",
|
name: "sendrawtransaction_bad_server_answer",
|
||||||
invoke: func(c *Client) (interface{}, error) {
|
invoke: func(c *Client) (interface{}, error) {
|
||||||
return nil, c.SendRawTransaction(transaction.NewMinerTX())
|
return nil, c.SendRawTransaction(transaction.NewContractTX())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1411,7 +1419,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{
|
||||||
{
|
{
|
||||||
name: "sendrawtransaction_unmarshalling_error",
|
name: "sendrawtransaction_unmarshalling_error",
|
||||||
invoke: func(c *Client) (interface{}, error) {
|
invoke: func(c *Client) (interface{}, error) {
|
||||||
return nil, c.SendRawTransaction(transaction.NewMinerTX())
|
return nil, c.SendRawTransaction(transaction.NewContractTX())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,6 +27,12 @@ type (
|
||||||
NetFee util.Fixed8 `json:"net_fee"`
|
NetFee util.Fixed8 `json:"net_fee"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
@ -36,9 +42,9 @@ type (
|
||||||
NextBlockHash *util.Uint256 `json:"nextblockhash,omitempty"`
|
NextBlockHash *util.Uint256 `json:"nextblockhash,omitempty"`
|
||||||
PreviousBlockHash util.Uint256 `json:"previousblockhash"`
|
PreviousBlockHash util.Uint256 `json:"previousblockhash"`
|
||||||
MerkleRoot util.Uint256 `json:"merkleroot"`
|
MerkleRoot util.Uint256 `json:"merkleroot"`
|
||||||
Time uint32 `json:"time"`
|
Time uint64 `json:"time"`
|
||||||
Index uint32 `json:"index"`
|
Index uint32 `json:"index"`
|
||||||
Nonce string `json:"nonce"`
|
ConsensusData ConsensusData `json:"consensus_data"`
|
||||||
NextConsensus string `json:"nextconsensus"`
|
NextConsensus string `json:"nextconsensus"`
|
||||||
|
|
||||||
Confirmations uint32 `json:"confirmations"`
|
Confirmations uint32 `json:"confirmations"`
|
||||||
|
@ -59,7 +65,10 @@ func NewBlock(b *block.Block, chain blockchainer.Blockchainer) Block {
|
||||||
MerkleRoot: b.MerkleRoot,
|
MerkleRoot: b.MerkleRoot,
|
||||||
Time: b.Timestamp,
|
Time: b.Timestamp,
|
||||||
Index: b.Index,
|
Index: b.Index,
|
||||||
Nonce: fmt.Sprintf("%016x", b.ConsensusData),
|
ConsensusData: ConsensusData{
|
||||||
|
PrimaryIndex: b.ConsensusData.PrimaryIndex,
|
||||||
|
Nonce: fmt.Sprintf("%016x", b.ConsensusData.Nonce),
|
||||||
|
},
|
||||||
NextConsensus: address.Uint160ToString(b.NextConsensus),
|
NextConsensus: address.Uint160ToString(b.NextConsensus),
|
||||||
Confirmations: chain.BlockHeight() - b.Index - 1,
|
Confirmations: chain.BlockHeight() - b.Index - 1,
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package result
|
package result
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"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/core/transaction"
|
||||||
|
@ -20,9 +18,8 @@ type (
|
||||||
Version uint32 `json:"version"`
|
Version uint32 `json:"version"`
|
||||||
PrevBlockHash util.Uint256 `json:"previousblockhash"`
|
PrevBlockHash util.Uint256 `json:"previousblockhash"`
|
||||||
MerkleRoot util.Uint256 `json:"merkleroot"`
|
MerkleRoot util.Uint256 `json:"merkleroot"`
|
||||||
Timestamp uint32 `json:"time"`
|
Timestamp uint64 `json:"time"`
|
||||||
Index uint32 `json:"index"`
|
Index uint32 `json:"index"`
|
||||||
Nonce string `json:"nonce"`
|
|
||||||
NextConsensus string `json:"nextconsensus"`
|
NextConsensus string `json:"nextconsensus"`
|
||||||
Script transaction.Witness `json:"script"`
|
Script transaction.Witness `json:"script"`
|
||||||
Confirmations uint32 `json:"confirmations"`
|
Confirmations uint32 `json:"confirmations"`
|
||||||
|
@ -40,7 +37,6 @@ func NewHeader(h *block.Header, chain blockchainer.Blockchainer) Header {
|
||||||
MerkleRoot: h.MerkleRoot,
|
MerkleRoot: h.MerkleRoot,
|
||||||
Timestamp: h.Timestamp,
|
Timestamp: h.Timestamp,
|
||||||
Index: h.Index,
|
Index: h.Index,
|
||||||
Nonce: strconv.FormatUint(h.ConsensusData, 16),
|
|
||||||
NextConsensus: address.Uint160ToString(h.NextConsensus),
|
NextConsensus: address.Uint160ToString(h.NextConsensus),
|
||||||
Script: h.Script,
|
Script: h.Script,
|
||||||
Confirmations: chain.BlockHeight() - h.Index + 1,
|
Confirmations: chain.BlockHeight() - h.Index + 1,
|
||||||
|
|
|
@ -35,7 +35,7 @@ type NEP5Transfers struct {
|
||||||
|
|
||||||
// NEP5Transfer represents single NEP5 transfer event.
|
// NEP5Transfer represents single NEP5 transfer event.
|
||||||
type NEP5Transfer struct {
|
type NEP5Transfer struct {
|
||||||
Timestamp uint32 `json:"timestamp"`
|
Timestamp uint64 `json:"timestamp"`
|
||||||
Asset util.Uint160 `json:"asset_hash"`
|
Asset util.Uint160 `json:"asset_hash"`
|
||||||
Address string `json:"transfer_address,omitempty"`
|
Address string `json:"transfer_address,omitempty"`
|
||||||
Amount string `json:"amount"`
|
Amount string `json:"amount"`
|
||||||
|
|
|
@ -23,7 +23,7 @@ type TransactionMetadata struct {
|
||||||
NetFee util.Fixed8 `json:"net_fee"`
|
NetFee util.Fixed8 `json:"net_fee"`
|
||||||
Blockhash util.Uint256 `json:"blockhash,omitempty"`
|
Blockhash util.Uint256 `json:"blockhash,omitempty"`
|
||||||
Confirmations int `json:"confirmations,omitempty"`
|
Confirmations int `json:"confirmations,omitempty"`
|
||||||
Timestamp uint32 `json:"blocktime,omitempty"`
|
Timestamp uint64 `json:"blocktime,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTransactionOutputRaw returns a new ransactionOutputRaw object.
|
// NewTransactionOutputRaw returns a new ransactionOutputRaw object.
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -54,12 +53,12 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
"getapplicationlog": {
|
"getapplicationlog": {
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
params: `["4108062977676178e8453a8ef84a702e01bb35af8a65c7529d04704fcb5f1e0e"]`,
|
params: `["fe1a3678b16eca35209acf85397708eb0f1668e4045ad4cd5d2453d3bc0a0a6d"]`,
|
||||||
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
|
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
|
||||||
check: func(t *testing.T, e *executor, acc interface{}) {
|
check: func(t *testing.T, e *executor, acc interface{}) {
|
||||||
res, ok := acc.(*result.ApplicationLog)
|
res, ok := acc.(*result.ApplicationLog)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
expectedTxHash, err := util.Uint256DecodeStringLE("4108062977676178e8453a8ef84a702e01bb35af8a65c7529d04704fcb5f1e0e")
|
expectedTxHash, err := util.Uint256DecodeStringLE("fe1a3678b16eca35209acf85397708eb0f1668e4045ad4cd5d2453d3bc0a0a6d")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, expectedTxHash, res.TxHash)
|
assert.Equal(t, expectedTxHash, res.TxHash)
|
||||||
assert.Equal(t, 1, len(res.Executions))
|
assert.Equal(t, 1, len(res.Executions))
|
||||||
|
@ -339,11 +338,11 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
assert.Equal(t, block.Hash(), res.Hash)
|
assert.Equal(t, block.Hash(), res.Hash)
|
||||||
for i := range res.Tx {
|
for i := range res.Tx {
|
||||||
tx := res.Tx[i]
|
tx := res.Tx[i]
|
||||||
require.Equal(t, transaction.MinerType, tx.Transaction.Type)
|
require.Equal(t, transaction.ContractType, tx.Transaction.Type)
|
||||||
|
|
||||||
miner := block.Transactions[i]
|
actualTx := block.Transactions[i]
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
require.Equal(t, miner.Nonce, tx.Transaction.Nonce)
|
require.Equal(t, actualTx.Nonce, tx.Transaction.Nonce)
|
||||||
require.Equal(t, block.Transactions[i].Hash(), tx.Transaction.Hash())
|
require.Equal(t, block.Transactions[i].Hash(), tx.Transaction.Hash())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -744,7 +743,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
"sendrawtransaction": {
|
"sendrawtransaction": {
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
params: `["80001300000075a94799633ed955dd85a8af314a5b435ab51903b00400000001eb15931b0544cbb9a283f934ab89a23e73cf90b9ca097bb327a0bcdcddf8ce2e010001f5bc5a9ac7b85a47be381260a06b5a1e7a667ce8f7d7c8baa5cfc6465571377a0030d3dec386230075a94799633ed955dd85a8af314a5b435ab5190301420c4082632495e555507a056eae951ad1893f27163dde40505340f6cf9578e20c3d7ec0c7e00f93cb2e770a7ce3e8a2910deabdd01fd966507a7a29106dd2add583ee290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"]`,
|
params: `["80000b00000075a94799633ed955dd85a8af314a5b435ab51903b004000000011e4db58df4326140a371d0b0cabecea70226b93157dfb561c73ba8db599ebcb6010001f5bc5a9ac7b85a47be381260a06b5a1e7a667ce8f7d7c8baa5cfc6465571377a0030d3dec386230075a94799633ed955dd85a8af314a5b435ab5190301420c401b3040b6eea83bfbd555554c94e7a0e6077922769f3ac19c1183e14dfd1d6ef6a87658b5499921ac59ae2d2acac10d8f0f6147620e27616bb5b7305fb36b6ce0290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"]`,
|
||||||
result: func(e *executor) interface{} {
|
result: func(e *executor) interface{} {
|
||||||
v := true
|
v := true
|
||||||
return &v
|
return &v
|
||||||
|
@ -858,7 +857,8 @@ func TestRPC(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
newTx := func() *transaction.Transaction {
|
newTx := func() *transaction.Transaction {
|
||||||
height := chain.BlockHeight()
|
height := chain.BlockHeight()
|
||||||
tx := transaction.NewMinerTXWithNonce(height + 1)
|
tx := transaction.NewContractTX()
|
||||||
|
tx.Nonce = height + 1
|
||||||
tx.ValidUntilBlock = height + 10
|
tx.ValidUntilBlock = height + 10
|
||||||
tx.Sender = acc.PrivateKey().GetScriptHash()
|
tx.Sender = acc.PrivateKey().GetScriptHash()
|
||||||
require.NoError(t, acc.SignTx(tx))
|
require.NoError(t, acc.SignTx(tx))
|
||||||
|
@ -883,7 +883,7 @@ func TestRPC(t *testing.T) {
|
||||||
|
|
||||||
t.Run("getrawtransaction", func(t *testing.T) {
|
t.Run("getrawtransaction", func(t *testing.T) {
|
||||||
block, _ := chain.GetBlock(chain.GetHeaderHash(0))
|
block, _ := chain.GetBlock(chain.GetHeaderHash(0))
|
||||||
TXHash := block.Transactions[1].Hash()
|
TXHash := block.Transactions[0].Hash()
|
||||||
rpc := fmt.Sprintf(`{"jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": ["%s"]}"`, TXHash.StringLE())
|
rpc := fmt.Sprintf(`{"jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": ["%s"]}"`, TXHash.StringLE())
|
||||||
body := doRPCCall(rpc, handler, t)
|
body := doRPCCall(rpc, handler, t)
|
||||||
result := checkErrGetResult(t, body, false)
|
result := checkErrGetResult(t, body, false)
|
||||||
|
@ -895,7 +895,7 @@ func TestRPC(t *testing.T) {
|
||||||
|
|
||||||
t.Run("getrawtransaction 2 arguments", func(t *testing.T) {
|
t.Run("getrawtransaction 2 arguments", func(t *testing.T) {
|
||||||
block, _ := chain.GetBlock(chain.GetHeaderHash(0))
|
block, _ := chain.GetBlock(chain.GetHeaderHash(0))
|
||||||
TXHash := block.Transactions[1].Hash()
|
TXHash := block.Transactions[0].Hash()
|
||||||
rpc := fmt.Sprintf(`{"jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": ["%s", 0]}"`, TXHash.StringLE())
|
rpc := fmt.Sprintf(`{"jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": ["%s", 0]}"`, TXHash.StringLE())
|
||||||
body := doRPCCall(rpc, handler, t)
|
body := doRPCCall(rpc, handler, t)
|
||||||
result := checkErrGetResult(t, body, false)
|
result := checkErrGetResult(t, body, false)
|
||||||
|
@ -907,7 +907,7 @@ func TestRPC(t *testing.T) {
|
||||||
|
|
||||||
t.Run("getrawtransaction 2 arguments, verbose", func(t *testing.T) {
|
t.Run("getrawtransaction 2 arguments, verbose", func(t *testing.T) {
|
||||||
block, _ := chain.GetBlock(chain.GetHeaderHash(0))
|
block, _ := chain.GetBlock(chain.GetHeaderHash(0))
|
||||||
TXHash := block.Transactions[1].Hash()
|
TXHash := block.Transactions[0].Hash()
|
||||||
rpc := fmt.Sprintf(`{"jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": ["%s", 1]}"`, TXHash.StringLE())
|
rpc := fmt.Sprintf(`{"jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": ["%s", 1]}"`, TXHash.StringLE())
|
||||||
body := doRPCCall(rpc, handler, t)
|
body := doRPCCall(rpc, handler, t)
|
||||||
txOut := checkErrGetResult(t, body, false)
|
txOut := checkErrGetResult(t, body, false)
|
||||||
|
@ -967,7 +967,6 @@ func TestRPC(t *testing.T) {
|
||||||
MerkleRoot: hdr.MerkleRoot,
|
MerkleRoot: hdr.MerkleRoot,
|
||||||
Timestamp: hdr.Timestamp,
|
Timestamp: hdr.Timestamp,
|
||||||
Index: hdr.Index,
|
Index: hdr.Index,
|
||||||
Nonce: strconv.FormatUint(hdr.ConsensusData, 16),
|
|
||||||
NextConsensus: address.Uint160ToString(hdr.NextConsensus),
|
NextConsensus: address.Uint160ToString(hdr.NextConsensus),
|
||||||
Script: hdr.Script,
|
Script: hdr.Script,
|
||||||
Confirmations: e.chain.BlockHeight() - hdr.Index + 1,
|
Confirmations: e.chain.BlockHeight() - hdr.Index + 1,
|
||||||
|
@ -981,7 +980,8 @@ func TestRPC(t *testing.T) {
|
||||||
|
|
||||||
t.Run("gettxout", func(t *testing.T) {
|
t.Run("gettxout", func(t *testing.T) {
|
||||||
block, _ := chain.GetBlock(chain.GetHeaderHash(0))
|
block, _ := chain.GetBlock(chain.GetHeaderHash(0))
|
||||||
tx := block.Transactions[3]
|
require.Equal(t, 4, len(block.Transactions))
|
||||||
|
tx := block.Transactions[2]
|
||||||
rpc := fmt.Sprintf(`{"jsonrpc": "2.0", "id": 1, "method": "gettxout", "params": [%s, %d]}"`,
|
rpc := fmt.Sprintf(`{"jsonrpc": "2.0", "id": 1, "method": "gettxout", "params": [%s, %d]}"`,
|
||||||
`"`+tx.Hash().StringLE()+`"`, 0)
|
`"`+tx.Hash().StringLE()+`"`, 0)
|
||||||
body := doRPCCall(rpc, handler, t)
|
body := doRPCCall(rpc, handler, t)
|
||||||
|
@ -1004,7 +1004,7 @@ func TestRPC(t *testing.T) {
|
||||||
expected = append(expected, tx.Tx.Hash())
|
expected = append(expected, tx.Tx.Hash())
|
||||||
}
|
}
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
tx := transaction.NewMinerTX()
|
tx := transaction.NewContractTX()
|
||||||
assert.NoError(t, mp.Add(tx, &FeerStub{}))
|
assert.NoError(t, mp.Add(tx, &FeerStub{}))
|
||||||
expected = append(expected, tx.Hash())
|
expected = append(expected, tx.Hash())
|
||||||
}
|
}
|
||||||
|
@ -1049,12 +1049,15 @@ func newBlock(t *testing.T, bc blockchainer.Blockchainer, index uint32, txs ...*
|
||||||
b := &block.Block{
|
b := &block.Block{
|
||||||
Base: block.Base{
|
Base: block.Base{
|
||||||
PrevHash: hdr.Hash(),
|
PrevHash: hdr.Hash(),
|
||||||
Timestamp: uint32(time.Now().UTC().Unix()) + hdr.Index,
|
Timestamp: (uint64(time.Now().UTC().Unix()) + uint64(hdr.Index)) * 1000,
|
||||||
Index: hdr.Index + index,
|
Index: hdr.Index + index,
|
||||||
ConsensusData: 1111,
|
|
||||||
NextConsensus: witness.ScriptHash(),
|
NextConsensus: witness.ScriptHash(),
|
||||||
Script: witness,
|
Script: witness,
|
||||||
},
|
},
|
||||||
|
ConsensusData: block.ConsensusData{
|
||||||
|
PrimaryIndex: 0,
|
||||||
|
Nonce: 1111,
|
||||||
|
},
|
||||||
Transactions: txs,
|
Transactions: txs,
|
||||||
}
|
}
|
||||||
_ = b.RebuildMerkleRoot()
|
_ = b.RebuildMerkleRoot()
|
||||||
|
|
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
Binary file not shown.
Loading…
Reference in a new issue