From 63c56cca5c3fac51f0b46135d550c161ced9f331 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 14 Jan 2020 15:32:07 +0300 Subject: [PATCH] core: refactor out Block, BlockBase and Header structs See #597. --- cli/server/server.go | 3 +- pkg/consensus/block.go | 4 +-- pkg/consensus/consensus.go | 5 ++-- pkg/core/{ => block}/block.go | 6 ++-- pkg/core/{ => block}/block_base.go | 2 +- pkg/core/{ => block}/block_test.go | 8 +++--- pkg/core/{ => block}/header.go | 2 +- pkg/core/{ => block}/header_test.go | 2 +- pkg/core/block/helper_test.go | 44 +++++++++++++++++++++++++++++ pkg/core/blockchain.go | 29 ++++++++++--------- pkg/core/blockchain_test.go | 3 +- pkg/core/blockchainer.go | 11 ++++---- pkg/core/dao.go | 9 +++--- pkg/core/dao_test.go | 15 +++++----- pkg/core/helper_test.go | 41 +++++++++++++++++++++------ pkg/core/interop_neo_test.go | 3 +- pkg/core/interop_system.go | 15 +++++----- pkg/core/interops.go | 5 ++-- pkg/core/util.go | 13 +++++---- pkg/network/blockqueue.go | 5 ++-- pkg/network/blockqueue_test.go | 6 ++-- pkg/network/helper_test.go | 11 ++++---- pkg/network/message.go | 4 +-- pkg/network/payload/headers.go | 8 +++--- pkg/network/payload/headers_test.go | 8 +++--- pkg/network/payload/merkleblock.go | 8 +++--- pkg/network/server.go | 9 +++--- pkg/rpc/server_helper_test.go | 7 +++-- pkg/rpc/wrappers/block.go | 7 +++-- pkg/rpc/wrappers/tx_raw_output.go | 3 +- 30 files changed, 190 insertions(+), 106 deletions(-) rename pkg/core/{ => block}/block.go (96%) rename pkg/core/{ => block}/block_base.go (99%) rename pkg/core/{ => block}/block_test.go (99%) rename pkg/core/{ => block}/header.go (97%) rename pkg/core/{ => block}/header_test.go (99%) create mode 100644 pkg/core/block/helper_test.go diff --git a/cli/server/server.go b/cli/server/server.go index 42a5a7259..f560a245c 100644 --- a/cli/server/server.go +++ b/cli/server/server.go @@ -8,6 +8,7 @@ import ( "github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/pkg/core" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/io" @@ -268,7 +269,7 @@ func restoreDB(ctx *cli.Context) error { } for ; i < skip+count; i++ { bytes, err := readBlock(reader) - block := &core.Block{} + block := &block.Block{} newReader := io.NewBinReaderFromBuf(bytes) block.DecodeBinary(newReader) if err != nil { diff --git a/pkg/consensus/block.go b/pkg/consensus/block.go index 6d9c6dc27..f71f4bfb5 100644 --- a/pkg/consensus/block.go +++ b/pkg/consensus/block.go @@ -1,7 +1,7 @@ package consensus import ( - "github.com/CityOfZion/neo-go/pkg/core" + coreb "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/util" "github.com/nspcc-dev/dbft/block" @@ -11,7 +11,7 @@ import ( // neoBlock is a wrapper of core.Block which implements // methods necessary for dBFT library. type neoBlock struct { - core.Block + coreb.Block signature []byte } diff --git a/pkg/consensus/consensus.go b/pkg/consensus/consensus.go index 6aebda543..8f96d8d5b 100644 --- a/pkg/consensus/consensus.go +++ b/pkg/consensus/consensus.go @@ -8,6 +8,7 @@ import ( "github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/pkg/core" + coreb "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/keys" @@ -67,7 +68,7 @@ type Config struct { Broadcast func(p *Payload) // RelayBlock is a callback that is called to notify server // about the new block that needs to be broadcasted. - RelayBlock func(b *core.Block) + RelayBlock func(b *coreb.Block) // Chain is a core.Blockchainer instance. Chain core.Blockchainer // RequestTx is a callback to which will be called @@ -285,7 +286,7 @@ func (s *service) processBlock(b block.Block) { } } -func (s *service) getBlockWitness(b *core.Block) *transaction.Witness { +func (s *service) getBlockWitness(b *coreb.Block) *transaction.Witness { dctx := s.dbft.Context pubs := convertKeys(dctx.Validators) sigs := make(map[*keys.PublicKey][]byte) diff --git a/pkg/core/block.go b/pkg/core/block/block.go similarity index 96% rename from pkg/core/block.go rename to pkg/core/block/block.go index a7e2b4791..3077095c7 100644 --- a/pkg/core/block.go +++ b/pkg/core/block/block.go @@ -1,4 +1,4 @@ -package core +package block import ( "errors" @@ -39,8 +39,8 @@ func merkleTreeFromTransactions(txes []*transaction.Transaction) (*hash.MerkleTr return hash.NewMerkleTree(hashes) } -// rebuildMerkleRoot rebuilds the merkleroot of the block. -func (b *Block) rebuildMerkleRoot() error { +// RebuildMerkleRoot rebuilds the merkleroot of the block. +func (b *Block) RebuildMerkleRoot() error { merkle, err := merkleTreeFromTransactions(b.Transactions) if err != nil { return err diff --git a/pkg/core/block_base.go b/pkg/core/block/block_base.go similarity index 99% rename from pkg/core/block_base.go rename to pkg/core/block/block_base.go index 9e6c1d0b5..404701059 100644 --- a/pkg/core/block_base.go +++ b/pkg/core/block/block_base.go @@ -1,4 +1,4 @@ -package core +package block import ( "fmt" diff --git a/pkg/core/block_test.go b/pkg/core/block/block_test.go similarity index 99% rename from pkg/core/block_test.go rename to pkg/core/block/block_test.go index 82118b6ea..42355e9c0 100644 --- a/pkg/core/block_test.go +++ b/pkg/core/block/block_test.go @@ -1,4 +1,4 @@ -package core +package block import ( "encoding/hex" @@ -108,21 +108,21 @@ func TestHashBlockEqualsHashHeader(t *testing.T) { func TestBlockVerify(t *testing.T) { block := newDumbBlock() assert.NotNil(t, block.Verify()) - assert.Nil(t, block.rebuildMerkleRoot()) + assert.Nil(t, block.RebuildMerkleRoot()) assert.Nil(t, block.Verify()) block.Transactions = []*transaction.Transaction{ {Type: transaction.IssueType}, {Type: transaction.MinerType}, } - assert.NoError(t, block.rebuildMerkleRoot()) + assert.NoError(t, block.RebuildMerkleRoot()) assert.NotNil(t, block.Verify()) block.Transactions = []*transaction.Transaction{ {Type: transaction.MinerType}, {Type: transaction.MinerType}, } - assert.NoError(t, block.rebuildMerkleRoot()) + assert.NoError(t, block.RebuildMerkleRoot()) assert.NotNil(t, block.Verify()) block.Transactions = []*transaction.Transaction{ {Type: transaction.MinerType}, diff --git a/pkg/core/header.go b/pkg/core/block/header.go similarity index 97% rename from pkg/core/header.go rename to pkg/core/block/header.go index e3bf50824..5f9060f3d 100644 --- a/pkg/core/header.go +++ b/pkg/core/block/header.go @@ -1,4 +1,4 @@ -package core +package block import ( "fmt" diff --git a/pkg/core/header_test.go b/pkg/core/block/header_test.go similarity index 99% rename from pkg/core/header_test.go rename to pkg/core/block/header_test.go index ed35c6f73..020afcbda 100644 --- a/pkg/core/header_test.go +++ b/pkg/core/block/header_test.go @@ -1,4 +1,4 @@ -package core +package block import ( "testing" diff --git a/pkg/core/block/helper_test.go b/pkg/core/block/helper_test.go new file mode 100644 index 000000000..31a8f29d8 --- /dev/null +++ b/pkg/core/block/helper_test.go @@ -0,0 +1,44 @@ +package block + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "io/ioutil" + "testing" + + "github.com/CityOfZion/neo-go/pkg/io" +) + +func getDecodedBlock(t *testing.T, i int) *Block { + data, err := getBlockData(i) + if err != nil { + t.Fatal(err) + } + + b, err := hex.DecodeString(data["raw"].(string)) + if err != nil { + t.Fatal(err) + } + + block := &Block{} + r := io.NewBinReaderFromBuf(b) + block.DecodeBinary(r) + if r.Err != nil { + t.Fatal(r.Err) + } + + return block +} + +func getBlockData(i int) (map[string]interface{}, error) { + b, err := ioutil.ReadFile(fmt.Sprintf("../test_data/block_%d.json", i)) + if err != nil { + return nil, err + } + var data map[string]interface{} + if err := json.Unmarshal(b, &data); err != nil { + return nil, err + } + return data, err +} diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 69cb4f9b8..cd0da4930 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -11,6 +11,7 @@ import ( "time" "github.com/CityOfZion/neo-go/config" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/transaction" @@ -179,7 +180,7 @@ func (bc *Blockchain) init() error { targetHash = genesisBlock.Hash() bc.headerList.Add(targetHash) } - headers := make([]*Header, 0) + headers := make([]*block.Header, 0) for hash != targetHash { header, err := bc.GetHeader(hash) @@ -242,7 +243,7 @@ func (bc *Blockchain) Close() { // AddBlock accepts successive block for the Blockchain, verifies it and // stores internally. Eventually it will be persisted to the backing storage. -func (bc *Blockchain) AddBlock(block *Block) error { +func (bc *Blockchain) AddBlock(block *block.Block) error { expectedHeight := bc.BlockHeight() + 1 if expectedHeight != block.Index { return fmt.Errorf("expected block %d, but passed block %d", expectedHeight, block.Index) @@ -276,7 +277,7 @@ func (bc *Blockchain) AddBlock(block *Block) error { // AddHeaders processes the given headers and add them to the // HeaderHashList. -func (bc *Blockchain) AddHeaders(headers ...*Header) (err error) { +func (bc *Blockchain) AddHeaders(headers ...*block.Header) (err error) { var ( start = time.Now() batch = bc.dao.store.Batch() @@ -321,7 +322,7 @@ func (bc *Blockchain) AddHeaders(headers ...*Header) (err error) { // processHeader processes the given header. Note that this is only thread safe // if executed in headers operation. -func (bc *Blockchain) processHeader(h *Header, batch storage.Batch, headerList *HeaderHashList) error { +func (bc *Blockchain) processHeader(h *block.Header, batch storage.Batch, headerList *HeaderHashList) error { headerList.Add(h.Hash()) buf := io.NewBufBinWriter() @@ -352,7 +353,7 @@ func (bc *Blockchain) processHeader(h *Header, batch storage.Batch, headerList * // project. This for the sake of development speed and understanding of what // is happening here, quite allot as you can see :). If things are wired together // and all tests are in place, we can make a more optimized and cleaner implementation. -func (bc *Blockchain) storeBlock(block *Block) error { +func (bc *Blockchain) storeBlock(block *block.Block) error { cache := newCachedDao(bc.dao.store) if err := cache.StoreAsBlock(block, 0); err != nil { return err @@ -756,10 +757,10 @@ func (bc *Blockchain) GetStorageItems(hash util.Uint160) (map[string]*state.Stor } // GetBlock returns a Block by the given hash. -func (bc *Blockchain) GetBlock(hash util.Uint256) (*Block, error) { +func (bc *Blockchain) GetBlock(hash util.Uint256) (*block.Block, error) { topBlock := bc.topBlock.Load() if topBlock != nil { - if tb, ok := topBlock.(*Block); ok && tb.Hash().Equals(hash) { + if tb, ok := topBlock.(*block.Block); ok && tb.Hash().Equals(hash) { return tb, nil } } @@ -782,10 +783,10 @@ func (bc *Blockchain) GetBlock(hash util.Uint256) (*Block, error) { } // GetHeader returns data block header identified with the given hash value. -func (bc *Blockchain) GetHeader(hash util.Uint256) (*Header, error) { +func (bc *Blockchain) GetHeader(hash util.Uint256) (*block.Header, error) { topBlock := bc.topBlock.Load() if topBlock != nil { - if tb, ok := topBlock.(*Block); ok && tb.Hash().Equals(hash) { + if tb, ok := topBlock.(*block.Block); ok && tb.Hash().Equals(hash) { return tb.Header(), nil } } @@ -955,7 +956,7 @@ func (bc *Blockchain) GetMemPool() MemPool { } // VerifyBlock verifies block against its current state. -func (bc *Blockchain) VerifyBlock(block *Block) error { +func (bc *Blockchain) VerifyBlock(block *block.Block) error { prevHeader, err := bc.GetHeader(block.PrevHash) if err != nil { return errors.Wrap(err, "unable to get previous header") @@ -973,7 +974,7 @@ func (bc *Blockchain) VerifyBlock(block *Block) error { // is used for easy interop access and can be omitted for transactions that are // not yet added into any block. // Golang implementation of Verify method in C# (https://github.com/neo-project/neo/blob/master/neo/Network/P2P/Payloads/Transaction.cs#L270). -func (bc *Blockchain) VerifyTx(t *transaction.Transaction, block *Block) error { +func (bc *Blockchain) VerifyTx(t *transaction.Transaction, block *block.Block) error { if io.GetVarSize(t) > transaction.MaxTransactionSize { return errors.Errorf("invalid transaction size = %d. It shoud be less then MaxTransactionSize = %d", io.GetVarSize(t), transaction.MaxTransactionSize) } @@ -1440,7 +1441,7 @@ func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transa // not yet added into any block. // Golang implementation of VerifyWitnesses method in C# (https://github.com/neo-project/neo/blob/master/neo/SmartContract/Helper.cs#L87). // Unfortunately the IVerifiable interface could not be implemented because we can't move the References method in blockchain.go to the transaction.go file. -func (bc *Blockchain) verifyTxWitnesses(t *transaction.Transaction, block *Block) error { +func (bc *Blockchain) verifyTxWitnesses(t *transaction.Transaction, block *block.Block) error { hashes, err := bc.GetScriptHashesForVerifying(t) if err != nil { return err @@ -1465,7 +1466,7 @@ func (bc *Blockchain) verifyTxWitnesses(t *transaction.Transaction, block *Block } // verifyBlockWitnesses is a block-specific implementation of VerifyWitnesses logic. -func (bc *Blockchain) verifyBlockWitnesses(block *Block, prevHeader *Header) error { +func (bc *Blockchain) verifyBlockWitnesses(block *block.Block, prevHeader *block.Header) error { var hash util.Uint160 if prevHeader == nil && block.PrevHash.Equals(util.Uint256{}) { hash = block.Script.ScriptHash() @@ -1487,6 +1488,6 @@ func (bc *Blockchain) secondsPerBlock() int { return bc.config.SecondsPerBlock } -func (bc *Blockchain) newInteropContext(trigger byte, s storage.Store, block *Block, tx *transaction.Transaction) *interopContext { +func (bc *Blockchain) newInteropContext(trigger byte, s storage.Store, block *block.Block, tx *transaction.Transaction) *interopContext { return newInteropContext(trigger, bc, s, block, tx, bc.log) } diff --git a/pkg/core/blockchain_test.go b/pkg/core/blockchain_test.go index 0fa8b3aae..a35245776 100644 --- a/pkg/core/blockchain_test.go +++ b/pkg/core/blockchain_test.go @@ -3,6 +3,7 @@ package core import ( "testing" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto/hash" @@ -38,7 +39,7 @@ func TestAddHeaders(t *testing.T) { func TestAddBlock(t *testing.T) { bc := newTestChain(t) - blocks := []*Block{ + blocks := []*block.Block{ newBlock(1, newMinerTX()), newBlock(2, newMinerTX()), newBlock(3, newMinerTX()), diff --git a/pkg/core/blockchainer.go b/pkg/core/blockchainer.go index 8493dec80..fdeaa6072 100644 --- a/pkg/core/blockchainer.go +++ b/pkg/core/blockchainer.go @@ -2,6 +2,7 @@ package core import ( "github.com/CityOfZion/neo-go/config" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/transaction" @@ -14,15 +15,15 @@ import ( // of the blockchain. type Blockchainer interface { GetConfig() config.ProtocolConfiguration - AddHeaders(...*Header) error - AddBlock(*Block) error + AddHeaders(...*block.Header) error + AddBlock(*block.Block) error BlockHeight() uint32 Close() HeaderHeight() uint32 - GetBlock(hash util.Uint256) (*Block, error) + GetBlock(hash util.Uint256) (*block.Block, error) GetContractState(hash util.Uint160) *state.Contract GetHeaderHash(int) util.Uint256 - GetHeader(hash util.Uint256) (*Header, error) + GetHeader(hash util.Uint256) (*block.Header, error) CurrentHeaderHash() util.Uint256 CurrentBlockHash() util.Uint256 HasBlock(util.Uint256) bool @@ -38,6 +39,6 @@ type Blockchainer interface { GetUnspentCoinState(util.Uint256) *UnspentCoinState References(t *transaction.Transaction) map[transaction.Input]*transaction.Output Feer // fee interface - VerifyTx(*transaction.Transaction, *Block) error + VerifyTx(*transaction.Transaction, *block.Block) error GetMemPool() MemPool } diff --git a/pkg/core/dao.go b/pkg/core/dao.go index d570d5e3e..4111fba66 100644 --- a/pkg/core/dao.go +++ b/pkg/core/dao.go @@ -6,6 +6,7 @@ import ( "fmt" "sort" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/transaction" @@ -358,13 +359,13 @@ func makeStorageItemKey(scripthash util.Uint160, key []byte) []byte { // -- other. // GetBlock returns Block by the given hash if it exists in the store. -func (dao *dao) GetBlock(hash util.Uint256) (*Block, error) { +func (dao *dao) GetBlock(hash util.Uint256) (*block.Block, error) { key := storage.AppendPrefix(storage.DataBlock, hash.BytesLE()) b, err := dao.store.Get(key) if err != nil { return nil, err } - block, err := NewBlockFromTrimmedBytes(b) + block, err := block.NewBlockFromTrimmedBytes(b) if err != nil { return nil, err } @@ -486,7 +487,7 @@ func (dao *dao) HasTransaction(hash util.Uint256) bool { } // StoreAsBlock stores the given block as DataBlock. -func (dao *dao) StoreAsBlock(block *Block, sysFee uint32) error { +func (dao *dao) StoreAsBlock(block *block.Block, sysFee uint32) error { var ( key = storage.AppendPrefix(storage.DataBlock, block.Hash().BytesLE()) buf = io.NewBufBinWriter() @@ -505,7 +506,7 @@ func (dao *dao) StoreAsBlock(block *Block, sysFee uint32) error { } // StoreAsCurrentBlock stores the given block witch prefix SYSCurrentBlock. -func (dao *dao) StoreAsCurrentBlock(block *Block) error { +func (dao *dao) StoreAsCurrentBlock(block *block.Block) error { buf := io.NewBufBinWriter() h := block.Hash() h.EncodeBinary(buf.BinWriter) diff --git a/pkg/core/dao_test.go b/pkg/core/dao_test.go index d747ddf19..cf06aa757 100644 --- a/pkg/core/dao_test.go +++ b/pkg/core/dao_test.go @@ -3,6 +3,7 @@ package core import ( "testing" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/transaction" @@ -260,16 +261,16 @@ func TestGetBlock_NotExists(t *testing.T) { func TestPutGetBlock(t *testing.T) { dao := newDao(storage.NewMemoryStore()) - block := &Block{ - BlockBase: BlockBase{ + b := &block.Block{ + BlockBase: block.BlockBase{ Script: transaction.Witness{ VerificationScript: []byte{byte(opcode.PUSH1)}, InvocationScript: []byte{byte(opcode.NOP)}, }, }, } - hash := block.Hash() - err := dao.StoreAsBlock(block, 0) + hash := b.Hash() + err := dao.StoreAsBlock(b, 0) require.NoError(t, err) gotBlock, err := dao.GetBlock(hash) require.NoError(t, err) @@ -301,15 +302,15 @@ func TestGetCurrentHeaderHeight_NoHeader(t *testing.T) { func TestGetCurrentHeaderHeight_Store(t *testing.T) { dao := newDao(storage.NewMemoryStore()) - block := &Block{ - BlockBase: BlockBase{ + b := &block.Block{ + BlockBase: block.BlockBase{ Script: transaction.Witness{ VerificationScript: []byte{byte(opcode.PUSH1)}, InvocationScript: []byte{byte(opcode.NOP)}, }, }, } - err := dao.StoreAsCurrentBlock(block) + err := dao.StoreAsCurrentBlock(b) require.NoError(t, err) height, err := dao.GetCurrentBlockHeight() require.NoError(t, err) diff --git a/pkg/core/helper_test.go b/pkg/core/helper_test.go index f750af78f..9a452ffc9 100644 --- a/pkg/core/helper_test.go +++ b/pkg/core/helper_test.go @@ -9,8 +9,10 @@ import ( "time" "github.com/CityOfZion/neo-go/config" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/transaction" + "github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/smartcontract" @@ -49,7 +51,7 @@ func newTestChain(t *testing.T) *Blockchain { return chain } -func newBlock(index uint32, txs ...*transaction.Transaction) *Block { +func newBlock(index uint32, txs ...*transaction.Transaction) *block.Block { validators, _ := getValidators(unitTestNetCfg.ProtocolConfiguration) vlen := len(validators) valScript, _ := smartcontract.CreateMultiSigRedeemScript( @@ -59,8 +61,8 @@ func newBlock(index uint32, txs ...*transaction.Transaction) *Block { witness := transaction.Witness{ VerificationScript: valScript, } - b := &Block{ - BlockBase: BlockBase{ + b := &block.Block{ + BlockBase: block.BlockBase{ Version: 0, PrevHash: newBlockPrevHash, Timestamp: uint32(time.Now().UTC().Unix()) + index, @@ -71,8 +73,7 @@ func newBlock(index uint32, txs ...*transaction.Transaction) *Block { }, Transactions: txs, } - _ = b.rebuildMerkleRoot() - b.createHash() + _ = b.RebuildMerkleRoot() newBlockPrevHash = b.Hash() invScript := make([]byte, 0) @@ -93,8 +94,8 @@ func newBlock(index uint32, txs ...*transaction.Transaction) *Block { return b } -func makeBlocks(n int) []*Block { - blocks := make([]*Block, n) +func makeBlocks(n int) []*block.Block { + blocks := make([]*block.Block, n) for i := 0; i < n; i++ { blocks[i] = newBlock(uint32(i+1), newMinerTX()) } @@ -108,7 +109,7 @@ func newMinerTX() *transaction.Transaction { } } -func getDecodedBlock(t *testing.T, i int) *Block { +func getDecodedBlock(t *testing.T, i int) *block.Block { data, err := getBlockData(i) if err != nil { t.Fatal(err) @@ -119,7 +120,7 @@ func getDecodedBlock(t *testing.T, i int) *Block { t.Fatal(err) } - block := &Block{} + block := &block.Block{} r := io.NewBinReaderFromBuf(b) block.DecodeBinary(r) if r.Err != nil { @@ -140,3 +141,25 @@ func getBlockData(i int) (map[string]interface{}, error) { } return data, err } + +func newDumbBlock() *block.Block { + return &block.Block{ + BlockBase: block.BlockBase{ + Version: 0, + PrevHash: hash.Sha256([]byte("a")), + MerkleRoot: hash.Sha256([]byte("b")), + Timestamp: uint32(100500), + Index: 1, + ConsensusData: 1111, + NextConsensus: hash.Hash160([]byte("a")), + Script: transaction.Witness{ + VerificationScript: []byte{0x51}, // PUSH1 + InvocationScript: []byte{0x61}, // NOP + }, + }, + Transactions: []*transaction.Transaction{ + {Type: transaction.MinerType}, + {Type: transaction.IssueType}, + }, + } +} diff --git a/pkg/core/interop_neo_test.go b/pkg/core/interop_neo_test.go index 39c43a714..f55a95cf9 100644 --- a/pkg/core/interop_neo_test.go +++ b/pkg/core/interop_neo_test.go @@ -4,6 +4,7 @@ import ( "math/big" "testing" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/transaction" @@ -451,7 +452,7 @@ func TestAssetGetPrecision(t *testing.T) { // Helper functions to create VM, InteropContext, TX, Account, Contract, Asset. -func createVMAndPushBlock(t *testing.T) (*vm.VM, *Block, *interopContext, *Blockchain) { +func createVMAndPushBlock(t *testing.T) (*vm.VM, *block.Block, *interopContext, *Blockchain) { v := vm.New() block := newDumbBlock() chain := newTestChain(t) diff --git a/pkg/core/interop_system.go b/pkg/core/interop_system.go index b96b5a0ec..9d8c930a8 100644 --- a/pkg/core/interop_system.go +++ b/pkg/core/interop_system.go @@ -5,6 +5,7 @@ import ( "fmt" "math" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto/hash" @@ -132,11 +133,11 @@ func (ic *interopContext) bcGetTransactionHeight(v *vm.VM) error { // popHeaderFromVM returns pointer to Header or error. It's main feature is // proper treatment of Block structure, because C# code implicitly assumes // that header APIs can also operate on blocks. -func popHeaderFromVM(v *vm.VM) (*Header, error) { +func popHeaderFromVM(v *vm.VM) (*block.Header, error) { iface := v.Estack().Pop().Value() - header, ok := iface.(*Header) + header, ok := iface.(*block.Header) if !ok { - block, ok := iface.(*Block) + block, ok := iface.(*block.Block) if !ok { return nil, errors.New("value is not a header or block") } @@ -188,7 +189,7 @@ func (ic *interopContext) headerGetTimestamp(v *vm.VM) error { // blockGetTransactionCount returns transactions count in the given block. func (ic *interopContext) blockGetTransactionCount(v *vm.VM) error { blockInterface := v.Estack().Pop().Value() - block, ok := blockInterface.(*Block) + block, ok := blockInterface.(*block.Block) if !ok { return errors.New("value is not a block") } @@ -199,7 +200,7 @@ func (ic *interopContext) blockGetTransactionCount(v *vm.VM) error { // blockGetTransactions returns transactions from the given block. func (ic *interopContext) blockGetTransactions(v *vm.VM) error { blockInterface := v.Estack().Pop().Value() - block, ok := blockInterface.(*Block) + block, ok := blockInterface.(*block.Block) if !ok { return errors.New("value is not a block") } @@ -218,7 +219,7 @@ func (ic *interopContext) blockGetTransactions(v *vm.VM) error { // block. func (ic *interopContext) blockGetTransaction(v *vm.VM) error { blockInterface := v.Estack().Pop().Value() - block, ok := blockInterface.(*Block) + block, ok := blockInterface.(*block.Block) if !ok { return errors.New("value is not a block") } @@ -359,7 +360,7 @@ func (ic *interopContext) runtimeLog(v *vm.VM) error { // runtimeGetTime returns timestamp of the block being verified, or the latest // one in the blockchain if no block is given to interopContext. func (ic *interopContext) runtimeGetTime(v *vm.VM) error { - var header *Header + var header *block.Header if ic.block == nil { var err error header, err = ic.bc.GetHeader(ic.bc.CurrentBlockHash()) diff --git a/pkg/core/interops.go b/pkg/core/interops.go index bf33b347d..15ee9b994 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -10,6 +10,7 @@ package core import ( "sort" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/transaction" @@ -20,14 +21,14 @@ import ( type interopContext struct { bc Blockchainer trigger byte - block *Block + block *block.Block tx *transaction.Transaction dao *cachedDao notifications []state.NotificationEvent log *zap.Logger } -func newInteropContext(trigger byte, bc Blockchainer, s storage.Store, block *Block, tx *transaction.Transaction, log *zap.Logger) *interopContext { +func newInteropContext(trigger byte, bc Blockchainer, s storage.Store, block *block.Block, tx *transaction.Transaction, log *zap.Logger) *interopContext { dao := newCachedDao(s) nes := make([]state.NotificationEvent, 0) return &interopContext{bc, trigger, block, tx, dao, nes, log} diff --git a/pkg/core/util.go b/pkg/core/util.go index c553f5ef0..3269035de 100644 --- a/pkg/core/util.go +++ b/pkg/core/util.go @@ -4,6 +4,7 @@ import ( "time" "github.com/CityOfZion/neo-go/config" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/keys" @@ -13,7 +14,7 @@ import ( ) // createGenesisBlock creates a genesis block based on the given configuration. -func createGenesisBlock(cfg config.ProtocolConfiguration) (*Block, error) { +func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) { validators, err := getValidators(cfg) if err != nil { return nil, err @@ -24,7 +25,7 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*Block, error) { return nil, err } - base := BlockBase{ + base := block.BlockBase{ Version: 0, PrevHash: util.Uint256{}, Timestamp: uint32(time.Date(2016, 7, 15, 15, 8, 21, 0, time.UTC).Unix()), @@ -48,7 +49,7 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*Block, error) { } scriptOut := hash.Hash160(rawScript) - block := &Block{ + b := &block.Block{ BlockBase: base, Transactions: []*transaction.Transaction{ { @@ -84,11 +85,11 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*Block, error) { }, } - if err = block.rebuildMerkleRoot(); err != nil { + if err = b.RebuildMerkleRoot(); err != nil { return nil, err } - return block, nil + return b, nil } func governingTokenTX() *transaction.Transaction { @@ -167,7 +168,7 @@ func calculateUtilityAmount() util.Fixed8 { } // headerSliceReverse reverses the given slice of *Header. -func headerSliceReverse(dest []*Header) { +func headerSliceReverse(dest []*block.Header) { for i, j := 0, len(dest)-1; i < j; i, j = i+1, j-1 { dest[i], dest[j] = dest[j], dest[i] } diff --git a/pkg/network/blockqueue.go b/pkg/network/blockqueue.go index bbd9f176a..e26d96629 100644 --- a/pkg/network/blockqueue.go +++ b/pkg/network/blockqueue.go @@ -2,6 +2,7 @@ package network import ( "github.com/CityOfZion/neo-go/pkg/core" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/Workiva/go-datastructures/queue" "go.uber.org/zap" ) @@ -37,7 +38,7 @@ func (bq *blockQueue) run() { if item == nil { break } - minblock := item.(*core.Block) + minblock := item.(*block.Block) if minblock.Index <= bq.chain.BlockHeight()+1 { _, _ = bq.queue.Get(1) updateBlockQueueLenMetric(bq.length()) @@ -57,7 +58,7 @@ func (bq *blockQueue) run() { } } -func (bq *blockQueue) putBlock(block *core.Block) error { +func (bq *blockQueue) putBlock(block *block.Block) error { if bq.chain.BlockHeight() >= block.Index { // can easily happen when fetching the same blocks from // different peers, thus not considered as error diff --git a/pkg/network/blockqueue_test.go b/pkg/network/blockqueue_test.go index f30b47a0a..881759d33 100644 --- a/pkg/network/blockqueue_test.go +++ b/pkg/network/blockqueue_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - "github.com/CityOfZion/neo-go/pkg/core" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/stretchr/testify/assert" "go.uber.org/zap/zaptest" ) @@ -13,9 +13,9 @@ func TestBlockQueue(t *testing.T) { chain := &testChain{} // notice, it's not yet running bq := newBlockQueue(0, chain, zaptest.NewLogger(t)) - blocks := make([]*core.Block, 11) + blocks := make([]*block.Block, 11) for i := 1; i < 11; i++ { - blocks[i] = &core.Block{BlockBase: core.BlockBase{Index: uint32(i)}} + blocks[i] = &block.Block{BlockBase: block.BlockBase{Index: uint32(i)}} } // not the ones expected currently for i := 3; i < 5; i++ { diff --git a/pkg/network/helper_test.go b/pkg/network/helper_test.go index 5fdc86e5f..e71fde016 100644 --- a/pkg/network/helper_test.go +++ b/pkg/network/helper_test.go @@ -9,6 +9,7 @@ import ( "github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/pkg/core" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/transaction" @@ -43,10 +44,10 @@ func (chain testChain) NetworkFee(t *transaction.Transaction) util.Fixed8 { panic("TODO") } -func (chain testChain) AddHeaders(...*core.Header) error { +func (chain testChain) AddHeaders(...*block.Header) error { panic("TODO") } -func (chain *testChain) AddBlock(block *core.Block) error { +func (chain *testChain) AddBlock(block *block.Block) error { if block.Index == chain.blockheight+1 { atomic.StoreUint32(&chain.blockheight, block.Index) } @@ -61,7 +62,7 @@ func (chain *testChain) Close() { func (chain testChain) HeaderHeight() uint32 { return 0 } -func (chain testChain) GetBlock(hash util.Uint256) (*core.Block, error) { +func (chain testChain) GetBlock(hash util.Uint256) (*block.Block, error) { panic("TODO") } func (chain testChain) GetContractState(hash util.Uint160) *state.Contract { @@ -70,7 +71,7 @@ func (chain testChain) GetContractState(hash util.Uint160) *state.Contract { func (chain testChain) GetHeaderHash(int) util.Uint256 { return util.Uint256{} } -func (chain testChain) GetHeader(hash util.Uint256) (*core.Header, error) { +func (chain testChain) GetHeader(hash util.Uint256) (*block.Header, error) { panic("TODO") } @@ -123,7 +124,7 @@ func (chain testChain) IsLowPriority(*transaction.Transaction) bool { panic("TODO") } -func (chain testChain) VerifyTx(*transaction.Transaction, *core.Block) error { +func (chain testChain) VerifyTx(*transaction.Transaction, *block.Block) error { panic("TODO") } diff --git a/pkg/network/message.go b/pkg/network/message.go index 087724967..973dee330 100644 --- a/pkg/network/message.go +++ b/pkg/network/message.go @@ -7,7 +7,7 @@ import ( "github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/pkg/consensus" - "github.com/CityOfZion/neo-go/pkg/core" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/io" @@ -184,7 +184,7 @@ func (m *Message) decodePayload(br *io.BinReader) error { case CMDAddr: p = &payload.AddressList{} case CMDBlock: - p = &core.Block{} + p = &block.Block{} case CMDConsensus: p = &consensus.Payload{} case CMDGetBlocks: diff --git a/pkg/network/payload/headers.go b/pkg/network/payload/headers.go index 57160c190..1b0ed7fd4 100644 --- a/pkg/network/payload/headers.go +++ b/pkg/network/payload/headers.go @@ -1,14 +1,14 @@ package payload import ( - "github.com/CityOfZion/neo-go/pkg/core" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/io" "github.com/pkg/errors" ) // Headers payload. type Headers struct { - Hdrs []*core.Header + Hdrs []*block.Header } // Users can at most request 2k header. @@ -30,10 +30,10 @@ func (p *Headers) DecodeBinary(br *io.BinReader) { lenHeaders = MaxHeadersAllowed } - p.Hdrs = make([]*core.Header, lenHeaders) + p.Hdrs = make([]*block.Header, lenHeaders) for i := 0; i < int(lenHeaders); i++ { - header := &core.Header{} + header := &block.Header{} header.DecodeBinary(br) p.Hdrs[i] = header } diff --git a/pkg/network/payload/headers_test.go b/pkg/network/payload/headers_test.go index 22762cc0e..f9fa957d0 100644 --- a/pkg/network/payload/headers_test.go +++ b/pkg/network/payload/headers_test.go @@ -4,7 +4,7 @@ import ( "encoding/hex" "testing" - "github.com/CityOfZion/neo-go/pkg/core" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/io" "github.com/stretchr/testify/assert" @@ -26,11 +26,11 @@ func TestHeadersEncodeDecode(t *testing.T) { } func newTestHeaders(n int) *Headers { - headers := &Headers{Hdrs: make([]*core.Header, n)} + headers := &Headers{Hdrs: make([]*block.Header, n)} for i := range headers.Hdrs { - headers.Hdrs[i] = &core.Header{ - BlockBase: core.BlockBase{ + headers.Hdrs[i] = &block.Header{ + BlockBase: block.BlockBase{ Index: uint32(i + 1), Script: transaction.Witness{ InvocationScript: []byte{0x0}, diff --git a/pkg/network/payload/merkleblock.go b/pkg/network/payload/merkleblock.go index 410e2b749..9759a853c 100644 --- a/pkg/network/payload/merkleblock.go +++ b/pkg/network/payload/merkleblock.go @@ -1,14 +1,14 @@ package payload import ( - "github.com/CityOfZion/neo-go/pkg/core" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) // MerkleBlock represents a merkle block packet payload. type MerkleBlock struct { - *core.BlockBase + *block.BlockBase TxCount int Hashes []util.Uint256 Flags []byte @@ -16,7 +16,7 @@ type MerkleBlock struct { // DecodeBinary implements Serializable interface. func (m *MerkleBlock) DecodeBinary(br *io.BinReader) { - m.BlockBase = &core.BlockBase{} + m.BlockBase = &block.BlockBase{} m.BlockBase.DecodeBinary(br) m.TxCount = int(br.ReadVarUint()) @@ -26,7 +26,7 @@ func (m *MerkleBlock) DecodeBinary(br *io.BinReader) { // EncodeBinary implements Serializable interface. func (m *MerkleBlock) EncodeBinary(bw *io.BinWriter) { - m.BlockBase = &core.BlockBase{} + m.BlockBase = &block.BlockBase{} m.BlockBase.EncodeBinary(bw) bw.WriteVarUint(uint64(m.TxCount)) diff --git a/pkg/network/server.go b/pkg/network/server.go index 9eabb5e7e..dbda99c9f 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -12,6 +12,7 @@ import ( "github.com/CityOfZion/neo-go/pkg/consensus" "github.com/CityOfZion/neo-go/pkg/core" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/network/payload" "github.com/CityOfZion/neo-go/pkg/util" @@ -400,7 +401,7 @@ func (s *Server) handleHeadersCmd(p Peer, headers *payload.Headers) { } // handleBlockCmd processes the received block received from its peer. -func (s *Server) handleBlockCmd(p Peer, block *core.Block) error { +func (s *Server) handleBlockCmd(p Peer, block *block.Block) error { return s.bQueue.putBlock(block) } @@ -505,7 +506,7 @@ func (s *Server) handleGetHeadersCmd(p Peer, gh *payload.GetBlocks) error { return err } resp := payload.Headers{} - resp.Hdrs = make([]*core.Header, 0, payload.MaxHeadersAllowed) + resp.Hdrs = make([]*block.Header, 0, payload.MaxHeadersAllowed) for i := start.Index + 1; i < start.Index+1+payload.MaxHeadersAllowed; i++ { hash := s.chain.GetHeaderHash(int(i)) if hash.Equals(util.Uint256{}) || hash.Equals(gh.HashStop) { @@ -632,7 +633,7 @@ func (s *Server) handleMessage(peer Peer, msg *Message) error { inventory := msg.Payload.(*payload.Inventory) return s.handleInvCmd(peer, inventory) case CMDBlock: - block := msg.Payload.(*core.Block) + block := msg.Payload.(*block.Block) return s.handleBlockCmd(peer, block) case CMDConsensus: cp := msg.Payload.(*consensus.Payload) @@ -689,7 +690,7 @@ func (s *Server) relayInventoryCmd(cmd CommandType, t payload.InventoryType, has } // relayBlock tells all the other connected nodes about the given block. -func (s *Server) relayBlock(b *core.Block) { +func (s *Server) relayBlock(b *block.Block) { s.relayInventoryCmd(CMDInv, payload.BlockType, b.Hash()) } diff --git a/pkg/rpc/server_helper_test.go b/pkg/rpc/server_helper_test.go index 5b0590f69..135e96f8a 100644 --- a/pkg/rpc/server_helper_test.go +++ b/pkg/rpc/server_helper_test.go @@ -7,6 +7,7 @@ import ( "github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/pkg/core" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/network" @@ -193,10 +194,10 @@ func initServerWithInMemoryChain(t *testing.T) (*core.Blockchain, http.HandlerFu nBlocks = br.ReadU32LE() require.Nil(t, br.Err) for i := 0; i < int(nBlocks); i++ { - block := &core.Block{} - block.DecodeBinary(br) + b := &block.Block{} + b.DecodeBinary(br) require.Nil(t, br.Err) - require.NoError(t, chain.AddBlock(block)) + require.NoError(t, chain.AddBlock(b)) } serverConfig := network.NewServerConfig(cfg) diff --git a/pkg/rpc/wrappers/block.go b/pkg/rpc/wrappers/block.go index 6c6a6ef56..77cf71bb0 100644 --- a/pkg/rpc/wrappers/block.go +++ b/pkg/rpc/wrappers/block.go @@ -2,14 +2,15 @@ package wrappers import ( "github.com/CityOfZion/neo-go/pkg/core" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/util" ) type ( // Block wrapper used for the representation of - // core.Block / core.BlockBase on the RPC Server. + // block.Block / block.BlockBase on the RPC Server. Block struct { - *core.Block + *block.Block Confirmations uint32 `json:"confirmations"` NextBlockHash util.Uint256 `json:"nextblockhash,omitempty"` Hash util.Uint256 `json:"hash"` @@ -17,7 +18,7 @@ type ( ) // NewBlock creates a new Block wrapper. -func NewBlock(block *core.Block, chain core.Blockchainer) Block { +func NewBlock(block *block.Block, chain core.Blockchainer) Block { blockWrapper := Block{ Block: block, Hash: block.Hash(), diff --git a/pkg/rpc/wrappers/tx_raw_output.go b/pkg/rpc/wrappers/tx_raw_output.go index 7a8a6fcf7..53f3025c9 100644 --- a/pkg/rpc/wrappers/tx_raw_output.go +++ b/pkg/rpc/wrappers/tx_raw_output.go @@ -2,6 +2,7 @@ package wrappers import ( "github.com/CityOfZion/neo-go/pkg/core" + "github.com/CityOfZion/neo-go/pkg/core/block" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" @@ -21,7 +22,7 @@ type TransactionOutputRaw struct { } // NewTransactionOutputRaw returns a new ransactionOutputRaw object. -func NewTransactionOutputRaw(tx *transaction.Transaction, header *core.Header, chain core.Blockchainer) TransactionOutputRaw { +func NewTransactionOutputRaw(tx *transaction.Transaction, header *block.Header, chain core.Blockchainer) TransactionOutputRaw { // confirmations formula confirmations := int(chain.BlockHeight() - header.BlockBase.Index + 1) // set index position