diff --git a/go.mod b/go.mod index 0d4eb0ec8..9f503d101 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/go-redis/redis v6.10.2+incompatible github.com/go-yaml/yaml v2.1.0+incompatible 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/pkg/errors v0.8.1 github.com/prometheus/client_golang v1.2.1 diff --git a/go.sum b/go.sum index abbecef44..68831bf15 100644 --- a/go.sum +++ b/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-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-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/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= diff --git a/pkg/consensus/block.go b/pkg/consensus/block.go index 31b6a5e15..cc4a77f99 100644 --- a/pkg/consensus/block.go +++ b/pkg/consensus/block.go @@ -58,44 +58,23 @@ func (n *neoBlock) SetTransactions(txes []block.Transaction) { // Version implements block.Block interface. 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. 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. 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. -func (n *neoBlock) Timestamp() uint32 { return n.Block.Timestamp } - -// SetTimestamp implements block.Block interface. -func (n *neoBlock) SetTimestamp(ts uint32) { n.Block.Timestamp = ts } +func (n *neoBlock) Timestamp() uint64 { return n.Block.Timestamp * 1000000 } // Index implements block.Block interface. 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. -func (n *neoBlock) ConsensusData() uint64 { return n.Block.ConsensusData } - -// SetConsensusData implements block.Block interface. -func (n *neoBlock) SetConsensusData(nonce uint64) { n.Block.ConsensusData = nonce } +func (n *neoBlock) ConsensusData() uint64 { return n.Block.ConsensusData.Nonce } // NextConsensus implements block.Block interface. 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. func (n *neoBlock) Signature() []byte { return n.signature } diff --git a/pkg/consensus/block_test.go b/pkg/consensus/block_test.go index 0e9edf915..6e1d91f4e 100644 --- a/pkg/consensus/block_test.go +++ b/pkg/consensus/block_test.go @@ -22,28 +22,29 @@ func TestNeoBlock_Sign(t *testing.T) { func TestNeoBlock_Setters(t *testing.T) { b := new(neoBlock) - b.SetVersion(1) + b.Block.Version = 1 require.EqualValues(t, 1, b.Version()) - b.SetIndex(12) + b.Block.Index = 12 require.EqualValues(t, 12, b.Index()) - b.SetTimestamp(777) - require.EqualValues(t, 777, b.Timestamp()) + b.Block.Timestamp = 777 + // 777ms -> 777000000ns + require.EqualValues(t, 777000000, b.Timestamp()) - b.SetConsensusData(456) + b.Block.ConsensusData.Nonce = 456 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()) - b.SetNextConsensus(util.Uint160{9, 2}) + b.Block.NextConsensus = util.Uint160{9, 2} 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()) - txx := []block.Transaction{transaction.NewMinerTX()} + txx := []block.Transaction{transaction.NewIssueTX()} b.SetTransactions(txx) require.Equal(t, txx, b.Transactions()) } diff --git a/pkg/consensus/consensus.go b/pkg/consensus/consensus.go index 151160622..d31b9a8a9 100644 --- a/pkg/consensus/consensus.go +++ b/pkg/consensus/consensus.go @@ -2,15 +2,14 @@ package consensus import ( "errors" - "math/rand" "sort" "time" "github.com/nspcc-dev/dbft" "github.com/nspcc-dev/dbft/block" "github.com/nspcc-dev/dbft/crypto" + "github.com/nspcc-dev/dbft/merkle" "github.com/nspcc-dev/dbft/payload" - "github.com/nspcc-dev/neo-go/pkg/core" 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/mempool" @@ -136,7 +135,7 @@ func NewService(cfg Config) (Service, error) { dbft.WithVerifyBlock(srv.verifyBlock), dbft.WithGetBlock(srv.getBlock), dbft.WithWatchOnly(func() bool { return false }), - dbft.WithNewBlock(func() block.Block { return new(neoBlock) }), + dbft.WithNewBlockFromContext(newBlockFromContext), dbft.WithCurrentHeight(cfg.Chain.BlockHeight), dbft.WithCurrentBlockHash(cfg.Chain.CurrentBlockHash), dbft.WithGetValidators(srv.getValidators), @@ -276,7 +275,6 @@ func (s *service) OnPayload(cp *Payload) { switch cp.Type() { case payload.PrepareRequestType: req := cp.GetPrepareRequest().(*prepareRequest) - s.txx.Add(&req.minerTx) s.lastProposal = req.transactionHashes } @@ -316,12 +314,6 @@ func (s *service) GetPayload(h util.Uint256) *Payload { } 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 { 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) } - res := make([]block.Transaction, len(txx)+1) - var netFee util.Fixed8 + res := make([]block.Transaction, len(txx)) for i := range txx { - res[i+1] = txx[i].Tx - netFee += txx[i].Fee + res[i] = txx[i].Tx } - 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 } @@ -516,3 +479,30 @@ func convertKeys(validators []crypto.PublicKey) (pubs []*keys.PublicKey) { 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 +} diff --git a/pkg/consensus/consensus_test.go b/pkg/consensus/consensus_test.go index 01699a3ed..eaaacaa03 100644 --- a/pkg/consensus/consensus_test.go +++ b/pkg/consensus/consensus_test.go @@ -22,7 +22,7 @@ import ( func TestNewService(t *testing.T) { srv := newTestService(t) - tx := transaction.NewMinerTX() + tx := transaction.NewContractTX() tx.ValidUntilBlock = 1 addSender(t, tx) signTx(t, tx) @@ -30,8 +30,8 @@ func TestNewService(t *testing.T) { var txx []block.Transaction require.NotPanics(t, func() { txx = srv.getVerifiedTx(1) }) - require.Len(t, txx, 2) - require.Equal(t, tx, txx[1]) + require.Len(t, txx, 1) + require.Equal(t, tx, txx[0]) srv.Chain.Close() } @@ -39,7 +39,8 @@ func TestService_GetVerified(t *testing.T) { srv := newTestService(t) var txs []*transaction.Transaction for i := 0; i < 4; i++ { - tx := transaction.NewMinerTXWithNonce(123 + uint32(i)) + tx := transaction.NewContractTX() + tx.Nonce = 123 + uint32(i) tx.ValidUntilBlock = 1 txs = append(txs, tx) } @@ -52,7 +53,9 @@ func TestService_GetVerified(t *testing.T) { p := new(Payload) p.message = &message{} 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) 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) { txx := srv.getVerifiedTx(10) - require.Equal(t, 2, len(txx), "there is only 1 tx in mempool") - require.Equal(t, txs[3], txx[1]) + require.Equal(t, 1, len(txx), "there is only 1 tx in mempool") + require.Equal(t, txs[3], txx[0]) }) 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) t.Run("transaction in mempool", func(t *testing.T) { - tx := transaction.NewMinerTXWithNonce(1234) + tx := transaction.NewContractTX() + tx.Nonce = 1234 tx.ValidUntilBlock = 1 addSender(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) { - tx := transaction.NewMinerTXWithNonce(4321) + tx := transaction.NewContractTX() + tx.Nonce = 4321 tx.ValidUntilBlock = 1 h := tx.Hash() diff --git a/pkg/consensus/payload_test.go b/pkg/consensus/payload_test.go index 48bf020c0..c5563beea 100644 --- a/pkg/consensus/payload_test.go +++ b/pkg/consensus/payload_test.go @@ -243,14 +243,12 @@ func randomPrepareRequest(t *testing.T) *prepareRequest { const txCount = 3 req := &prepareRequest{ - timestamp: rand.Uint32(), + timestamp: rand.Uint64(), nonce: rand.Uint64(), transactionHashes: make([]util.Uint256, txCount), - minerTx: *transaction.NewMinerTX(), } - req.transactionHashes[0] = req.minerTx.Hash() - for i := 1; i < txCount; i++ { + for i := 0; i < txCount; i++ { req.transactionHashes[i] = random.Uint256() } req.nextConsensus = random.Uint160() diff --git a/pkg/consensus/prepare_request.go b/pkg/consensus/prepare_request.go index bbc7ce90b..fb1d314f9 100644 --- a/pkg/consensus/prepare_request.go +++ b/pkg/consensus/prepare_request.go @@ -2,17 +2,15 @@ package consensus import ( "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/util" ) // prepareRequest represents dBFT prepareRequest message. type prepareRequest struct { - timestamp uint32 + timestamp uint64 nonce uint64 transactionHashes []util.Uint256 - minerTx transaction.Transaction nextConsensus util.Uint160 } @@ -20,27 +18,25 @@ var _ payload.PrepareRequest = (*prepareRequest)(nil) // EncodeBinary implements io.Serializable interface. func (p *prepareRequest) EncodeBinary(w *io.BinWriter) { - w.WriteU32LE(p.timestamp) + w.WriteU64LE(p.timestamp) w.WriteU64LE(p.nonce) w.WriteBytes(p.nextConsensus[:]) w.WriteArray(p.transactionHashes) - p.minerTx.EncodeBinary(w) } // DecodeBinary implements io.Serializable interface. func (p *prepareRequest) DecodeBinary(r *io.BinReader) { - p.timestamp = r.ReadU32LE() + p.timestamp = r.ReadU64LE() p.nonce = r.ReadU64LE() r.ReadBytes(p.nextConsensus[:]) r.ReadArray(&p.transactionHashes) - p.minerTx.DecodeBinary(r) } // 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. -func (p *prepareRequest) SetTimestamp(ts uint32) { p.timestamp = ts } +func (p *prepareRequest) SetTimestamp(ts uint64) { p.timestamp = ts / 1000000 } // Nonce implements payload.PrepareRequest interface. func (p *prepareRequest) Nonce() uint64 { return p.nonce } diff --git a/pkg/consensus/prepare_request_test.go b/pkg/consensus/prepare_request_test.go index d7a3473b9..4b91e6cfb 100644 --- a/pkg/consensus/prepare_request_test.go +++ b/pkg/consensus/prepare_request_test.go @@ -12,7 +12,12 @@ func TestPrepareRequest_Setters(t *testing.T) { var p prepareRequest 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}) require.Equal(t, util.Uint160{5, 6, 7}, p.NextConsensus()) diff --git a/pkg/consensus/recovery_message_test.go b/pkg/consensus/recovery_message_test.go index 195b392ee..203edf45c 100644 --- a/pkg/consensus/recovery_message_test.go +++ b/pkg/consensus/recovery_message_test.go @@ -5,7 +5,6 @@ import ( "github.com/nspcc-dev/dbft/crypto" "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/util" "github.com/stretchr/testify/require" @@ -32,7 +31,6 @@ func TestRecoveryMessage_Setters(t *testing.T) { timestamp: 87, nonce: 321, transactionHashes: []util.Uint256{{1}}, - minerTx: *transaction.NewMinerTX(), nextConsensus: util.Uint160{1, 2}, } p1 := new(Payload) diff --git a/pkg/core/block/block.go b/pkg/core/block/block.go index 37ec73847..a9715d71e 100644 --- a/pkg/core/block/block.go +++ b/pkg/core/block/block.go @@ -2,7 +2,6 @@ package block import ( "errors" - "fmt" "github.com/Workiva/go-datastructures/queue" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -16,6 +15,9 @@ type Block struct { // The base of the block. Base + // Primary index and nonce + ConsensusData ConsensusData `json:"consensus_data"` + // Transaction list. Transactions []*transaction.Transaction `json:"tx"` @@ -30,10 +32,12 @@ func (b *Block) Header() *Header { } } -func merkleTreeFromTransactions(txes []*transaction.Transaction) (*hash.MerkleTree, error) { - hashes := make([]util.Uint256, len(txes)) - for i, tx := range txes { - hashes[i] = tx.Hash() +// computeMerkleTree computes Merkle tree based on actual block's data. +func (b *Block) computeMerkleTree() (*hash.MerkleTree, error) { + hashes := make([]util.Uint256, len(b.Transactions)+1) + hashes[0] = b.ConsensusData.Hash() + for i, tx := range b.Transactions { + hashes[i+1] = tx.Hash() } return hash.NewMerkleTree(hashes) @@ -41,7 +45,7 @@ func merkleTreeFromTransactions(txes []*transaction.Transaction) (*hash.MerkleTr // RebuildMerkleRoot rebuilds the merkleroot of the block. func (b *Block) RebuildMerkleRoot() error { - merkle, err := merkleTreeFromTransactions(b.Transactions) + merkle, err := b.computeMerkleTree() if err != nil { return err } @@ -52,21 +56,18 @@ func (b *Block) RebuildMerkleRoot() error { // Verify verifies the integrity of the block. func (b *Block) Verify() error { - // There has to be some transaction inside. - if len(b.Transactions) == 0 { - return errors.New("no transactions") - } - // The first TX has to be a miner transaction. - if b.Transactions[0].Type != transaction.MinerType { - return fmt.Errorf("the first transaction is %s", b.Transactions[0].Type) - } - // 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()) + if b.Transactions != nil { + hashes := map[util.Uint256]bool{} + for _, tx := range b.Transactions { + if !hashes[tx.Hash()] { + hashes[tx.Hash()] = true + } else { + return errors.New("transaction duplication is not allowed") + } } } - merkle, err := merkleTreeFromTransactions(b.Transactions) + + merkle, err := b.computeMerkleTree() if err != nil { return err } @@ -92,12 +93,18 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) { block.Script.DecodeBinary(br) - lenTX := br.ReadVarUint() - block.Transactions = make([]*transaction.Transaction, lenTX) - for i := 0; i < int(lenTX); i++ { - var hash util.Uint256 - hash.DecodeBinary(br) - block.Transactions[i] = transaction.NewTrimmedTX(hash) + lenHashes := br.ReadVarUint() + if lenHashes > 0 { + var consensusDataHash util.Uint256 + consensusDataHash.DecodeBinary(br) + lenTX := lenHashes - 1 + block.Transactions = make([]*transaction.Transaction, lenTX) + for i := 0; i < int(lenTX); i++ { + var hash util.Uint256 + hash.DecodeBinary(br) + block.Transactions[i] = transaction.NewTrimmedTX(hash) + } + block.ConsensusData.DecodeBinary(br) } return block, br.Err @@ -112,14 +119,20 @@ func (b *Block) Trim() ([]byte, error) { buf.WriteB(1) 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 { h := tx.Hash() h.EncodeBinary(buf.BinWriter) } + + b.ConsensusData.EncodeBinary(buf.BinWriter) if buf.Err != nil { return nil, buf.Err } + return buf.Bytes(), nil } @@ -127,14 +140,31 @@ func (b *Block) Trim() ([]byte, error) { // Serializable interface. func (b *Block) DecodeBinary(br *io.BinReader) { 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 // Serializable interface. func (b *Block) EncodeBinary(bw *io.BinWriter) { 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. diff --git a/pkg/core/block/block_base.go b/pkg/core/block/block_base.go index bfd5e4ab4..3b4073a5a 100644 --- a/pkg/core/block/block_base.go +++ b/pkg/core/block/block_base.go @@ -20,17 +20,15 @@ type Base struct { // Root hash of a transaction list. 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. // 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. - Timestamp uint32 `json:"time"` + Timestamp uint64 `json:"time"` // index/height of the block Index uint32 `json:"height"` - // Random number also called nonce - ConsensusData uint64 `json:"nonce"` - // Contract address of the next miner NextConsensus util.Uint160 `json:"next_consensus"` @@ -117,9 +115,8 @@ func (b *Base) encodeHashableFields(bw *io.BinWriter) { bw.WriteU32LE(b.Version) bw.WriteBytes(b.PrevHash[:]) bw.WriteBytes(b.MerkleRoot[:]) - bw.WriteU32LE(b.Timestamp) + bw.WriteU64LE(b.Timestamp) bw.WriteU32LE(b.Index) - bw.WriteU64LE(b.ConsensusData) bw.WriteBytes(b.NextConsensus[:]) } @@ -129,9 +126,8 @@ func (b *Base) decodeHashableFields(br *io.BinReader) { b.Version = br.ReadU32LE() br.ReadBytes(b.PrevHash[:]) br.ReadBytes(b.MerkleRoot[:]) - b.Timestamp = br.ReadU32LE() + b.Timestamp = br.ReadU64LE() b.Index = br.ReadU32LE() - b.ConsensusData = br.ReadU64LE() br.ReadBytes(b.NextConsensus[:]) // Make the hash of the block here so we dont need to do this diff --git a/pkg/core/block/block_test.go b/pkg/core/block/block_test.go index 15e6acd37..f3461ffbd 100644 --- a/pkg/core/block/block_test.go +++ b/pkg/core/block/block_test.go @@ -71,17 +71,19 @@ func newDumbBlock() *Block { Version: 0, PrevHash: hash.Sha256([]byte("a")), MerkleRoot: hash.Sha256([]byte("b")), - Timestamp: uint32(100500), + Timestamp: 100500, Index: 1, - ConsensusData: 1111, NextConsensus: hash.Hash160([]byte("a")), Script: transaction.Witness{ VerificationScript: []byte{0x51}, // PUSH1 InvocationScript: []byte{0x61}, // NOP }, }, + ConsensusData: ConsensusData{ + PrimaryIndex: 0, + Nonce: 1111, + }, Transactions: []*transaction.Transaction{ - transaction.NewMinerTX(), transaction.NewIssueTX(), }, } @@ -99,25 +101,9 @@ func TestBlockVerify(t *testing.T) { assert.Nil(t, block.RebuildMerkleRoot()) assert.Nil(t, block.Verify()) - block.Transactions = []*transaction.Transaction{ - transaction.NewIssueTX(), - transaction.NewMinerTX(), - } + block.Transactions = []*transaction.Transaction{} assert.NoError(t, block.RebuildMerkleRoot()) - assert.NotNil(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()) + assert.Nil(t, block.Verify()) } //TODO NEO3.0: Update binary diff --git a/pkg/core/block/consensus_data.go b/pkg/core/block/consensus_data.go new file mode 100644 index 000000000..ef8cc6f95 --- /dev/null +++ b/pkg/core/block/consensus_data.go @@ -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 +} diff --git a/pkg/core/block/header_test.go b/pkg/core/block/header_test.go index 55b20b24b..989920fbf 100644 --- a/pkg/core/block/header_test.go +++ b/pkg/core/block/header_test.go @@ -16,9 +16,8 @@ func TestHeaderEncodeDecode(t *testing.T) { Version: 0, PrevHash: hash.Sha256([]byte("prevhash")), MerkleRoot: hash.Sha256([]byte("merkleroot")), - Timestamp: uint32(time.Now().UTC().Unix()), + Timestamp: uint64(time.Now().UTC().Unix() * 1000), Index: 3445, - ConsensusData: 394949, NextConsensus: util.Uint160{}, Script: transaction.Witness{ 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.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.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.Script.InvocationScript, headerDecode.Script.InvocationScript, "expected equal invocation scripts") assert.Equal(t, header.Script.VerificationScript, headerDecode.Script.VerificationScript, "expected equal verification scripts") diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index af99c5de1..06ca8a4d6 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -914,9 +914,6 @@ func (bc *Blockchain) GetBlock(hash util.Uint256) (*block.Block, error) { if err != nil { return nil, err } - if len(block.Transactions) == 0 { - return nil, fmt.Errorf("only header is available") - } for _, tx := range block.Transactions { stx, _, err := bc.dao.GetTransaction(tx.Hash()) if err != nil { @@ -1118,7 +1115,7 @@ func (bc *Blockchain) FeePerByte(t *transaction.Transaction) util.Fixed8 { // NetworkFee returns network fee. 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 - if t.Type == transaction.ClaimType || t.Type == transaction.MinerType { + if t.Type == transaction.ClaimType { return 0 } @@ -1455,7 +1452,7 @@ func (bc *Blockchain) verifyResults(t *transaction.Transaction, results []*trans } switch t.Type { - case transaction.MinerType, transaction.ClaimType: + case transaction.ClaimType: for _, r := range resultsIssue { if r.AssetID != UtilityTokenID() { return errors.New("miner or claim tx issues non-utility tokens") diff --git a/pkg/core/blockchain_test.go b/pkg/core/blockchain_test.go index 9724d755f..a106d4fba 100644 --- a/pkg/core/blockchain_test.go +++ b/pkg/core/blockchain_test.go @@ -97,7 +97,7 @@ func TestScriptFromWitness(t *testing.T) { func TestGetHeader(t *testing.T) { bc := newTestChain(t) - tx := transaction.NewMinerTX() + tx := transaction.NewContractTX() tx.ValidUntilBlock = bc.BlockHeight() + 1 assert.Nil(t, addSender(tx)) assert.Nil(t, signTx(bc, tx)) diff --git a/pkg/core/helper_test.go b/pkg/core/helper_test.go index f54b1ad23..ea0f00f60 100644 --- a/pkg/core/helper_test.go +++ b/pkg/core/helper_test.go @@ -61,12 +61,15 @@ func newBlock(cfg config.ProtocolConfiguration, index uint32, prev util.Uint256, Base: block.Base{ Version: 0, PrevHash: prev, - Timestamp: uint32(time.Now().UTC().Unix()) + index, + Timestamp: uint64(time.Now().UTC().Unix()) + uint64(index), Index: index, - ConsensusData: 1111, NextConsensus: witness.ScriptHash(), Script: witness, }, + ConsensusData: block.ConsensusData{ + PrimaryIndex: 0, + Nonce: 1111, + }, Transactions: txs, } _ = b.RebuildMerkleRoot() @@ -80,17 +83,7 @@ func (bc *Blockchain) genBlocks(n int) ([]*block.Block, error) { lastHash := bc.topBlock.Load().(*block.Block).Hash() lastIndex := bc.topBlock.Load().(*block.Block).Index for i := 0; i < n; i++ { - minerTx := transaction.NewMinerTXWithNonce(uint32(1234 + i)) - 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) + blocks[i] = newBlock(bc.config, uint32(i)+lastIndex+1, lastHash) if err := bc.AddBlock(blocks[i]); err != nil { return blocks, err } @@ -130,17 +123,19 @@ func newDumbBlock() *block.Block { Version: 0, PrevHash: hash.Sha256([]byte("a")), MerkleRoot: hash.Sha256([]byte("b")), - Timestamp: uint32(100500), + Timestamp: 100500, Index: 1, - ConsensusData: 1111, NextConsensus: hash.Hash160([]byte("a")), Script: transaction.Witness{ VerificationScript: []byte{0x51}, // PUSH1 InvocationScript: []byte{0x61}, // NOP }, }, + ConsensusData: block.ConsensusData{ + PrimaryIndex: 0, + Nonce: 1111, + }, Transactions: []*transaction.Transaction{ - {Type: transaction.MinerType}, {Type: transaction.IssueType}, }, } @@ -175,13 +170,6 @@ func TestCreateBasicChain(t *testing.T) { 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 neoRemainder = util.Fixed8FromInt64(100000000) - neoAmount bc := newTestChain(t) @@ -195,8 +183,8 @@ func TestCreateBasicChain(t *testing.T) { // use output of issue tx from genesis block as an input genesisBlock, err := bc.GetBlock(bc.GetHeaderHash(0)) require.NoError(t, err) - require.Equal(t, 5, len(genesisBlock.Transactions)) - h := genesisBlock.Transactions[3].Hash() + require.Equal(t, 4, len(genesisBlock.Transactions)) + h := genesisBlock.Transactions[2].Hash() txMoveNeo.AddInput(&transaction.Input{ PrevHash: h, PrevIndex: 0, @@ -219,12 +207,8 @@ func TestCreateBasicChain(t *testing.T) { Position: 1, }) txMoveNeo.Data = new(transaction.ContractTX) - - minerTx := nextMinerTx(validUntilBlock) - minerTx.Sender = neoOwner - - require.NoError(t, signTx(bc, minerTx, txMoveNeo)) - b := bc.newBlock(minerTx, txMoveNeo) + require.NoError(t, signTx(bc, txMoveNeo)) + b := bc.newBlock(txMoveNeo) require.NoError(t, bc.AddBlock(b)) t.Logf("txMoveNeo: %s", txMoveNeo.Hash().StringLE()) @@ -258,10 +242,7 @@ func TestCreateBasicChain(t *testing.T) { }) txNeoRound.Data = new(transaction.ContractTX) require.NoError(t, acc0.SignTx(txNeoRound)) - minerTx = nextMinerTx(validUntilBlock) - minerTx.Sender = priv0ScriptHash - require.NoError(t, acc0.SignTx(minerTx)) - b = bc.newBlock(minerTx, txNeoRound) + b = bc.newBlock(txNeoRound) require.NoError(t, bc.AddBlock(b)) t.Logf("txNeoRound: %s", txNeoRound.Hash().StringLE()) @@ -285,10 +266,7 @@ func TestCreateBasicChain(t *testing.T) { Position: 0, }) require.NoError(t, acc0.SignTx(txClaim)) - minerTx = nextMinerTx(validUntilBlock) - minerTx.Sender = priv0ScriptHash - require.NoError(t, acc0.SignTx(minerTx)) - b = bc.newBlock(minerTx, txClaim) + b = bc.newBlock(txClaim) require.NoError(t, bc.AddBlock(b)) t.Logf("txClaim: %s", txClaim.Hash().StringLE()) @@ -331,10 +309,7 @@ func TestCreateBasicChain(t *testing.T) { }) gasOwned -= invFee require.NoError(t, acc0.SignTx(txDeploy)) - minerTx = nextMinerTx(validUntilBlock) - minerTx.Sender = priv0ScriptHash - require.NoError(t, acc0.SignTx(minerTx)) - b = bc.newBlock(minerTx, txDeploy) + b = bc.newBlock(txDeploy) require.NoError(t, bc.AddBlock(b)) t.Logf("txDeploy: %s", txDeploy.Hash().StringLE()) @@ -347,10 +322,7 @@ func TestCreateBasicChain(t *testing.T) { txInv.ValidUntilBlock = validUntilBlock txInv.Sender = priv0ScriptHash require.NoError(t, acc0.SignTx(txInv)) - minerTx = nextMinerTx(validUntilBlock) - minerTx.Sender = priv0ScriptHash - require.NoError(t, acc0.SignTx(minerTx)) - b = bc.newBlock(minerTx, txInv) + b = bc.newBlock(txInv) require.NoError(t, bc.AddBlock(b)) t.Logf("txInv: %s", txInv.Hash().StringLE()) @@ -376,10 +348,7 @@ func TestCreateBasicChain(t *testing.T) { }) require.NoError(t, acc0.SignTx(txNeo0to1)) - minerTx = nextMinerTx(validUntilBlock) - minerTx.Sender = priv0ScriptHash - require.NoError(t, acc0.SignTx(minerTx)) - b = bc.newBlock(minerTx, txNeo0to1) + b = bc.newBlock(txNeo0to1) require.NoError(t, bc.AddBlock(b)) sh := hash.Hash160(avm) @@ -396,10 +365,7 @@ func TestCreateBasicChain(t *testing.T) { transferTx.Sender = priv0ScriptHash require.NoError(t, acc0.SignTx(transferTx)) - minerTx = nextMinerTx(validUntilBlock) - minerTx.Sender = priv0ScriptHash - require.NoError(t, acc0.SignTx(minerTx)) - b = bc.newBlock(minerTx, initTx, transferTx) + b = bc.newBlock(initTx, transferTx) require.NoError(t, bc.AddBlock(b)) transferTx = newNEP5Transfer(sh, priv0.GetScriptHash(), priv1.GetScriptHash(), 123) @@ -408,10 +374,7 @@ func TestCreateBasicChain(t *testing.T) { transferTx.Sender = priv0ScriptHash require.NoError(t, acc0.SignTx(transferTx)) - minerTx = nextMinerTx(validUntilBlock) - minerTx.Sender = priv0ScriptHash - require.NoError(t, acc0.SignTx(minerTx)) - b = bc.newBlock(minerTx, transferTx) + b = bc.newBlock(transferTx) require.NoError(t, bc.AddBlock(b)) if saveChain { diff --git a/pkg/core/interop_neo.go b/pkg/core/interop_neo.go index 065ecd8e5..6dcc1f9b9 100644 --- a/pkg/core/interop_neo.go +++ b/pkg/core/interop_neo.go @@ -48,16 +48,6 @@ func headerGetVersion(ic *interop.Context, v *vm.VM) error { 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. func headerGetMerkleRoot(ic *interop.Context, v *vm.VM) error { header, err := popHeaderFromVM(v) diff --git a/pkg/core/interop_neo_test.go b/pkg/core/interop_neo_test.go index d7625d681..24835af64 100644 --- a/pkg/core/interop_neo_test.go +++ b/pkg/core/interop_neo_test.go @@ -136,16 +136,6 @@ func TestHeaderGetVersion_Negative(t *testing.T) { 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) { v, block, context, chain := createVMAndPushBlock(t) defer chain.Close() diff --git a/pkg/core/interops.go b/pkg/core/interops.go index 0f2c2c203..93b03d778 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -151,7 +151,6 @@ var neoInterops = []interop.Function{ {Name: "Neo.Enumerator.Create", Func: enumerator.Create, Price: 1}, {Name: "Neo.Enumerator.Next", Func: enumerator.Next, 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.GetIndex", Func: headerGetIndex, 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.GetStorageContext", Func: contractGetStorageContext, Price: 1}, {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.GetMerkleRoot", Func: headerGetMerkleRoot, Price: 1}, {Name: "AntShares.Header.GetNextConsensus", Func: headerGetNextConsensus, Price: 1}, diff --git a/pkg/core/interops_test.go b/pkg/core/interops_test.go index 70dd25c8c..c1ca1bdfa 100644 --- a/pkg/core/interops_test.go +++ b/pkg/core/interops_test.go @@ -51,7 +51,6 @@ func TestUnexpectedNonInterops(t *testing.T) { contractGetScript, contractGetStorageContext, contractIsPayable, - headerGetConsensusData, headerGetHash, headerGetIndex, headerGetMerkleRoot, diff --git a/pkg/core/mempool/mem_pool_test.go b/pkg/core/mempool/mem_pool_test.go index bf5f2486c..bd6bd47fb 100644 --- a/pkg/core/mempool/mem_pool_test.go +++ b/pkg/core/mempool/mem_pool_test.go @@ -36,7 +36,8 @@ func (fs *FeerStub) SystemFee(*transaction.Transaction) util.Fixed8 { func testMemPoolAddRemoveWithFeer(t *testing.T, fs Feer) { mp := NewMemPool(10) - tx := transaction.NewMinerTXWithNonce(0) + tx := transaction.NewContractTX() + tx.Nonce = 0 _, _, ok := mp.TryGetValue(tx.Hash()) require.Equal(t, false, ok) require.NoError(t, mp.Add(tx, fs)) @@ -72,8 +73,8 @@ func TestMemPoolAddRemoveWithInputsAndClaims(t *testing.T) { mpLessClaims := func(i, j int) bool { return mp.claims[i].Cmp(mp.claims[j]) < 0 } - - txm1 := transaction.NewMinerTXWithNonce(1) + txm1 := transaction.NewContractTX() + txm1.Nonce = 1 txc1, claim1 := newClaimTX() for i := 0; i < 5; 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.True(t, sort.SliceIsSorted(mp.claims, mpLessClaims)) - txm2 := transaction.NewMinerTXWithNonce(1) + txm2 := transaction.NewContractTX() + txm2.Nonce = 1 txc2, claim2 := newClaimTX() for i := 0; i < 10; 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) { mp := NewMemPool(10) - tx := transaction.NewMinerTXWithNonce(1) + tx := transaction.NewContractTX() + tx.Nonce = 1 inhash1 := random.Uint256() tx.Inputs = append(tx.Inputs, transaction.Input{PrevHash: inhash1, PrevIndex: 0}) require.Equal(t, true, mp.Verify(tx)) require.NoError(t, mp.Add(tx, &FeerStub{})) - tx2 := transaction.NewMinerTXWithNonce(2) + tx2 := transaction.NewContractTX() + tx2.Nonce = 2 inhash2 := random.Uint256() tx2.Inputs = append(tx2.Inputs, transaction.Input{PrevHash: inhash2, PrevIndex: 0}) require.Equal(t, true, mp.Verify(tx2)) 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. tx3.Inputs = append(tx3.Inputs, transaction.Input{PrevHash: inhash1, PrevIndex: 1}) require.Equal(t, true, mp.Verify(tx3)) @@ -211,7 +216,8 @@ func TestOverCapacity(t *testing.T) { mp := NewMemPool(mempoolSize) 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)) } txcnt := uint32(mempoolSize) @@ -231,7 +237,8 @@ func TestOverCapacity(t *testing.T) { // Fees are also prioritized. fs.netFee = util.Fixed8FromFloat(0.0001) for i := 0; i < mempoolSize-1; i++ { - tx := transaction.NewMinerTXWithNonce(txcnt) + tx := transaction.NewContractTX() + tx.Nonce = txcnt txcnt++ require.NoError(t, mp.Add(tx, fs)) require.Equal(t, mempoolSize, mp.Count()) @@ -239,7 +246,8 @@ func TestOverCapacity(t *testing.T) { } // Less prioritized txes are not allowed anymore. fs.netFee = util.Fixed8FromFloat(0.00001) - tx := transaction.NewMinerTXWithNonce(txcnt) + tx := transaction.NewContractTX() + tx.Nonce = txcnt txcnt++ require.Error(t, mp.Add(tx, fs)) 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. fs.perByteFee = util.Fixed8FromFloat(0.001) - tx = transaction.NewMinerTXWithNonce(txcnt) + tx = transaction.NewContractTX() + tx.Nonce = txcnt txcnt++ require.NoError(t, mp.Add(tx, fs)) require.Equal(t, mempoolSize, mp.Count()) @@ -259,7 +268,8 @@ func TestOverCapacity(t *testing.T) { // High priority always wins over low priority. fs.lowPriority = false for i := 0; i < mempoolSize; i++ { - tx := transaction.NewMinerTXWithNonce(txcnt) + tx := transaction.NewContractTX() + tx.Nonce = txcnt txcnt++ require.NoError(t, mp.Add(tx, fs)) require.Equal(t, mempoolSize, mp.Count()) @@ -267,7 +277,8 @@ func TestOverCapacity(t *testing.T) { } // Good luck with low priority now. fs.lowPriority = true - tx = transaction.NewMinerTXWithNonce(txcnt) + tx = transaction.NewContractTX() + tx.Nonce = txcnt require.Error(t, mp.Add(tx, fs)) require.Equal(t, mempoolSize, mp.Count()) 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) for i := 0; i < mempoolSize; i++ { - tx := transaction.NewMinerTXWithNonce(uint32(i)) + tx := transaction.NewContractTX() + tx.Nonce = uint32(i) txes = append(txes, tx) require.NoError(t, mp.Add(tx, fs)) } @@ -305,7 +317,8 @@ func TestRemoveStale(t *testing.T) { txes1 := make([]*transaction.Transaction, 0, mempoolSize/2) txes2 := make([]*transaction.Transaction, 0, mempoolSize/2) for i := 0; i < mempoolSize; i++ { - tx := transaction.NewMinerTXWithNonce(uint32(i)) + tx := transaction.NewContractTX() + tx.Nonce = uint32(i) if i%2 == 0 { txes1 = append(txes1, tx) } else { diff --git a/pkg/core/native_contract_test.go b/pkg/core/native_contract_test.go index 4e17a36b6..90e422483 100644 --- a/pkg/core/native_contract_test.go +++ b/pkg/core/native_contract_test.go @@ -2,7 +2,6 @@ package core import ( "errors" - "math/rand" "testing" "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)) script := w.Bytes() tx := transaction.NewInvocationTX(script, 0) - mn := transaction.NewMinerTXWithNonce(rand.Uint32()) validUntil := chain.blockHeight + 1 tx.ValidUntilBlock = validUntil - mn.ValidUntilBlock = validUntil - require.NoError(t, addSender(tx, mn)) - require.NoError(t, signTx(chain, tx, mn)) - b := chain.newBlock(mn, tx) + require.NoError(t, addSender(tx)) + require.NoError(t, signTx(chain, tx)) + b := chain.newBlock(tx) require.NoError(t, chain.AddBlock(b)) res, err := chain.GetAppExecResult(tx.Hash()) diff --git a/pkg/core/state/nep5.go b/pkg/core/state/nep5.go index 91fe30932..a0631dd09 100644 --- a/pkg/core/state/nep5.go +++ b/pkg/core/state/nep5.go @@ -20,7 +20,7 @@ type NEP5TransferLog struct { } // 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. type NEP5Transfer struct { @@ -36,7 +36,7 @@ type NEP5Transfer struct { // Block is a number of block when the event occured. Block uint32 // Timestamp is the timestamp of the block where transfer occured. - Timestamp uint32 + Timestamp uint64 // Tx is a hash the transaction. Tx util.Uint256 } @@ -135,7 +135,7 @@ func (t *NEP5Transfer) EncodeBinary(w *io.BinWriter) { w.WriteBytes(t.From[:]) w.WriteBytes(t.To[:]) w.WriteU32LE(t.Block) - w.WriteU32LE(t.Timestamp) + w.WriteU64LE(t.Timestamp) w.WriteU64LE(uint64(t.Amount)) } @@ -146,6 +146,6 @@ func (t *NEP5Transfer) DecodeBinary(r *io.BinReader) { r.ReadBytes(t.From[:]) r.ReadBytes(t.To[:]) t.Block = r.ReadU32LE() - t.Timestamp = r.ReadU32LE() + t.Timestamp = r.ReadU64LE() t.Amount = int64(r.ReadU64LE()) } diff --git a/pkg/core/transaction/miner.go b/pkg/core/transaction/miner.go deleted file mode 100644 index 6fc262d8d..000000000 --- a/pkg/core/transaction/miner.go +++ /dev/null @@ -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) { -} diff --git a/pkg/core/transaction/miner_test.go b/pkg/core/transaction/miner_test.go deleted file mode 100644 index b15814952..000000000 --- a/pkg/core/transaction/miner_test.go +++ /dev/null @@ -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)) -} -*/ diff --git a/pkg/core/transaction/transaction.go b/pkg/core/transaction/transaction.go index c404a5e29..160270ed2 100644 --- a/pkg/core/transaction/transaction.go +++ b/pkg/core/transaction/transaction.go @@ -148,9 +148,6 @@ func (t *Transaction) decodeData(r *io.BinReader) { case InvocationType: t.Data = &InvocationTX{Version: t.Version} t.Data.(*InvocationTX).DecodeBinary(r) - case MinerType: - t.Data = &MinerTX{} - t.Data.(*MinerTX).DecodeBinary(r) case ClaimType: t.Data = &ClaimTX{} t.Data.(*ClaimTX).DecodeBinary(r) @@ -335,8 +332,6 @@ func (t *Transaction) UnmarshalJSON(data []byte) error { } t.Sender = sender switch tx.Type { - case MinerType: - t.Data = &MinerTX{} case ClaimType: t.Data = &ClaimTX{ Claims: tx.Claims, diff --git a/pkg/core/transaction/transaction_test.go b/pkg/core/transaction/transaction_test.go index 9050026ee..78e0a9d94 100644 --- a/pkg/core/transaction/transaction_test.go +++ b/pkg/core/transaction/transaction_test.go @@ -120,12 +120,6 @@ func TestMarshalUnmarshalJSONContractTX(t *testing.T) { testserdes.MarshalUnmarshalJSON(t, tx, new(Transaction)) } -func TestMarshalUnmarshalJSONMinerTX(t *testing.T) { - tx := NewMinerTX() - - testserdes.MarshalUnmarshalJSON(t, tx, new(Transaction)) -} - func TestMarshalUnmarshalJSONClaimTX(t *testing.T) { tx := &Transaction{ Type: ClaimType, diff --git a/pkg/core/transaction/type.go b/pkg/core/transaction/type.go index 8c3ab94a8..bf5d34420 100644 --- a/pkg/core/transaction/type.go +++ b/pkg/core/transaction/type.go @@ -11,7 +11,6 @@ type TXType uint8 // Constants for all valid transaction types. const ( - MinerType TXType = 0x00 IssueType TXType = 0x01 ClaimType TXType = 0x02 RegisterType TXType = 0x40 @@ -22,8 +21,6 @@ const ( // String implements the stringer interface. func (t TXType) String() string { switch t { - case MinerType: - return "MinerTransaction" case IssueType: return "IssueTransaction" case ClaimType: @@ -58,8 +55,6 @@ func (t *TXType) UnmarshalJSON(data []byte) error { // TXTypeFromString searches for TXType by string name. func TXTypeFromString(jsonString string) (TXType, error) { switch jsonString = strings.TrimSpace(jsonString); jsonString { - case "MinerTransaction": - return MinerType, nil case "IssueTransaction": return IssueType, nil case "ClaimTransaction": diff --git a/pkg/core/util.go b/pkg/core/util.go index 465e90d11..1c998d724 100644 --- a/pkg/core/util.go +++ b/pkg/core/util.go @@ -41,9 +41,8 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) base := block.Base{ Version: 0, 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, - ConsensusData: 2083236893, NextConsensus: nextConsensus, Script: transaction.Witness{ InvocationScript: []byte{}, @@ -60,9 +59,6 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) } scriptOut := hash.Hash160(rawScript) - minerTx := transaction.NewMinerTXWithNonce(2083236893) - minerTx.Sender = hash.Hash160([]byte{byte(opcode.PUSH1)}) - issueTx := transaction.NewIssueTX() // TODO NEO3.0: nonce should be constant to avoid variability of genesis block issueTx.Nonce = 0 @@ -84,12 +80,15 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) b := &block.Block{ Base: base, Transactions: []*transaction.Transaction{ - minerTx, &governingTokenTX, &utilityTokenTX, issueTx, deployNativeContracts(), }, + ConsensusData: block.ConsensusData{ + PrimaryIndex: 0, + Nonce: 2083236893, + }, } if err = b.RebuildMerkleRoot(); err != nil { diff --git a/pkg/core/util_test.go b/pkg/core/util_test.go index a3b9fc001..5bf66555d 100644 --- a/pkg/core/util_test.go +++ b/pkg/core/util_test.go @@ -20,7 +20,7 @@ func TestGenesisBlockMainNet(t *testing.T) { // have been changed. Consequently, hash of the genesis block has been changed. // Update expected genesis block hash for better times. // Old hash is "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf" - expect := "094c2c2db5dcb868d85aa4d652aed23bc67e7166f53223a228e382265b1be84b" + expect := "16ffda4cc6a9b0a0ca63f1571f7724418c43f014e2eb4e8614b4938ccf0f20f6" assert.Equal(t, expect, block.Hash().StringLE()) } diff --git a/pkg/network/payload/headers_test.go b/pkg/network/payload/headers_test.go index 729b258be..94ebdaf8b 100644 --- a/pkg/network/payload/headers_test.go +++ b/pkg/network/payload/headers_test.go @@ -1,7 +1,6 @@ package payload import ( - "encoding/hex" "testing" "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) { rawBlockHeaders := "010000000026b3c3df4dc1602a3b0e6989248b23275b5e4014a159af5dce69e16d4ab75f00f439321a51f425a530820cfe4d715bfd835b49687e87772f2c4737b8bc586dca7fda03580a000000bf14ff160228f0c059e75d652b5d3827bf04c165bbe9ef95cca4bf5501fd45014036fdd23248880c1c311bcd97df04fe6d740dc1bf340c26915f0466e31e81c039012eca7a760270389e04b58b99820fe49cf8c24c9afc65d696b4d3f406a1e6b5405172a9b461e68dd399c8716de11d31f7dd2ec3be327c636b024562db6ac5df1cffdbee74c994736fd49803234d2baffbc0054f28ba5ec76494a467b4106955bb4084af7746d269241628c667003e9d39288b190ad5cef218ada625cbba8be411bb153828d8d3634e8f586638e2448425bc5b671be69800392ccbdebc945a5099c7406f6a11824105ecad345e525957053e77fbc0119d6b3fa7f854527e816cfce0d95dac66888e07e8990c95103d8e46124aac16f152e088520d7ec8325e3a2456f840e5b77ef0e3c410b347ccaf8a87516d10b88d436563c80712153273993afc320ec49b638225f58de464a1345e62a564b398939f96f6f4b7cf21b583609f85495af1552102486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a7021024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d2102aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e2103b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c2103b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a2102ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba5542102df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e89509357ae00" @@ -84,3 +85,4 @@ func TestBinEncodeDecode(t *testing.T) { assert.NoError(t, err) assert.Equal(t, hex.EncodeToString(rawBlockBytes), hex.EncodeToString(data)) } +*/ diff --git a/pkg/network/server.go b/pkg/network/server.go index 729995067..638a86319 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -803,9 +803,6 @@ func (s *Server) relayBlock(b *block.Block) { // verifyAndPoolTX verifies the TX and adds it to the local mempool. func (s *Server) verifyAndPoolTX(t *transaction.Transaction) RelayReason { - if t.Type == transaction.MinerType { - return RelayInvalid - } if err := s.chain.PoolTx(t); err != nil { switch err { case core.ErrAlreadyExists: diff --git a/pkg/rpc/client/rpc_test.go b/pkg/rpc/client/rpc_test.go index f630868b2..d56168c28 100644 --- a/pkg/rpc/client/rpc_test.go +++ b/pkg/rpc/client/rpc_test.go @@ -136,17 +136,17 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ invoke: func(c *Client) (interface{}, error) { 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{} }, check: func(t *testing.T, c *Client, result interface{}) { res, ok := result.(*block.Block) require.True(t, ok) assert.Equal(t, uint32(0), res.Version) - assert.Equal(t, "66d1c140fbdc0eaa47e69a6a9c5034ebc3a449db98da565191ab863d1a079906", res.Hash().StringLE()) - assert.Equal(t, "8fed18d4cf93e3c1607df1ffcce54a39a25c0bb18f80542ebc7a236a9204aab3", res.PrevHash.StringLE()) - assert.Equal(t, "79e5361552be86156c86c000183526f22ce0c8a0be346e692f4b388810275f26", res.MerkleRoot.StringLE()) + assert.Equal(t, "81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb", res.Hash().StringLE()) + assert.Equal(t, "a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b", res.PrevHash.StringLE()) + assert.Equal(t, "e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0", res.MerkleRoot.StringLE()) 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) { 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{} { - hash, err := util.Uint256DecodeStringLE("66d1c140fbdc0eaa47e69a6a9c5034ebc3a449db98da565191ab863d1a079906") + hash, err := util.Uint256DecodeStringLE("81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb") if err != nil { panic(err) } - nextBlockHash, err := util.Uint256DecodeStringLE("f6749a5eb21273ec67951afd22282f002e605e210678c2fa765dbecf0124bd1a") + nextBlockHash, err := util.Uint256DecodeStringLE("d08e408909ae24de3470a3f231f966e15719910cb7b1a30f356b3e784c1ddf6a") if err != nil { panic(err) } - prevBlockHash, err := util.Uint256DecodeStringLE("8fed18d4cf93e3c1607df1ffcce54a39a25c0bb18f80542ebc7a236a9204aab3") + prevBlockHash, err := util.Uint256DecodeStringLE("a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b") if err != nil { panic(err) } - merkleRoot, err := util.Uint256DecodeStringLE("79e5361552be86156c86c000183526f22ce0c8a0be346e692f4b388810275f26") + merkleRoot, err := util.Uint256DecodeStringLE("e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0") if err != nil { panic(err) } - invScript, err := hex.DecodeString("40a6cc2c7fdee4f8fd97f84114d04edda16a37a4c088da9d5be3233e118fccdf73c0305d2cbd15ea0dbcedb594fec3044844e8f59f236ded7fccb1eda2eee2c76740197eba5d648d650ca1d73b8c0a0c7cdc22d31d7b2564764729d271e7ff6378c4f2228f657d65fec530f2af6cdc7af3bc2ab17a7b8175376601fb17ec951faf074038222bb0430f7808d333be3fb8e5b93c490dbb07e6c085350ba64cb7de61127067d1825de30915964dbb345f3b902d61dbf9a294c11ff6459000648f0dc4e66740926854a25b9ea87d7fffe0253bf2bcb3d153434cc0a8ba166136d16aef9a3de70ba3704ba3103a26d01c2bdbeb7262a19bbceab6a7487beba5e55f7ee768a080") + invScript, err := hex.DecodeString("0c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf8") if err != nil { panic(err) } - verifScript, err := hex.DecodeString("532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae") + verifScript, err := hex.DecodeString("130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb") if err != nil { panic(err) } - sender, err := address.StringToUint160("AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU") + sender, err := address.StringToUint160("Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy") if err != nil { panic(err) } - txInvScript, err := hex.DecodeString("40f50121bb6ec9d8e0d1c15eea66b2ff7b51bb1bc4b3da27d9eac1d46b59e6a319bb1db4eb710c7f1931b0c2deaa2389a0fc3fe8c761cec40906b7973450c43173402dc082417a6815e722216de0b857eda6c846bf435088d543d2ab89f1dd92488e87b4d2c6508b0db945cbe6968e85c1c6d57274bfc898e82876c5cb08613da5d64053100f0162a41709a37305c300e7d6ac0d46575aab98dade7375b8d9ca980086594f1288dc68da0e0e42913d1c68024f63442a79c9478971d3ad93c5467ec53040a1c3a772a88b09cba8cc8ec3b46c0c0db6ac86519a7fd7db29b43d34e804a22d8839eaeb35e2a1e05d591fbad4ae290b90c6dc02dddbe28b2b3bf0fec2a337dd") + txInvScript, err := hex.DecodeString("0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7") if err != nil { panic(err) } - txVerifScript, err := hex.DecodeString("532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae") + txVerifScript, err := hex.DecodeString("130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb") if err != nil { panic(err) } - tx := transaction.NewMinerTXWithNonce(1237) + tx := transaction.NewContractTX() + tx.Nonce = 1237 tx.ValidUntilBlock = 5 tx.Sender = sender tx.Scripts = []transaction.Witness{ @@ -205,16 +206,19 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ _ = tx.Hash() return &result.Block{ Hash: hash, - Size: 946, + Size: 977, Version: 0, NextBlockHash: &nextBlockHash, PreviousBlockHash: prevBlockHash, MerkleRoot: merkleRoot, - Time: 1587379353, + Time: 1587727442, Index: 5, - Nonce: "0000000000000457", - NextConsensus: "AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU", + NextConsensus: "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy", Confirmations: 203, + ConsensusData: result.ConsensusData{ + PrimaryIndex: 0, + Nonce: "0000000000000457", + }, Script: transaction.Witness{ InvocationScript: invScript, VerificationScript: verifScript, @@ -232,73 +236,74 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ { name: "byHash_positive", invoke: func(c *Client) (interface{}, error) { - hash, err := util.Uint256DecodeStringLE("0699071a3d86ab915156da98db49a4c3eb34509c6a9ae647aa0edcfb40c1d166") + hash, err := util.Uint256DecodeStringLE("e9f71b58764157f1e2c3e29f217e654b57956ee7c8a60496b03ea85e39084b42") if err != nil { panic(err) } 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{} }, check: func(t *testing.T, c *Client, result interface{}) { res, ok := result.(*block.Block) require.True(t, ok) assert.Equal(t, uint32(0), res.Version) - assert.Equal(t, "66d1c140fbdc0eaa47e69a6a9c5034ebc3a449db98da565191ab863d1a079906", res.Hash().StringLE()) - assert.Equal(t, "8fed18d4cf93e3c1607df1ffcce54a39a25c0bb18f80542ebc7a236a9204aab3", res.PrevHash.StringLE()) - assert.Equal(t, "79e5361552be86156c86c000183526f22ce0c8a0be346e692f4b388810275f26", res.MerkleRoot.StringLE()) + assert.Equal(t, "81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb", res.Hash().StringLE()) + assert.Equal(t, "a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b", res.PrevHash.StringLE()) + assert.Equal(t, "e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0", res.MerkleRoot.StringLE()) 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", invoke: func(c *Client) (i interface{}, err error) { - hash, err := util.Uint256DecodeStringLE("0699071a3d86ab915156da98db49a4c3eb34509c6a9ae647aa0edcfb40c1d166") + hash, err := util.Uint256DecodeStringLE("bb09d40563c7141215b024b0959aec00a3ab316248c2ee31f32ea4c3cf4db781") if err != nil { panic(err) } 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{} { - hash, err := util.Uint256DecodeStringLE("66d1c140fbdc0eaa47e69a6a9c5034ebc3a449db98da565191ab863d1a079906") + hash, err := util.Uint256DecodeStringLE("81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb") if err != nil { panic(err) } - nextBlockHash, err := util.Uint256DecodeStringLE("f6749a5eb21273ec67951afd22282f002e605e210678c2fa765dbecf0124bd1a") + nextBlockHash, err := util.Uint256DecodeStringLE("d08e408909ae24de3470a3f231f966e15719910cb7b1a30f356b3e784c1ddf6a") if err != nil { panic(err) } - prevBlockHash, err := util.Uint256DecodeStringLE("8fed18d4cf93e3c1607df1ffcce54a39a25c0bb18f80542ebc7a236a9204aab3") + prevBlockHash, err := util.Uint256DecodeStringLE("a39a1769af16a1aa6715179884d503a1266461cf7100a1c73cb1180956cf255b") if err != nil { panic(err) } - merkleRoot, err := util.Uint256DecodeStringLE("79e5361552be86156c86c000183526f22ce0c8a0be346e692f4b388810275f26") + merkleRoot, err := util.Uint256DecodeStringLE("e74f202d6a9a8dd6ed52f7a8e1bbde8b0f86f801cad5692d391643de9a355cc0") if err != nil { panic(err) } - invScript, err := hex.DecodeString("40a6cc2c7fdee4f8fd97f84114d04edda16a37a4c088da9d5be3233e118fccdf73c0305d2cbd15ea0dbcedb594fec3044844e8f59f236ded7fccb1eda2eee2c76740197eba5d648d650ca1d73b8c0a0c7cdc22d31d7b2564764729d271e7ff6378c4f2228f657d65fec530f2af6cdc7af3bc2ab17a7b8175376601fb17ec951faf074038222bb0430f7808d333be3fb8e5b93c490dbb07e6c085350ba64cb7de61127067d1825de30915964dbb345f3b902d61dbf9a294c11ff6459000648f0dc4e66740926854a25b9ea87d7fffe0253bf2bcb3d153434cc0a8ba166136d16aef9a3de70ba3704ba3103a26d01c2bdbeb7262a19bbceab6a7487beba5e55f7ee768a080") + invScript, err := hex.DecodeString("0c407f70912fdcd0ce9a70963110eb39ef73ed02512ea63bc1c55577474df8f364a874999b16666888f8a3ca69873054a31ab42dd1fee1ed8605ff65edb39797e34e0c40d59459cb1cc8270d9a813aa444852a5d7714aed0b25373ec07549349c6db32b6c8c2e43cdd7b1ad2a4154cb5ff1222d9d7010877016a59775abdd2c08f253c850c4048b65cb58e0d58f2dd0f5db3b195c5784933d6179d8317217ba46f9deac9a667bffb1afd0dd86bdae6267af4c2605f7401849a0b980fcecfeae95df7f5ca6e140c406d9b1942c5aa80070ad484b3dd76421a3f46327670bea94e3ecb3a94eef8843a75195b55872a7c503acb01ab368cdaa11a9e5fb80d55bbd6b861233ba84edcf8") if err != nil { panic(err) } - verifScript, err := hex.DecodeString("532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae") + verifScript, err := hex.DecodeString("130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb") if err != nil { panic(err) } - sender, err := address.StringToUint160("AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU") + sender, err := address.StringToUint160("Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy") if err != nil { panic(err) } - txInvScript, err := hex.DecodeString("40f50121bb6ec9d8e0d1c15eea66b2ff7b51bb1bc4b3da27d9eac1d46b59e6a319bb1db4eb710c7f1931b0c2deaa2389a0fc3fe8c761cec40906b7973450c43173402dc082417a6815e722216de0b857eda6c846bf435088d543d2ab89f1dd92488e87b4d2c6508b0db945cbe6968e85c1c6d57274bfc898e82876c5cb08613da5d64053100f0162a41709a37305c300e7d6ac0d46575aab98dade7375b8d9ca980086594f1288dc68da0e0e42913d1c68024f63442a79c9478971d3ad93c5467ec53040a1c3a772a88b09cba8cc8ec3b46c0c0db6ac86519a7fd7db29b43d34e804a22d8839eaeb35e2a1e05d591fbad4ae290b90c6dc02dddbe28b2b3bf0fec2a337dd") + txInvScript, err := hex.DecodeString("0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7") if err != nil { panic(err) } - txVerifScript, err := hex.DecodeString("532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae") + txVerifScript, err := hex.DecodeString("130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb") if err != nil { panic(err) } - tx := transaction.NewMinerTXWithNonce(1237) + tx := transaction.NewContractTX() + tx.Nonce = 1237 tx.ValidUntilBlock = 5 tx.Sender = sender tx.Scripts = []transaction.Witness{ @@ -311,16 +316,19 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ _ = tx.Hash() return &result.Block{ Hash: hash, - Size: 946, + Size: 977, Version: 0, NextBlockHash: &nextBlockHash, PreviousBlockHash: prevBlockHash, MerkleRoot: merkleRoot, - Time: 1587379353, + Time: 1587727442, Index: 5, - Nonce: "0000000000000457", - NextConsensus: "AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU", + NextConsensus: "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy", Confirmations: 203, + ConsensusData: result.ConsensusData{ + PrimaryIndex: 0, + Nonce: "0000000000000457", + }, Script: transaction.Witness{ InvocationScript: invScript, VerificationScript: verifScript, @@ -368,21 +376,21 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ { name: "positive", invoke: func(c *Client) (interface{}, error) { - hash, err := util.Uint256DecodeStringLE("e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c") + hash, err := util.Uint256DecodeStringLE("68e4bd688b852e807eef13a0ff7da7b02223e359a35153667e88f9cb4a3b0801") if err != nil { panic(err) } 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{} }, check: func(t *testing.T, c *Client, result interface{}) { res, ok := result.(*block.Header) require.True(t, ok) assert.Equal(t, uint32(0), res.Version) - assert.Equal(t, "e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c", res.Hash().StringLE()) - assert.Equal(t, "996e37358dc369912041f966f8c5d8d3a8255ba5dcbd3447f8a82b55db869099", res.PrevHash.StringLE()) - assert.Equal(t, "cb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2", res.MerkleRoot.StringLE()) + assert.Equal(t, "68e4bd688b852e807eef13a0ff7da7b02223e359a35153667e88f9cb4a3b0801", res.Hash().StringLE()) + assert.Equal(t, "b9cddf4889cafff0399c598086f8acaeb6cef84fd2373453b03ed6495eda39d0", res.PrevHash.StringLE()) + assert.Equal(t, "07c06af53c7da479dbbbcef457e521767fe73b4e415893d645cf91ca1fef3d4a", res.MerkleRoot.StringLE()) }, }, { @@ -429,7 +437,6 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ MerkleRoot: merkleRoot, Timestamp: 1541215200, Index: 1, - Nonce: "51b484a2fe49ed4d", NextConsensus: "AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU", Confirmations: 20061, Script: transaction.Witness{ @@ -646,51 +653,52 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ { name: "positive", invoke: func(c *Client) (i interface{}, err error) { - hash, err := util.Uint256DecodeStringLE("265f271088384b2f696e34bea0c8e02cf226351800c0866c1586be521536e579") + hash, err := util.Uint256DecodeStringLE("b3ce8376ec464b198132fcc37fbff62fb39e6fd7f16e82074cc53d263851d969") if err != nil { panic(err) } 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{} }, check: func(t *testing.T, c *Client, result interface{}) { res, ok := result.(*transaction.Transaction) require.True(t, ok) assert.Equal(t, uint8(0), res.Version) - assert.Equal(t, "265f271088384b2f696e34bea0c8e02cf226351800c0866c1586be521536e579", res.Hash().StringBE()) - assert.Equal(t, transaction.MinerType, res.Type) + assert.Equal(t, "b3ce8376ec464b198132fcc37fbff62fb39e6fd7f16e82074cc53d263851d969", res.Hash().StringBE()) + assert.Equal(t, transaction.ContractType, res.Type) assert.Equal(t, false, res.Trimmed) }, }, { name: "verbose_positive", invoke: func(c *Client) (interface{}, error) { - hash, err := util.Uint256DecodeStringLE("265f271088384b2f696e34bea0c8e02cf226351800c0866c1586be521536e579") + hash, err := util.Uint256DecodeStringLE("b3ce8376ec464b198132fcc37fbff62fb39e6fd7f16e82074cc53d263851d969") if err != nil { panic(err) } 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{} { - blockHash, err := util.Uint256DecodeStringLE("66d1c140fbdc0eaa47e69a6a9c5034ebc3a449db98da565191ab863d1a079906") + blockHash, err := util.Uint256DecodeStringLE("81b74dcfc3a42ef331eec2486231aba300ec9a95b024b0151214c76305d409bb") if err != nil { panic(err) } - sender, err := address.StringToUint160("AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU") + sender, err := address.StringToUint160("Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy") if err != nil { panic(err) } - invocation, err := hex.DecodeString("40f50121bb6ec9d8e0d1c15eea66b2ff7b51bb1bc4b3da27d9eac1d46b59e6a319bb1db4eb710c7f1931b0c2deaa2389a0fc3fe8c761cec40906b7973450c43173402dc082417a6815e722216de0b857eda6c846bf435088d543d2ab89f1dd92488e87b4d2c6508b0db945cbe6968e85c1c6d57274bfc898e82876c5cb08613da5d64053100f0162a41709a37305c300e7d6ac0d46575aab98dade7375b8d9ca980086594f1288dc68da0e0e42913d1c68024f63442a79c9478971d3ad93c5467ec53040a1c3a772a88b09cba8cc8ec3b46c0c0db6ac86519a7fd7db29b43d34e804a22d8839eaeb35e2a1e05d591fbad4ae290b90c6dc02dddbe28b2b3bf0fec2a337dd") + invocation, err := hex.DecodeString("0c40ae62dadb95b21628921adb9ee14e8c1f20d68b9d6ffba218f8e403af70126449435a53525cd6f1d1c871e64a91025866cd8a413ec70e3cde0ddf62931aa22baa0c40c3e09fc8ad46789d645240634ef40bd180e0dba75beae07a37dc2e899b68b4b3b3a67d076ea9444ed143dbb3264702914a4662ff95859d32c9b5bb5bdc9ec1d60c40b2511115482bd860d85f57103fb8cce2cb45ba8461d4e164685b426cb5df1525e6f09dd7aa23db0fec2241bde7c925e22f3cba3824ea461455515dc2a1455f5e0c40c0aee2528e7fd75a0434f4d67da58507e8d349ca29e01e7eafa9f283e8b8c05d06587db7234f111730c14c8a4bfb7a1ffd9493b9696c71e68966c6bf4a832ab7") if err != nil { panic(err) } - verification, err := hex.DecodeString("532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae") + verification, err := hex.DecodeString("130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb") if err != nil { panic(err) } - tx := transaction.NewMinerTXWithNonce(1237) + tx := transaction.NewContractTX() + tx.Nonce = 1237 tx.ValidUntilBlock = 5 tx.Sender = sender tx.Scripts = []transaction.Witness{ @@ -709,7 +717,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ NetFee: 0, Blockhash: blockHash, Confirmations: 205, - Timestamp: uint32(1587379353), + Timestamp: uint64(1587727442), }, } }, @@ -904,7 +912,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ { name: "positive", 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}`, result: func(c *Client) interface{} { @@ -1025,7 +1033,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ { name: "sendrawtransaction_bad_server_answer", 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", invoke: func(c *Client) (interface{}, error) { - return nil, c.SendRawTransaction(transaction.NewMinerTX()) + return nil, c.SendRawTransaction(transaction.NewContractTX()) }, }, { diff --git a/pkg/rpc/response/result/block.go b/pkg/rpc/response/result/block.go index 8f02a2999..ccdef6fd5 100644 --- a/pkg/rpc/response/result/block.go +++ b/pkg/rpc/response/result/block.go @@ -27,6 +27,12 @@ type ( 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.Block / block.Base on the RPC Server. Block struct { @@ -36,9 +42,9 @@ type ( NextBlockHash *util.Uint256 `json:"nextblockhash,omitempty"` PreviousBlockHash util.Uint256 `json:"previousblockhash"` MerkleRoot util.Uint256 `json:"merkleroot"` - Time uint32 `json:"time"` + Time uint64 `json:"time"` Index uint32 `json:"index"` - Nonce string `json:"nonce"` + ConsensusData ConsensusData `json:"consensus_data"` NextConsensus string `json:"nextconsensus"` Confirmations uint32 `json:"confirmations"` @@ -59,9 +65,12 @@ func NewBlock(b *block.Block, chain blockchainer.Blockchainer) Block { MerkleRoot: b.MerkleRoot, Time: b.Timestamp, Index: b.Index, - Nonce: fmt.Sprintf("%016x", b.ConsensusData), - NextConsensus: address.Uint160ToString(b.NextConsensus), - Confirmations: chain.BlockHeight() - b.Index - 1, + ConsensusData: ConsensusData{ + PrimaryIndex: b.ConsensusData.PrimaryIndex, + Nonce: fmt.Sprintf("%016x", b.ConsensusData.Nonce), + }, + NextConsensus: address.Uint160ToString(b.NextConsensus), + Confirmations: chain.BlockHeight() - b.Index - 1, Script: b.Script, diff --git a/pkg/rpc/response/result/block_header.go b/pkg/rpc/response/result/block_header.go index 886903500..1eeabd4eb 100644 --- a/pkg/rpc/response/result/block_header.go +++ b/pkg/rpc/response/result/block_header.go @@ -1,8 +1,6 @@ package result import ( - "strconv" - "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/blockchainer" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -20,9 +18,8 @@ type ( Version uint32 `json:"version"` PrevBlockHash util.Uint256 `json:"previousblockhash"` MerkleRoot util.Uint256 `json:"merkleroot"` - Timestamp uint32 `json:"time"` + Timestamp uint64 `json:"time"` Index uint32 `json:"index"` - Nonce string `json:"nonce"` NextConsensus string `json:"nextconsensus"` Script transaction.Witness `json:"script"` Confirmations uint32 `json:"confirmations"` @@ -40,7 +37,6 @@ func NewHeader(h *block.Header, chain blockchainer.Blockchainer) Header { MerkleRoot: h.MerkleRoot, Timestamp: h.Timestamp, Index: h.Index, - Nonce: strconv.FormatUint(h.ConsensusData, 16), NextConsensus: address.Uint160ToString(h.NextConsensus), Script: h.Script, Confirmations: chain.BlockHeight() - h.Index + 1, diff --git a/pkg/rpc/response/result/nep5.go b/pkg/rpc/response/result/nep5.go index 897c82345..fb906192b 100644 --- a/pkg/rpc/response/result/nep5.go +++ b/pkg/rpc/response/result/nep5.go @@ -35,7 +35,7 @@ type NEP5Transfers struct { // NEP5Transfer represents single NEP5 transfer event. type NEP5Transfer struct { - Timestamp uint32 `json:"timestamp"` + Timestamp uint64 `json:"timestamp"` Asset util.Uint160 `json:"asset_hash"` Address string `json:"transfer_address,omitempty"` Amount string `json:"amount"` diff --git a/pkg/rpc/response/result/tx_raw_output.go b/pkg/rpc/response/result/tx_raw_output.go index 3c0269022..886d865ed 100644 --- a/pkg/rpc/response/result/tx_raw_output.go +++ b/pkg/rpc/response/result/tx_raw_output.go @@ -23,7 +23,7 @@ type TransactionMetadata struct { NetFee util.Fixed8 `json:"net_fee"` Blockhash util.Uint256 `json:"blockhash,omitempty"` Confirmations int `json:"confirmations,omitempty"` - Timestamp uint32 `json:"blocktime,omitempty"` + Timestamp uint64 `json:"blocktime,omitempty"` } // NewTransactionOutputRaw returns a new ransactionOutputRaw object. diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index ab5e059de..77b669db6 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -9,7 +9,6 @@ import ( "net/http" "net/http/httptest" "reflect" - "strconv" "strings" "testing" "time" @@ -54,12 +53,12 @@ var rpcTestCases = map[string][]rpcTestCase{ "getapplicationlog": { { name: "positive", - params: `["4108062977676178e8453a8ef84a702e01bb35af8a65c7529d04704fcb5f1e0e"]`, + params: `["fe1a3678b16eca35209acf85397708eb0f1668e4045ad4cd5d2453d3bc0a0a6d"]`, result: func(e *executor) interface{} { return &result.ApplicationLog{} }, check: func(t *testing.T, e *executor, acc interface{}) { res, ok := acc.(*result.ApplicationLog) require.True(t, ok) - expectedTxHash, err := util.Uint256DecodeStringLE("4108062977676178e8453a8ef84a702e01bb35af8a65c7529d04704fcb5f1e0e") + expectedTxHash, err := util.Uint256DecodeStringLE("fe1a3678b16eca35209acf85397708eb0f1668e4045ad4cd5d2453d3bc0a0a6d") require.NoError(t, err) assert.Equal(t, expectedTxHash, res.TxHash) assert.Equal(t, 1, len(res.Executions)) @@ -339,11 +338,11 @@ var rpcTestCases = map[string][]rpcTestCase{ assert.Equal(t, block.Hash(), res.Hash) for i := range res.Tx { 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.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()) } }, @@ -744,7 +743,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "sendrawtransaction": { { name: "positive", - params: `["80001300000075a94799633ed955dd85a8af314a5b435ab51903b00400000001eb15931b0544cbb9a283f934ab89a23e73cf90b9ca097bb327a0bcdcddf8ce2e010001f5bc5a9ac7b85a47be381260a06b5a1e7a667ce8f7d7c8baa5cfc6465571377a0030d3dec386230075a94799633ed955dd85a8af314a5b435ab5190301420c4082632495e555507a056eae951ad1893f27163dde40505340f6cf9578e20c3d7ec0c7e00f93cb2e770a7ce3e8a2910deabdd01fd966507a7a29106dd2add583ee290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"]`, + params: `["80000b00000075a94799633ed955dd85a8af314a5b435ab51903b004000000011e4db58df4326140a371d0b0cabecea70226b93157dfb561c73ba8db599ebcb6010001f5bc5a9ac7b85a47be381260a06b5a1e7a667ce8f7d7c8baa5cfc6465571377a0030d3dec386230075a94799633ed955dd85a8af314a5b435ab5190301420c401b3040b6eea83bfbd555554c94e7a0e6077922769f3ac19c1183e14dfd1d6ef6a87658b5499921ac59ae2d2acac10d8f0f6147620e27616bb5b7305fb36b6ce0290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"]`, result: func(e *executor) interface{} { v := true return &v @@ -858,7 +857,8 @@ func TestRPC(t *testing.T) { require.NoError(t, err) newTx := func() *transaction.Transaction { height := chain.BlockHeight() - tx := transaction.NewMinerTXWithNonce(height + 1) + tx := transaction.NewContractTX() + tx.Nonce = height + 1 tx.ValidUntilBlock = height + 10 tx.Sender = acc.PrivateKey().GetScriptHash() require.NoError(t, acc.SignTx(tx)) @@ -883,7 +883,7 @@ func TestRPC(t *testing.T) { t.Run("getrawtransaction", func(t *testing.T) { 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()) body := doRPCCall(rpc, handler, t) result := checkErrGetResult(t, body, false) @@ -895,7 +895,7 @@ func TestRPC(t *testing.T) { t.Run("getrawtransaction 2 arguments", func(t *testing.T) { 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()) body := doRPCCall(rpc, handler, t) result := checkErrGetResult(t, body, false) @@ -907,7 +907,7 @@ func TestRPC(t *testing.T) { t.Run("getrawtransaction 2 arguments, verbose", func(t *testing.T) { 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()) body := doRPCCall(rpc, handler, t) txOut := checkErrGetResult(t, body, false) @@ -967,7 +967,6 @@ func TestRPC(t *testing.T) { MerkleRoot: hdr.MerkleRoot, Timestamp: hdr.Timestamp, Index: hdr.Index, - Nonce: strconv.FormatUint(hdr.ConsensusData, 16), NextConsensus: address.Uint160ToString(hdr.NextConsensus), Script: hdr.Script, Confirmations: e.chain.BlockHeight() - hdr.Index + 1, @@ -981,7 +980,8 @@ func TestRPC(t *testing.T) { t.Run("gettxout", func(t *testing.T) { 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]}"`, `"`+tx.Hash().StringLE()+`"`, 0) body := doRPCCall(rpc, handler, t) @@ -1004,7 +1004,7 @@ func TestRPC(t *testing.T) { expected = append(expected, tx.Tx.Hash()) } for i := 0; i < 5; i++ { - tx := transaction.NewMinerTX() + tx := transaction.NewContractTX() assert.NoError(t, mp.Add(tx, &FeerStub{})) expected = append(expected, tx.Hash()) } @@ -1049,12 +1049,15 @@ func newBlock(t *testing.T, bc blockchainer.Blockchainer, index uint32, txs ...* b := &block.Block{ Base: block.Base{ 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, - ConsensusData: 1111, NextConsensus: witness.ScriptHash(), Script: witness, }, + ConsensusData: block.ConsensusData{ + PrimaryIndex: 0, + Nonce: 1111, + }, Transactions: txs, } _ = b.RebuildMerkleRoot() diff --git a/pkg/rpc/server/testdata/testblocks.acc b/pkg/rpc/server/testdata/testblocks.acc index ba7136e26..1885c851b 100644 Binary files a/pkg/rpc/server/testdata/testblocks.acc and b/pkg/rpc/server/testdata/testblocks.acc differ