Merge pull request #601 from nspcc-dev/refactoring/core

core: refactor out Block, BlockBase and Header, closes #597.
This commit is contained in:
Roman Khimov 2020-01-20 16:19:20 +03:00 committed by GitHub
commit 32213b1454
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 327 additions and 232 deletions

View file

@ -8,6 +8,7 @@ import (
"github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/config"
"github.com/CityOfZion/neo-go/pkg/core" "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/core/storage"
"github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/encoding/address"
"github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/io"
@ -268,7 +269,7 @@ func restoreDB(ctx *cli.Context) error {
} }
for ; i < skip+count; i++ { for ; i < skip+count; i++ {
bytes, err := readBlock(reader) bytes, err := readBlock(reader)
block := &core.Block{} block := &block.Block{}
newReader := io.NewBinReaderFromBuf(bytes) newReader := io.NewBinReaderFromBuf(bytes)
block.DecodeBinary(newReader) block.DecodeBinary(newReader)
if err != nil { if err != nil {

View file

@ -1,7 +1,7 @@
package consensus package consensus
import ( 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/core/transaction"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
"github.com/nspcc-dev/dbft/block" "github.com/nspcc-dev/dbft/block"
@ -11,7 +11,7 @@ import (
// neoBlock is a wrapper of core.Block which implements // neoBlock is a wrapper of core.Block which implements
// methods necessary for dBFT library. // methods necessary for dBFT library.
type neoBlock struct { type neoBlock struct {
core.Block coreb.Block
signature []byte signature []byte
} }
@ -20,7 +20,7 @@ var _ block.Block = (*neoBlock)(nil)
// Sign implements block.Block interface. // Sign implements block.Block interface.
func (n *neoBlock) Sign(key crypto.PrivateKey) error { func (n *neoBlock) Sign(key crypto.PrivateKey) error {
data := n.BlockBase.GetHashableData() data := n.Base.GetHashableData()
sig, err := key.Sign(data[:]) sig, err := key.Sign(data[:])
if err != nil { if err != nil {
return err return err
@ -33,7 +33,7 @@ func (n *neoBlock) Sign(key crypto.PrivateKey) error {
// Verify implements block.Block interface. // Verify implements block.Block interface.
func (n *neoBlock) Verify(key crypto.PublicKey, sign []byte) error { func (n *neoBlock) Verify(key crypto.PublicKey, sign []byte) error {
data := n.BlockBase.GetHashableData() data := n.Base.GetHashableData()
return key.Verify(data, sign) return key.Verify(data, sign)
} }

View file

@ -8,6 +8,7 @@ import (
"github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/config"
"github.com/CityOfZion/neo-go/pkg/core" "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/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/crypto/keys"
@ -69,7 +70,7 @@ type Config struct {
Broadcast func(p *Payload) Broadcast func(p *Payload)
// RelayBlock is a callback that is called to notify server // RelayBlock is a callback that is called to notify server
// about the new block that needs to be broadcasted. // 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 is a core.Blockchainer instance.
Chain core.Blockchainer Chain core.Blockchainer
// RequestTx is a callback to which will be called // RequestTx is a callback to which will be called
@ -302,7 +303,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 dctx := s.dbft.Context
pubs := convertKeys(dctx.Validators) pubs := convertKeys(dctx.Validators)
sigs := make(map[*keys.PublicKey][]byte) sigs := make(map[*keys.PublicKey][]byte)

View file

@ -5,6 +5,7 @@ import (
"github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/config"
"github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/core/mempool"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/crypto/keys"
@ -21,7 +22,7 @@ func TestNewService(t *testing.T) {
Type: transaction.MinerType, Type: transaction.MinerType,
Data: &transaction.MinerTX{Nonce: 12345}, Data: &transaction.MinerTX{Nonce: 12345},
} }
item := core.NewPoolItem(tx, new(feer)) item := mempool.NewPoolItem(tx, new(feer))
srv.Chain.GetMemPool().TryAdd(tx.Hash(), item) srv.Chain.GetMemPool().TryAdd(tx.Hash(), item)
var txx []block.Transaction var txx []block.Transaction
@ -39,7 +40,7 @@ func TestService_GetVerified(t *testing.T) {
newMinerTx(4), newMinerTx(4),
} }
pool := srv.Chain.GetMemPool() pool := srv.Chain.GetMemPool()
item := core.NewPoolItem(txs[3], new(feer)) item := mempool.NewPoolItem(txs[3], new(feer))
require.True(t, pool.TryAdd(txs[3].Hash(), item)) require.True(t, pool.TryAdd(txs[3].Hash(), item))
@ -66,7 +67,7 @@ func TestService_GetVerified(t *testing.T) {
t.Run("more than half of the last proposal will be reused", func(t *testing.T) { t.Run("more than half of the last proposal will be reused", func(t *testing.T) {
for _, tx := range txs[:2] { for _, tx := range txs[:2] {
item := core.NewPoolItem(tx, new(feer)) item := mempool.NewPoolItem(tx, new(feer))
require.True(t, pool.TryAdd(tx.Hash(), item)) require.True(t, pool.TryAdd(tx.Hash(), item))
} }
@ -115,7 +116,7 @@ func TestService_getTx(t *testing.T) {
require.Equal(t, nil, srv.getTx(h)) require.Equal(t, nil, srv.getTx(h))
item := core.NewPoolItem(tx, new(feer)) item := mempool.NewPoolItem(tx, new(feer))
srv.Chain.GetMemPool().TryAdd(h, item) srv.Chain.GetMemPool().TryAdd(h, item)
got := srv.getTx(h) got := srv.getTx(h)

View file

@ -1,4 +1,4 @@
package core package block
import ( import (
"errors" "errors"
@ -14,7 +14,7 @@ import (
// Block represents one block in the chain. // Block represents one block in the chain.
type Block struct { type Block struct {
// The base of the block. // The base of the block.
BlockBase Base
// Transaction list. // Transaction list.
Transactions []*transaction.Transaction `json:"tx"` Transactions []*transaction.Transaction `json:"tx"`
@ -26,7 +26,7 @@ type Block struct {
// Header returns the Header of the Block. // Header returns the Header of the Block.
func (b *Block) Header() *Header { func (b *Block) Header() *Header {
return &Header{ return &Header{
BlockBase: b.BlockBase, Base: b.Base,
} }
} }
@ -39,8 +39,8 @@ func merkleTreeFromTransactions(txes []*transaction.Transaction) (*hash.MerkleTr
return hash.NewMerkleTree(hashes) return hash.NewMerkleTree(hashes)
} }
// rebuildMerkleRoot rebuilds the merkleroot of the block. // RebuildMerkleRoot rebuilds the merkleroot of the block.
func (b *Block) rebuildMerkleRoot() error { func (b *Block) RebuildMerkleRoot() error {
merkle, err := merkleTreeFromTransactions(b.Transactions) merkle, err := merkleTreeFromTransactions(b.Transactions)
if err != nil { if err != nil {
return err return err
@ -126,14 +126,14 @@ func (b *Block) Trim() ([]byte, error) {
// DecodeBinary decodes the block from the given BinReader, implementing // DecodeBinary decodes the block from the given BinReader, implementing
// Serializable interface. // Serializable interface.
func (b *Block) DecodeBinary(br *io.BinReader) { func (b *Block) DecodeBinary(br *io.BinReader) {
b.BlockBase.DecodeBinary(br) b.Base.DecodeBinary(br)
br.ReadArray(&b.Transactions) br.ReadArray(&b.Transactions)
} }
// EncodeBinary encodes the block to the given BinWriter, implementing // EncodeBinary encodes the block to the given BinWriter, implementing
// Serializable interface. // Serializable interface.
func (b *Block) EncodeBinary(bw *io.BinWriter) { func (b *Block) EncodeBinary(bw *io.BinWriter) {
b.BlockBase.EncodeBinary(bw) b.Base.EncodeBinary(bw)
bw.WriteArray(b.Transactions) bw.WriteArray(b.Transactions)
} }

View file

@ -1,4 +1,4 @@
package core package block
import ( import (
"fmt" "fmt"
@ -9,8 +9,8 @@ import (
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
// BlockBase holds the base info of a block // Base holds the base info of a block
type BlockBase struct { type Base struct {
// Version of the block. // Version of the block.
Version uint32 `json:"version"` Version uint32 `json:"version"`
@ -47,14 +47,14 @@ type BlockBase struct {
verificationHash util.Uint256 verificationHash util.Uint256
} }
// Verify verifies the integrity of the BlockBase. // Verify verifies the integrity of the Base.
func (b *BlockBase) Verify() bool { func (b *Base) Verify() bool {
// TODO: Need a persisted blockchain for this. // TODO: Need a persisted blockchain for this.
return true return true
} }
// Hash returns the hash of the block. // Hash returns the hash of the block.
func (b *BlockBase) Hash() util.Uint256 { func (b *Base) Hash() util.Uint256 {
if b.hash.Equals(util.Uint256{}) { if b.hash.Equals(util.Uint256{}) {
b.createHash() b.createHash()
} }
@ -62,7 +62,7 @@ func (b *BlockBase) Hash() util.Uint256 {
} }
// VerificationHash returns the hash of the block used to verify it. // VerificationHash returns the hash of the block used to verify it.
func (b *BlockBase) VerificationHash() util.Uint256 { func (b *Base) VerificationHash() util.Uint256 {
if b.verificationHash.Equals(util.Uint256{}) { if b.verificationHash.Equals(util.Uint256{}) {
b.createHash() b.createHash()
} }
@ -70,7 +70,7 @@ func (b *BlockBase) VerificationHash() util.Uint256 {
} }
// DecodeBinary implements Serializable interface. // DecodeBinary implements Serializable interface.
func (b *BlockBase) DecodeBinary(br *io.BinReader) { func (b *Base) DecodeBinary(br *io.BinReader) {
b.decodeHashableFields(br) b.decodeHashableFields(br)
padding := []byte{0} padding := []byte{0}
@ -84,14 +84,14 @@ func (b *BlockBase) DecodeBinary(br *io.BinReader) {
} }
// EncodeBinary implements Serializable interface // EncodeBinary implements Serializable interface
func (b *BlockBase) EncodeBinary(bw *io.BinWriter) { func (b *Base) EncodeBinary(bw *io.BinWriter) {
b.encodeHashableFields(bw) b.encodeHashableFields(bw)
bw.WriteBytes([]byte{1}) bw.WriteBytes([]byte{1})
b.Script.EncodeBinary(bw) b.Script.EncodeBinary(bw)
} }
// GetHashableData returns serialized hashable data of the block. // GetHashableData returns serialized hashable data of the block.
func (b *BlockBase) GetHashableData() []byte { func (b *Base) GetHashableData() []byte {
buf := io.NewBufBinWriter() buf := io.NewBufBinWriter()
// No error can occure while encoding hashable fields. // No error can occure while encoding hashable fields.
b.encodeHashableFields(buf.BinWriter) b.encodeHashableFields(buf.BinWriter)
@ -105,7 +105,7 @@ func (b *BlockBase) GetHashableData() []byte {
// version, PrevBlock, MerkleRoot, timestamp, and height, the nonce, NextMiner. // version, PrevBlock, MerkleRoot, timestamp, and height, the nonce, NextMiner.
// Since MerkleRoot already contains the hash value of all transactions, // Since MerkleRoot already contains the hash value of all transactions,
// the modification of transaction will influence the hash value of the block. // the modification of transaction will influence the hash value of the block.
func (b *BlockBase) createHash() { func (b *Base) createHash() {
bb := b.GetHashableData() bb := b.GetHashableData()
b.verificationHash = hash.Sha256(bb) b.verificationHash = hash.Sha256(bb)
b.hash = hash.Sha256(b.verificationHash.BytesBE()) b.hash = hash.Sha256(b.verificationHash.BytesBE())
@ -113,7 +113,7 @@ func (b *BlockBase) createHash() {
// encodeHashableFields will only encode the fields used for hashing. // encodeHashableFields will only encode the fields used for hashing.
// see Hash() for more information about the fields. // see Hash() for more information about the fields.
func (b *BlockBase) encodeHashableFields(bw *io.BinWriter) { func (b *Base) encodeHashableFields(bw *io.BinWriter) {
bw.WriteU32LE(b.Version) bw.WriteU32LE(b.Version)
bw.WriteBytes(b.PrevHash[:]) bw.WriteBytes(b.PrevHash[:])
bw.WriteBytes(b.MerkleRoot[:]) bw.WriteBytes(b.MerkleRoot[:])
@ -125,7 +125,7 @@ func (b *BlockBase) encodeHashableFields(bw *io.BinWriter) {
// decodeHashableFields decodes the fields used for hashing. // decodeHashableFields decodes the fields used for hashing.
// see Hash() for more information about the fields. // see Hash() for more information about the fields.
func (b *BlockBase) decodeHashableFields(br *io.BinReader) { func (b *Base) decodeHashableFields(br *io.BinReader) {
b.Version = br.ReadU32LE() b.Version = br.ReadU32LE()
br.ReadBytes(b.PrevHash[:]) br.ReadBytes(b.PrevHash[:])
br.ReadBytes(b.MerkleRoot[:]) br.ReadBytes(b.MerkleRoot[:])

View file

@ -1,4 +1,4 @@
package core package block
import ( import (
"encoding/hex" "encoding/hex"
@ -9,20 +9,17 @@ import (
"github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/encoding/address"
"github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/io"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
// Test blocks are blocks from mainnet with their corresponding index. // Test blocks are blocks from mainnet with their corresponding index.
func TestDecodeBlock1(t *testing.T) { func TestDecodeBlock1(t *testing.T) {
data, err := getBlockData(1) data, err := getBlockData(1)
if err != nil { require.NoError(t, err)
t.Fatal(err)
}
b, err := hex.DecodeString(data["raw"].(string)) b, err := hex.DecodeString(data["raw"].(string))
if err != nil { require.NoError(t, err)
t.Fatal(err)
}
block := &Block{} block := &Block{}
r := io.NewBinReaderFromBuf(b) r := io.NewBinReaderFromBuf(b)
@ -51,14 +48,10 @@ func TestTrimmedBlock(t *testing.T) {
block := getDecodedBlock(t, 1) block := getDecodedBlock(t, 1)
b, err := block.Trim() b, err := block.Trim()
if err != nil { require.NoError(t, err)
t.Fatal(err)
}
trimmedBlock, err := NewBlockFromTrimmedBytes(b) trimmedBlock, err := NewBlockFromTrimmedBytes(b)
if err != nil { require.NoError(t, err)
t.Fatal(err)
}
assert.True(t, trimmedBlock.Trimmed) assert.True(t, trimmedBlock.Trimmed)
assert.Equal(t, block.Version, trimmedBlock.Version) assert.Equal(t, block.Version, trimmedBlock.Version)
@ -79,7 +72,7 @@ func TestTrimmedBlock(t *testing.T) {
func newDumbBlock() *Block { func newDumbBlock() *Block {
return &Block{ return &Block{
BlockBase: BlockBase{ Base: Base{
Version: 0, Version: 0,
PrevHash: hash.Sha256([]byte("a")), PrevHash: hash.Sha256([]byte("a")),
MerkleRoot: hash.Sha256([]byte("b")), MerkleRoot: hash.Sha256([]byte("b")),
@ -108,21 +101,21 @@ func TestHashBlockEqualsHashHeader(t *testing.T) {
func TestBlockVerify(t *testing.T) { func TestBlockVerify(t *testing.T) {
block := newDumbBlock() block := newDumbBlock()
assert.NotNil(t, block.Verify()) assert.NotNil(t, block.Verify())
assert.Nil(t, block.rebuildMerkleRoot()) assert.Nil(t, block.RebuildMerkleRoot())
assert.Nil(t, block.Verify()) assert.Nil(t, block.Verify())
block.Transactions = []*transaction.Transaction{ block.Transactions = []*transaction.Transaction{
{Type: transaction.IssueType}, {Type: transaction.IssueType},
{Type: transaction.MinerType}, {Type: transaction.MinerType},
} }
assert.NoError(t, block.rebuildMerkleRoot()) assert.NoError(t, block.RebuildMerkleRoot())
assert.NotNil(t, block.Verify()) assert.NotNil(t, block.Verify())
block.Transactions = []*transaction.Transaction{ block.Transactions = []*transaction.Transaction{
{Type: transaction.MinerType}, {Type: transaction.MinerType},
{Type: transaction.MinerType}, {Type: transaction.MinerType},
} }
assert.NoError(t, block.rebuildMerkleRoot()) assert.NoError(t, block.RebuildMerkleRoot())
assert.NotNil(t, block.Verify()) assert.NotNil(t, block.Verify())
block.Transactions = []*transaction.Transaction{ block.Transactions = []*transaction.Transaction{
{Type: transaction.MinerType}, {Type: transaction.MinerType},
@ -291,9 +284,9 @@ func TestBlockSizeCalculation(t *testing.T) {
} }
func TestBlockCompare(t *testing.T) { func TestBlockCompare(t *testing.T) {
b1 := Block{BlockBase: BlockBase{Index: 1}} b1 := Block{Base: Base{Index: 1}}
b2 := Block{BlockBase: BlockBase{Index: 2}} b2 := Block{Base: Base{Index: 2}}
b3 := Block{BlockBase: BlockBase{Index: 3}} b3 := Block{Base: Base{Index: 3}}
assert.Equal(t, 1, b2.Compare(&b1)) assert.Equal(t, 1, b2.Compare(&b1))
assert.Equal(t, 0, b2.Compare(&b2)) assert.Equal(t, 0, b2.Compare(&b2))
assert.Equal(t, -1, b2.Compare(&b3)) assert.Equal(t, -1, b2.Compare(&b3))

View file

@ -1,4 +1,4 @@
package core package block
import ( import (
"fmt" "fmt"
@ -9,14 +9,14 @@ import (
// Header holds the head info of a block. // Header holds the head info of a block.
type Header struct { type Header struct {
// Base of the block. // Base of the block.
BlockBase Base
// Padding that is fixed to 0. // Padding that is fixed to 0.
_ uint8 _ uint8
} }
// DecodeBinary implements Serializable interface. // DecodeBinary implements Serializable interface.
func (h *Header) DecodeBinary(r *io.BinReader) { func (h *Header) DecodeBinary(r *io.BinReader) {
h.BlockBase.DecodeBinary(r) h.Base.DecodeBinary(r)
padding := []byte{0} padding := []byte{0}
r.ReadBytes(padding) r.ReadBytes(padding)
@ -28,6 +28,6 @@ func (h *Header) DecodeBinary(r *io.BinReader) {
// EncodeBinary implements Serializable interface. // EncodeBinary implements Serializable interface.
func (h *Header) EncodeBinary(w *io.BinWriter) { func (h *Header) EncodeBinary(w *io.BinWriter) {
h.BlockBase.EncodeBinary(w) h.Base.EncodeBinary(w)
w.WriteBytes([]byte{0}) w.WriteBytes([]byte{0})
} }

View file

@ -1,4 +1,4 @@
package core package block
import ( import (
"testing" "testing"
@ -12,7 +12,7 @@ import (
) )
func TestHeaderEncodeDecode(t *testing.T) { func TestHeaderEncodeDecode(t *testing.T) {
header := Header{BlockBase: BlockBase{ header := Header{Base: Base{
Version: 0, Version: 0,
PrevHash: hash.Sha256([]byte("prevhash")), PrevHash: hash.Sha256([]byte("prevhash")),
MerkleRoot: hash.Sha256([]byte("merkleroot")), MerkleRoot: hash.Sha256([]byte("merkleroot")),

View file

@ -0,0 +1,39 @@
package block
import (
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"testing"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/stretchr/testify/require"
)
func getDecodedBlock(t *testing.T, i int) *Block {
data, err := getBlockData(i)
require.NoError(t, err)
b, err := hex.DecodeString(data["raw"].(string))
require.NoError(t, err)
block := &Block{}
r := io.NewBinReaderFromBuf(b)
block.DecodeBinary(r)
require.NoError(t, 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
}

View file

@ -11,6 +11,8 @@ import (
"time" "time"
"github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/config"
"github.com/CityOfZion/neo-go/pkg/core/block"
"github.com/CityOfZion/neo-go/pkg/core/mempool"
"github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/state"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
@ -76,7 +78,7 @@ type Blockchain struct {
stopCh chan struct{} stopCh chan struct{}
runToExitCh chan struct{} runToExitCh chan struct{}
memPool MemPool memPool mempool.Pool
// cache for block verification keys. // cache for block verification keys.
keyCache map[util.Uint160]map[string]*keys.PublicKey keyCache map[util.Uint160]map[string]*keys.PublicKey
@ -100,7 +102,7 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L
headersOpDone: make(chan struct{}), headersOpDone: make(chan struct{}),
stopCh: make(chan struct{}), stopCh: make(chan struct{}),
runToExitCh: make(chan struct{}), runToExitCh: make(chan struct{}),
memPool: NewMemPool(50000), memPool: mempool.NewMemPool(50000),
keyCache: make(map[util.Uint160]map[string]*keys.PublicKey), keyCache: make(map[util.Uint160]map[string]*keys.PublicKey),
log: log, log: log,
} }
@ -179,7 +181,7 @@ func (bc *Blockchain) init() error {
targetHash = genesisBlock.Hash() targetHash = genesisBlock.Hash()
bc.headerList.Add(targetHash) bc.headerList.Add(targetHash)
} }
headers := make([]*Header, 0) headers := make([]*block.Header, 0)
for hash != targetHash { for hash != targetHash {
header, err := bc.GetHeader(hash) header, err := bc.GetHeader(hash)
@ -242,7 +244,7 @@ func (bc *Blockchain) Close() {
// AddBlock accepts successive block for the Blockchain, verifies it and // AddBlock accepts successive block for the Blockchain, verifies it and
// stores internally. Eventually it will be persisted to the backing storage. // 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 expectedHeight := bc.BlockHeight() + 1
if expectedHeight != block.Index { if expectedHeight != block.Index {
return fmt.Errorf("expected block %d, but passed block %d", expectedHeight, block.Index) return fmt.Errorf("expected block %d, but passed block %d", expectedHeight, block.Index)
@ -276,7 +278,7 @@ func (bc *Blockchain) AddBlock(block *Block) error {
// AddHeaders processes the given headers and add them to the // AddHeaders processes the given headers and add them to the
// HeaderHashList. // HeaderHashList.
func (bc *Blockchain) AddHeaders(headers ...*Header) (err error) { func (bc *Blockchain) AddHeaders(headers ...*block.Header) (err error) {
var ( var (
start = time.Now() start = time.Now()
batch = bc.dao.store.Batch() batch = bc.dao.store.Batch()
@ -321,7 +323,7 @@ func (bc *Blockchain) AddHeaders(headers ...*Header) (err error) {
// processHeader processes the given header. Note that this is only thread safe // processHeader processes the given header. Note that this is only thread safe
// if executed in headers operation. // 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()) headerList.Add(h.Hash())
buf := io.NewBufBinWriter() buf := io.NewBufBinWriter()
@ -352,7 +354,7 @@ func (bc *Blockchain) processHeader(h *Header, batch storage.Batch, headerList *
// project. This for the sake of development speed and understanding of what // 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 // 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. // 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) cache := newCachedDao(bc.dao.store)
if err := cache.StoreAsBlock(block, 0); err != nil { if err := cache.StoreAsBlock(block, 0); err != nil {
return err return err
@ -756,10 +758,10 @@ func (bc *Blockchain) GetStorageItems(hash util.Uint160) (map[string]*state.Stor
} }
// GetBlock returns a Block by the given hash. // 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() topBlock := bc.topBlock.Load()
if topBlock != nil { 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 return tb, nil
} }
} }
@ -782,10 +784,10 @@ func (bc *Blockchain) GetBlock(hash util.Uint256) (*Block, error) {
} }
// GetHeader returns data block header identified with the given hash value. // 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() topBlock := bc.topBlock.Load()
if topBlock != nil { 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 return tb.Header(), nil
} }
} }
@ -950,12 +952,12 @@ func (bc *Blockchain) IsLowPriority(t *transaction.Transaction) bool {
} }
// GetMemPool returns the memory pool of the blockchain. // GetMemPool returns the memory pool of the blockchain.
func (bc *Blockchain) GetMemPool() MemPool { func (bc *Blockchain) GetMemPool() mempool.Pool {
return bc.memPool return bc.memPool
} }
// VerifyBlock verifies block against its current state. // 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) prevHeader, err := bc.GetHeader(block.PrevHash)
if err != nil { if err != nil {
return errors.Wrap(err, "unable to get previous header") return errors.Wrap(err, "unable to get previous header")
@ -973,7 +975,7 @@ func (bc *Blockchain) VerifyBlock(block *Block) error {
// is used for easy interop access and can be omitted for transactions that are // is used for easy interop access and can be omitted for transactions that are
// not yet added into any block. // 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). // 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 { 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) return errors.Errorf("invalid transaction size = %d. It shoud be less then MaxTransactionSize = %d", io.GetVarSize(t), transaction.MaxTransactionSize)
} }
@ -1440,7 +1442,7 @@ func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transa
// not yet added into any block. // 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). // 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. // 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) hashes, err := bc.GetScriptHashesForVerifying(t)
if err != nil { if err != nil {
return err return err
@ -1465,7 +1467,7 @@ func (bc *Blockchain) verifyTxWitnesses(t *transaction.Transaction, block *Block
} }
// verifyBlockWitnesses is a block-specific implementation of VerifyWitnesses logic. // 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 var hash util.Uint160
if prevHeader == nil && block.PrevHash.Equals(util.Uint256{}) { if prevHeader == nil && block.PrevHash.Equals(util.Uint256{}) {
hash = block.Script.ScriptHash() hash = block.Script.ScriptHash()
@ -1487,6 +1489,6 @@ func (bc *Blockchain) secondsPerBlock() int {
return bc.config.SecondsPerBlock 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) return newInteropContext(trigger, bc, s, block, tx, bc.log)
} }

View file

@ -3,6 +3,7 @@ package core
import ( import (
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/core/block"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
@ -38,7 +39,7 @@ func TestAddHeaders(t *testing.T) {
func TestAddBlock(t *testing.T) { func TestAddBlock(t *testing.T) {
bc := newTestChain(t) bc := newTestChain(t)
blocks := []*Block{ blocks := []*block.Block{
newBlock(1, newMinerTX()), newBlock(1, newMinerTX()),
newBlock(2, newMinerTX()), newBlock(2, newMinerTX()),
newBlock(3, newMinerTX()), newBlock(3, newMinerTX()),

View file

@ -2,6 +2,8 @@ package core
import ( import (
"github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/config"
"github.com/CityOfZion/neo-go/pkg/core/block"
"github.com/CityOfZion/neo-go/pkg/core/mempool"
"github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/state"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
@ -14,15 +16,15 @@ import (
// of the blockchain. // of the blockchain.
type Blockchainer interface { type Blockchainer interface {
GetConfig() config.ProtocolConfiguration GetConfig() config.ProtocolConfiguration
AddHeaders(...*Header) error AddHeaders(...*block.Header) error
AddBlock(*Block) error AddBlock(*block.Block) error
BlockHeight() uint32 BlockHeight() uint32
Close() Close()
HeaderHeight() uint32 HeaderHeight() uint32
GetBlock(hash util.Uint256) (*Block, error) GetBlock(hash util.Uint256) (*block.Block, error)
GetContractState(hash util.Uint160) *state.Contract GetContractState(hash util.Uint160) *state.Contract
GetHeaderHash(int) util.Uint256 GetHeaderHash(int) util.Uint256
GetHeader(hash util.Uint256) (*Header, error) GetHeader(hash util.Uint256) (*block.Header, error)
CurrentHeaderHash() util.Uint256 CurrentHeaderHash() util.Uint256
CurrentBlockHash() util.Uint256 CurrentBlockHash() util.Uint256
HasBlock(util.Uint256) bool HasBlock(util.Uint256) bool
@ -37,7 +39,7 @@ type Blockchainer interface {
GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error) GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error)
GetUnspentCoinState(util.Uint256) *UnspentCoinState GetUnspentCoinState(util.Uint256) *UnspentCoinState
References(t *transaction.Transaction) map[transaction.Input]*transaction.Output References(t *transaction.Transaction) map[transaction.Input]*transaction.Output
Feer // fee interface mempool.Feer // fee interface
VerifyTx(*transaction.Transaction, *Block) error VerifyTx(*transaction.Transaction, *block.Block) error
GetMemPool() MemPool GetMemPool() mempool.Pool
} }

View file

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"sort" "sort"
"github.com/CityOfZion/neo-go/pkg/core/block"
"github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/state"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
@ -358,13 +359,13 @@ func makeStorageItemKey(scripthash util.Uint160, key []byte) []byte {
// -- other. // -- other.
// GetBlock returns Block by the given hash if it exists in the store. // 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()) key := storage.AppendPrefix(storage.DataBlock, hash.BytesLE())
b, err := dao.store.Get(key) b, err := dao.store.Get(key)
if err != nil { if err != nil {
return nil, err return nil, err
} }
block, err := NewBlockFromTrimmedBytes(b) block, err := block.NewBlockFromTrimmedBytes(b)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -486,7 +487,7 @@ func (dao *dao) HasTransaction(hash util.Uint256) bool {
} }
// StoreAsBlock stores the given block as DataBlock. // 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 ( var (
key = storage.AppendPrefix(storage.DataBlock, block.Hash().BytesLE()) key = storage.AppendPrefix(storage.DataBlock, block.Hash().BytesLE())
buf = io.NewBufBinWriter() buf = io.NewBufBinWriter()
@ -505,7 +506,7 @@ func (dao *dao) StoreAsBlock(block *Block, sysFee uint32) error {
} }
// StoreAsCurrentBlock stores the given block witch prefix SYSCurrentBlock. // 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() buf := io.NewBufBinWriter()
h := block.Hash() h := block.Hash()
h.EncodeBinary(buf.BinWriter) h.EncodeBinary(buf.BinWriter)

View file

@ -3,6 +3,7 @@ package core
import ( import (
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/core/block"
"github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/state"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
@ -260,16 +261,16 @@ func TestGetBlock_NotExists(t *testing.T) {
func TestPutGetBlock(t *testing.T) { func TestPutGetBlock(t *testing.T) {
dao := newDao(storage.NewMemoryStore()) dao := newDao(storage.NewMemoryStore())
block := &Block{ b := &block.Block{
BlockBase: BlockBase{ Base: block.Base{
Script: transaction.Witness{ Script: transaction.Witness{
VerificationScript: []byte{byte(opcode.PUSH1)}, VerificationScript: []byte{byte(opcode.PUSH1)},
InvocationScript: []byte{byte(opcode.NOP)}, InvocationScript: []byte{byte(opcode.NOP)},
}, },
}, },
} }
hash := block.Hash() hash := b.Hash()
err := dao.StoreAsBlock(block, 0) err := dao.StoreAsBlock(b, 0)
require.NoError(t, err) require.NoError(t, err)
gotBlock, err := dao.GetBlock(hash) gotBlock, err := dao.GetBlock(hash)
require.NoError(t, err) require.NoError(t, err)
@ -301,15 +302,15 @@ func TestGetCurrentHeaderHeight_NoHeader(t *testing.T) {
func TestGetCurrentHeaderHeight_Store(t *testing.T) { func TestGetCurrentHeaderHeight_Store(t *testing.T) {
dao := newDao(storage.NewMemoryStore()) dao := newDao(storage.NewMemoryStore())
block := &Block{ b := &block.Block{
BlockBase: BlockBase{ Base: block.Base{
Script: transaction.Witness{ Script: transaction.Witness{
VerificationScript: []byte{byte(opcode.PUSH1)}, VerificationScript: []byte{byte(opcode.PUSH1)},
InvocationScript: []byte{byte(opcode.NOP)}, InvocationScript: []byte{byte(opcode.NOP)},
}, },
}, },
} }
err := dao.StoreAsCurrentBlock(block) err := dao.StoreAsCurrentBlock(b)
require.NoError(t, err) require.NoError(t, err)
height, err := dao.GetCurrentBlockHeight() height, err := dao.GetCurrentBlockHeight()
require.NoError(t, err) require.NoError(t, err)

View file

@ -9,8 +9,10 @@ import (
"time" "time"
"github.com/CityOfZion/neo-go/config" "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/storage"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "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/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/smartcontract" "github.com/CityOfZion/neo-go/pkg/smartcontract"
@ -49,7 +51,7 @@ func newTestChain(t *testing.T) *Blockchain {
return chain return chain
} }
func newBlock(index uint32, txs ...*transaction.Transaction) *Block { func newBlock(index uint32, txs ...*transaction.Transaction) *block.Block {
validators, _ := getValidators(unitTestNetCfg.ProtocolConfiguration) validators, _ := getValidators(unitTestNetCfg.ProtocolConfiguration)
vlen := len(validators) vlen := len(validators)
valScript, _ := smartcontract.CreateMultiSigRedeemScript( valScript, _ := smartcontract.CreateMultiSigRedeemScript(
@ -59,8 +61,8 @@ func newBlock(index uint32, txs ...*transaction.Transaction) *Block {
witness := transaction.Witness{ witness := transaction.Witness{
VerificationScript: valScript, VerificationScript: valScript,
} }
b := &Block{ b := &block.Block{
BlockBase: BlockBase{ Base: block.Base{
Version: 0, Version: 0,
PrevHash: newBlockPrevHash, PrevHash: newBlockPrevHash,
Timestamp: uint32(time.Now().UTC().Unix()) + index, Timestamp: uint32(time.Now().UTC().Unix()) + index,
@ -71,8 +73,7 @@ func newBlock(index uint32, txs ...*transaction.Transaction) *Block {
}, },
Transactions: txs, Transactions: txs,
} }
_ = b.rebuildMerkleRoot() _ = b.RebuildMerkleRoot()
b.createHash()
newBlockPrevHash = b.Hash() newBlockPrevHash = b.Hash()
invScript := make([]byte, 0) invScript := make([]byte, 0)
@ -93,8 +94,8 @@ func newBlock(index uint32, txs ...*transaction.Transaction) *Block {
return b return b
} }
func makeBlocks(n int) []*Block { func makeBlocks(n int) []*block.Block {
blocks := make([]*Block, n) blocks := make([]*block.Block, n)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
blocks[i] = newBlock(uint32(i+1), newMinerTX()) 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) data, err := getBlockData(i)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -119,7 +120,7 @@ func getDecodedBlock(t *testing.T, i int) *Block {
t.Fatal(err) t.Fatal(err)
} }
block := &Block{} block := &block.Block{}
r := io.NewBinReaderFromBuf(b) r := io.NewBinReaderFromBuf(b)
block.DecodeBinary(r) block.DecodeBinary(r)
if r.Err != nil { if r.Err != nil {
@ -140,3 +141,25 @@ func getBlockData(i int) (map[string]interface{}, error) {
} }
return data, err return data, err
} }
func newDumbBlock() *block.Block {
return &block.Block{
Base: block.Base{
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},
},
}
}

View file

@ -4,6 +4,7 @@ import (
"math/big" "math/big"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/core/block"
"github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/state"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "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. // 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() v := vm.New()
block := newDumbBlock() block := newDumbBlock()
chain := newTestChain(t) chain := newTestChain(t)

View file

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"math" "math"
"github.com/CityOfZion/neo-go/pkg/core/block"
"github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/state"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "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 // popHeaderFromVM returns pointer to Header or error. It's main feature is
// proper treatment of Block structure, because C# code implicitly assumes // proper treatment of Block structure, because C# code implicitly assumes
// that header APIs can also operate on blocks. // 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() iface := v.Estack().Pop().Value()
header, ok := iface.(*Header) header, ok := iface.(*block.Header)
if !ok { if !ok {
block, ok := iface.(*Block) block, ok := iface.(*block.Block)
if !ok { if !ok {
return nil, errors.New("value is not a header or block") 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. // blockGetTransactionCount returns transactions count in the given block.
func (ic *interopContext) blockGetTransactionCount(v *vm.VM) error { func (ic *interopContext) blockGetTransactionCount(v *vm.VM) error {
blockInterface := v.Estack().Pop().Value() blockInterface := v.Estack().Pop().Value()
block, ok := blockInterface.(*Block) block, ok := blockInterface.(*block.Block)
if !ok { if !ok {
return errors.New("value is not a block") 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. // blockGetTransactions returns transactions from the given block.
func (ic *interopContext) blockGetTransactions(v *vm.VM) error { func (ic *interopContext) blockGetTransactions(v *vm.VM) error {
blockInterface := v.Estack().Pop().Value() blockInterface := v.Estack().Pop().Value()
block, ok := blockInterface.(*Block) block, ok := blockInterface.(*block.Block)
if !ok { if !ok {
return errors.New("value is not a block") return errors.New("value is not a block")
} }
@ -218,7 +219,7 @@ func (ic *interopContext) blockGetTransactions(v *vm.VM) error {
// block. // block.
func (ic *interopContext) blockGetTransaction(v *vm.VM) error { func (ic *interopContext) blockGetTransaction(v *vm.VM) error {
blockInterface := v.Estack().Pop().Value() blockInterface := v.Estack().Pop().Value()
block, ok := blockInterface.(*Block) block, ok := blockInterface.(*block.Block)
if !ok { if !ok {
return errors.New("value is not a block") 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 // runtimeGetTime returns timestamp of the block being verified, or the latest
// one in the blockchain if no block is given to interopContext. // one in the blockchain if no block is given to interopContext.
func (ic *interopContext) runtimeGetTime(v *vm.VM) error { func (ic *interopContext) runtimeGetTime(v *vm.VM) error {
var header *Header var header *block.Header
if ic.block == nil { if ic.block == nil {
var err error var err error
header, err = ic.bc.GetHeader(ic.bc.CurrentBlockHash()) header, err = ic.bc.GetHeader(ic.bc.CurrentBlockHash())

View file

@ -10,6 +10,7 @@ package core
import ( import (
"sort" "sort"
"github.com/CityOfZion/neo-go/pkg/core/block"
"github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/state"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
@ -20,14 +21,14 @@ import (
type interopContext struct { type interopContext struct {
bc Blockchainer bc Blockchainer
trigger byte trigger byte
block *Block block *block.Block
tx *transaction.Transaction tx *transaction.Transaction
dao *cachedDao dao *cachedDao
notifications []state.NotificationEvent notifications []state.NotificationEvent
log *zap.Logger 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) dao := newCachedDao(s)
nes := make([]state.NotificationEvent, 0) nes := make([]state.NotificationEvent, 0)
return &interopContext{bc, trigger, block, tx, dao, nes, log} return &interopContext{bc, trigger, block, tx, dao, nes, log}

View file

@ -1,4 +1,4 @@
package core package mempool
import ( import (
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"

View file

@ -1,4 +1,4 @@
package core package mempool
import ( import (
"sort" "sort"
@ -9,38 +9,38 @@ import (
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
// PoolItem represents a transaction in the the Memory pool. // Item represents a transaction in the the Memory pool.
type PoolItem struct { type Item struct {
txn *transaction.Transaction txn *transaction.Transaction
timeStamp time.Time timeStamp time.Time
fee Feer fee Feer
} }
// PoolItems slice of PoolItem. // Items is a slice of Item.
type PoolItems []*PoolItem type Items []*Item
// MemPool stores the unconfirms transactions. // Pool stores the unconfirms transactions.
type MemPool struct { type Pool struct {
lock *sync.RWMutex lock *sync.RWMutex
unsortedTxn map[util.Uint256]*PoolItem unsortedTxn map[util.Uint256]*Item
unverifiedTxn map[util.Uint256]*PoolItem unverifiedTxn map[util.Uint256]*Item
sortedHighPrioTxn PoolItems sortedHighPrioTxn Items
sortedLowPrioTxn PoolItems sortedLowPrioTxn Items
unverifiedSortedHighPrioTxn PoolItems unverifiedSortedHighPrioTxn Items
unverifiedSortedLowPrioTxn PoolItems unverifiedSortedLowPrioTxn Items
capacity int capacity int
} }
func (p PoolItems) Len() int { return len(p) } func (p Items) Len() int { return len(p) }
func (p PoolItems) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p Items) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p PoolItems) Less(i, j int) bool { return p[i].CompareTo(p[j]) < 0 } func (p Items) Less(i, j int) bool { return p[i].CompareTo(p[j]) < 0 }
// CompareTo returns the difference between two PoolItems. // CompareTo returns the difference between two Items.
// difference < 0 implies p < otherP. // difference < 0 implies p < otherP.
// difference = 0 implies p = otherP. // difference = 0 implies p = otherP.
// difference > 0 implies p > otherP. // difference > 0 implies p > otherP.
func (p PoolItem) CompareTo(otherP *PoolItem) int { func (p Item) CompareTo(otherP *Item) int {
if otherP == nil { if otherP == nil {
return 1 return 1
} }
@ -77,15 +77,15 @@ func (p PoolItem) CompareTo(otherP *PoolItem) int {
} }
// Count returns the total number of uncofirm transactions. // Count returns the total number of uncofirm transactions.
func (mp MemPool) Count() int { func (mp Pool) Count() int {
mp.lock.RLock() mp.lock.RLock()
defer mp.lock.RUnlock() defer mp.lock.RUnlock()
return len(mp.unsortedTxn) + len(mp.unverifiedTxn) return len(mp.unsortedTxn) + len(mp.unverifiedTxn)
} }
// ContainsKey checks if a transactions hash is in the MemPool. // ContainsKey checks if a transactions hash is in the Pool.
func (mp MemPool) ContainsKey(hash util.Uint256) bool { func (mp Pool) ContainsKey(hash util.Uint256) bool {
mp.lock.RLock() mp.lock.RLock()
defer mp.lock.RUnlock() defer mp.lock.RUnlock()
@ -100,9 +100,9 @@ func (mp MemPool) ContainsKey(hash util.Uint256) bool {
return false return false
} }
// TryAdd try to add the PoolItem to the MemPool. // TryAdd try to add the Item to the Pool.
func (mp MemPool) TryAdd(hash util.Uint256, pItem *PoolItem) bool { func (mp Pool) TryAdd(hash util.Uint256, pItem *Item) bool {
var pool PoolItems var pool Items
mp.lock.Lock() mp.lock.Lock()
if _, ok := mp.unsortedTxn[hash]; ok { if _, ok := mp.unsortedTxn[hash]; ok {
@ -135,13 +135,13 @@ func (mp MemPool) TryAdd(hash util.Uint256, pItem *PoolItem) bool {
// Remove removes an item from the mempool, if it exists there (and does // Remove removes an item from the mempool, if it exists there (and does
// nothing if it doesn't). // nothing if it doesn't).
func (mp *MemPool) Remove(hash util.Uint256) { func (mp *Pool) Remove(hash util.Uint256) {
var mapAndPools = []struct { var mapAndPools = []struct {
unsortedMap map[util.Uint256]*PoolItem unsortedMap map[util.Uint256]*Item
sortedPools []*PoolItems sortedPools []*Items
}{ }{
{unsortedMap: mp.unsortedTxn, sortedPools: []*PoolItems{&mp.sortedHighPrioTxn, &mp.sortedLowPrioTxn}}, {unsortedMap: mp.unsortedTxn, sortedPools: []*Items{&mp.sortedHighPrioTxn, &mp.sortedLowPrioTxn}},
{unsortedMap: mp.unverifiedTxn, sortedPools: []*PoolItems{&mp.unverifiedSortedHighPrioTxn, &mp.unverifiedSortedLowPrioTxn}}, {unsortedMap: mp.unverifiedTxn, sortedPools: []*Items{&mp.unverifiedSortedHighPrioTxn, &mp.unverifiedSortedLowPrioTxn}},
} }
mp.lock.Lock() mp.lock.Lock()
for _, mapAndPool := range mapAndPools { for _, mapAndPool := range mapAndPools {
@ -149,7 +149,7 @@ func (mp *MemPool) Remove(hash util.Uint256) {
delete(mapAndPool.unsortedMap, hash) delete(mapAndPool.unsortedMap, hash)
for _, pool := range mapAndPool.sortedPools { for _, pool := range mapAndPool.sortedPools {
var num int var num int
var item *PoolItem var item *Item
for num, item = range *pool { for num, item = range *pool {
if hash.Equals(item.txn.Hash()) { if hash.Equals(item.txn.Hash()) {
break break
@ -168,8 +168,8 @@ func (mp *MemPool) Remove(hash util.Uint256) {
} }
// RemoveOverCapacity removes transactions with lowest fees until the total number of transactions // RemoveOverCapacity removes transactions with lowest fees until the total number of transactions
// in the MemPool is within the capacity of the MemPool. // in the Pool is within the capacity of the Pool.
func (mp *MemPool) RemoveOverCapacity() { func (mp *Pool) RemoveOverCapacity() {
for mp.Count()-mp.capacity > 0 { for mp.Count()-mp.capacity > 0 {
mp.lock.Lock() mp.lock.Lock()
if minItem, argPosition := getLowestFeeTransaction(mp.sortedLowPrioTxn, mp.unverifiedSortedLowPrioTxn); minItem != nil { if minItem, argPosition := getLowestFeeTransaction(mp.sortedLowPrioTxn, mp.unverifiedSortedLowPrioTxn); minItem != nil {
@ -205,27 +205,27 @@ func (mp *MemPool) RemoveOverCapacity() {
} }
// NewPoolItem returns a new PoolItem. // NewPoolItem returns a new Item.
func NewPoolItem(t *transaction.Transaction, fee Feer) *PoolItem { func NewPoolItem(t *transaction.Transaction, fee Feer) *Item {
return &PoolItem{ return &Item{
txn: t, txn: t,
timeStamp: time.Now().UTC(), timeStamp: time.Now().UTC(),
fee: fee, fee: fee,
} }
} }
// NewMemPool returns a new MemPool struct. // NewMemPool returns a new Pool struct.
func NewMemPool(capacity int) MemPool { func NewMemPool(capacity int) Pool {
return MemPool{ return Pool{
lock: new(sync.RWMutex), lock: new(sync.RWMutex),
unsortedTxn: make(map[util.Uint256]*PoolItem), unsortedTxn: make(map[util.Uint256]*Item),
unverifiedTxn: make(map[util.Uint256]*PoolItem), unverifiedTxn: make(map[util.Uint256]*Item),
capacity: capacity, capacity: capacity,
} }
} }
// TryGetValue returns a transaction if it exists in the memory pool. // TryGetValue returns a transaction if it exists in the memory pool.
func (mp MemPool) TryGetValue(hash util.Uint256) (*transaction.Transaction, bool) { func (mp Pool) TryGetValue(hash util.Uint256) (*transaction.Transaction, bool) {
mp.lock.RLock() mp.lock.RLock()
defer mp.lock.RUnlock() defer mp.lock.RUnlock()
if pItem, ok := mp.unsortedTxn[hash]; ok { if pItem, ok := mp.unsortedTxn[hash]; ok {
@ -239,13 +239,13 @@ func (mp MemPool) TryGetValue(hash util.Uint256) (*transaction.Transaction, bool
return nil, false return nil, false
} }
// getLowestFeeTransaction returns the PoolItem with the lowest fee amongst the "verifiedTxnSorted" // getLowestFeeTransaction returns the Item with the lowest fee amongst the "verifiedTxnSorted"
// and "unverifiedTxnSorted" PoolItems along with a integer. The integer can assume two values, 1 and 2 which indicate // and "unverifiedTxnSorted" Items along with a integer. The integer can assume two values, 1 and 2 which indicate
// that the PoolItem with the lowest fee was found in "verifiedTxnSorted" respectively in "unverifiedTxnSorted". // that the Item with the lowest fee was found in "verifiedTxnSorted" respectively in "unverifiedTxnSorted".
// "verifiedTxnSorted" and "unverifiedTxnSorted" are sorted slice order by transaction fee ascending. This means that // "verifiedTxnSorted" and "unverifiedTxnSorted" are sorted slice order by transaction fee ascending. This means that
// the transaction with lowest fee start at index 0. // the transaction with lowest fee start at index 0.
// Reference: GetLowestFeeTransaction method in C# (https://github.com/neo-project/neo/blob/master/neo/Ledger/MemoryPool.cs) // Reference: GetLowestFeeTransaction method in C# (https://github.com/neo-project/neo/blob/master/neo/Ledger/MemoryPool.cs)
func getLowestFeeTransaction(verifiedTxnSorted PoolItems, unverifiedTxnSorted PoolItems) (*PoolItem, int) { func getLowestFeeTransaction(verifiedTxnSorted Items, unverifiedTxnSorted Items) (*Item, int) {
minItem := min(unverifiedTxnSorted) minItem := min(unverifiedTxnSorted)
verifiedMin := min(verifiedTxnSorted) verifiedMin := min(verifiedTxnSorted)
if verifiedMin == nil || (minItem != nil && verifiedMin.CompareTo(minItem) >= 0) { if verifiedMin == nil || (minItem != nil && verifiedMin.CompareTo(minItem) >= 0) {
@ -259,7 +259,7 @@ func getLowestFeeTransaction(verifiedTxnSorted PoolItems, unverifiedTxnSorted Po
// min returns the minimum item in a ascending sorted slice of pool items. // min returns the minimum item in a ascending sorted slice of pool items.
// The function can't be applied to unsorted slice! // The function can't be applied to unsorted slice!
func min(sortedPool PoolItems) *PoolItem { func min(sortedPool Items) *Item {
if len(sortedPool) == 0 { if len(sortedPool) == 0 {
return nil return nil
} }
@ -268,7 +268,7 @@ func min(sortedPool PoolItems) *PoolItem {
// GetVerifiedTransactions returns a slice of Input from all the transactions in the memory pool // GetVerifiedTransactions returns a slice of Input from all the transactions in the memory pool
// whose hash is not included in excludedHashes. // whose hash is not included in excludedHashes.
func (mp *MemPool) GetVerifiedTransactions() []*transaction.Transaction { func (mp *Pool) GetVerifiedTransactions() []*transaction.Transaction {
mp.lock.RLock() mp.lock.RLock()
defer mp.lock.RUnlock() defer mp.lock.RUnlock()
@ -286,7 +286,7 @@ func (mp *MemPool) GetVerifiedTransactions() []*transaction.Transaction {
// Verify verifies if the inputs of a transaction tx are already used in any other transaction in the memory pool. // Verify verifies if the inputs of a transaction tx are already used in any other transaction in the memory pool.
// If yes, the transaction tx is not a valid transaction and the function return false. // If yes, the transaction tx is not a valid transaction and the function return false.
// If no, the transaction tx is a valid transaction and the function return true. // If no, the transaction tx is a valid transaction and the function return true.
func (mp MemPool) Verify(tx *transaction.Transaction) bool { func (mp Pool) Verify(tx *transaction.Transaction) bool {
mp.lock.RLock() mp.lock.RLock()
defer mp.lock.RUnlock() defer mp.lock.RUnlock()
for _, item := range mp.unsortedTxn { for _, item := range mp.unsortedTxn {

View file

@ -1,4 +1,4 @@
package core package mempool
import ( import (
"testing" "testing"
@ -88,3 +88,10 @@ func TestMemPoolVerify(t *testing.T) {
tx3.Inputs = append(tx3.Inputs, transaction.Input{PrevHash: inhash2, PrevIndex: 0}) tx3.Inputs = append(tx3.Inputs, transaction.Input{PrevHash: inhash2, PrevIndex: 0})
require.Equal(t, false, mp.Verify(tx3)) require.Equal(t, false, mp.Verify(tx3))
} }
func newMinerTX() *transaction.Transaction {
return &transaction.Transaction{
Type: transaction.MinerType,
Data: &transaction.MinerTX{},
}
}

View file

@ -0,0 +1,34 @@
package mempool
import "github.com/prometheus/client_golang/prometheus"
var (
//mempoolUnsortedTx prometheus metric.
mempoolUnsortedTx = prometheus.NewGauge(
prometheus.GaugeOpts{
Help: "Mempool Unsorted TXs",
Name: "mempool_unsorted_tx",
Namespace: "neogo",
},
)
//mempoolUnverifiedTx prometheus metric.
mempoolUnverifiedTx = prometheus.NewGauge(
prometheus.GaugeOpts{
Help: "Mempool Unverified TXs",
Name: "mempool_unverified_tx",
Namespace: "neogo",
},
)
)
func init() {
prometheus.MustRegister(
mempoolUnsortedTx,
mempoolUnverifiedTx,
)
}
func updateMempoolMetrics(unsortedTxnLen int, unverifiedTxnLen int) {
mempoolUnsortedTx.Set(float64(unsortedTxnLen))
mempoolUnverifiedTx.Set(float64(unverifiedTxnLen))
}

View file

@ -30,22 +30,6 @@ var (
Namespace: "neogo", Namespace: "neogo",
}, },
) )
//mempoolUnsortedTx prometheus metric.
mempoolUnsortedTx = prometheus.NewGauge(
prometheus.GaugeOpts{
Help: "Mempool Unsorted TXs",
Name: "mempool_unsorted_tx",
Namespace: "neogo",
},
)
//mempoolUnverifiedTx prometheus metric.
mempoolUnverifiedTx = prometheus.NewGauge(
prometheus.GaugeOpts{
Help: "Mempool Unverified TXs",
Name: "mempool_unverified_tx",
Namespace: "neogo",
},
)
) )
func init() { func init() {
@ -53,8 +37,6 @@ func init() {
blockHeight, blockHeight,
persistedHeight, persistedHeight,
headerHeight, headerHeight,
mempoolUnsortedTx,
mempoolUnverifiedTx,
) )
} }
@ -69,8 +51,3 @@ func updateHeaderHeightMetric(hHeight int) {
func updateBlockHeightMetric(bHeight uint32) { func updateBlockHeightMetric(bHeight uint32) {
blockHeight.Set(float64(bHeight)) blockHeight.Set(float64(bHeight))
} }
func updateMempoolMetrics(unsortedTxnLen int, unverifiedTxnLen int) {
mempoolUnsortedTx.Set(float64(unsortedTxnLen))
mempoolUnverifiedTx.Set(float64(unverifiedTxnLen))
}

View file

@ -4,6 +4,7 @@ import (
"time" "time"
"github.com/CityOfZion/neo-go/config" "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/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/crypto/keys"
@ -13,7 +14,7 @@ import (
) )
// createGenesisBlock creates a genesis block based on the given configuration. // 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) validators, err := getValidators(cfg)
if err != nil { if err != nil {
return nil, err return nil, err
@ -24,7 +25,7 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*Block, error) {
return nil, err return nil, err
} }
base := BlockBase{ base := block.Base{
Version: 0, Version: 0,
PrevHash: util.Uint256{}, PrevHash: util.Uint256{},
Timestamp: uint32(time.Date(2016, 7, 15, 15, 8, 21, 0, time.UTC).Unix()), Timestamp: uint32(time.Date(2016, 7, 15, 15, 8, 21, 0, time.UTC).Unix()),
@ -48,8 +49,8 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*Block, error) {
} }
scriptOut := hash.Hash160(rawScript) scriptOut := hash.Hash160(rawScript)
block := &Block{ b := &block.Block{
BlockBase: base, Base: base,
Transactions: []*transaction.Transaction{ Transactions: []*transaction.Transaction{
{ {
Type: transaction.MinerType, Type: transaction.MinerType,
@ -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 nil, err
} }
return block, nil return b, nil
} }
func governingTokenTX() *transaction.Transaction { func governingTokenTX() *transaction.Transaction {
@ -167,7 +168,7 @@ func calculateUtilityAmount() util.Fixed8 {
} }
// headerSliceReverse reverses the given slice of *Header. // 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 { for i, j := 0, len(dest)-1; i < j; i, j = i+1, j-1 {
dest[i], dest[j] = dest[j], dest[i] dest[i], dest[j] = dest[j], dest[i]
} }

View file

@ -2,6 +2,7 @@ package network
import ( import (
"github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/core/block"
"github.com/Workiva/go-datastructures/queue" "github.com/Workiva/go-datastructures/queue"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -37,7 +38,7 @@ func (bq *blockQueue) run() {
if item == nil { if item == nil {
break break
} }
minblock := item.(*core.Block) minblock := item.(*block.Block)
if minblock.Index <= bq.chain.BlockHeight()+1 { if minblock.Index <= bq.chain.BlockHeight()+1 {
_, _ = bq.queue.Get(1) _, _ = bq.queue.Get(1)
updateBlockQueueLenMetric(bq.length()) 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 { if bq.chain.BlockHeight() >= block.Index {
// can easily happen when fetching the same blocks from // can easily happen when fetching the same blocks from
// different peers, thus not considered as error // different peers, thus not considered as error

View file

@ -4,7 +4,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core/block"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.uber.org/zap/zaptest" "go.uber.org/zap/zaptest"
) )
@ -13,9 +13,9 @@ func TestBlockQueue(t *testing.T) {
chain := &testChain{} chain := &testChain{}
// notice, it's not yet running // notice, it's not yet running
bq := newBlockQueue(0, chain, zaptest.NewLogger(t)) bq := newBlockQueue(0, chain, zaptest.NewLogger(t))
blocks := make([]*core.Block, 11) blocks := make([]*block.Block, 11)
for i := 1; i < 11; i++ { for i := 1; i < 11; i++ {
blocks[i] = &core.Block{BlockBase: core.BlockBase{Index: uint32(i)}} blocks[i] = &block.Block{Base: block.Base{Index: uint32(i)}}
} }
// not the ones expected currently // not the ones expected currently
for i := 3; i < 5; i++ { for i := 3; i < 5; i++ {

View file

@ -9,6 +9,8 @@ import (
"github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/config"
"github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/core/block"
"github.com/CityOfZion/neo-go/pkg/core/mempool"
"github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/state"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
@ -43,10 +45,10 @@ func (chain testChain) NetworkFee(t *transaction.Transaction) util.Fixed8 {
panic("TODO") panic("TODO")
} }
func (chain testChain) AddHeaders(...*core.Header) error { func (chain testChain) AddHeaders(...*block.Header) error {
panic("TODO") panic("TODO")
} }
func (chain *testChain) AddBlock(block *core.Block) error { func (chain *testChain) AddBlock(block *block.Block) error {
if block.Index == chain.blockheight+1 { if block.Index == chain.blockheight+1 {
atomic.StoreUint32(&chain.blockheight, block.Index) atomic.StoreUint32(&chain.blockheight, block.Index)
} }
@ -61,7 +63,7 @@ func (chain *testChain) Close() {
func (chain testChain) HeaderHeight() uint32 { func (chain testChain) HeaderHeight() uint32 {
return 0 return 0
} }
func (chain testChain) GetBlock(hash util.Uint256) (*core.Block, error) { func (chain testChain) GetBlock(hash util.Uint256) (*block.Block, error) {
panic("TODO") panic("TODO")
} }
func (chain testChain) GetContractState(hash util.Uint160) *state.Contract { func (chain testChain) GetContractState(hash util.Uint160) *state.Contract {
@ -70,7 +72,7 @@ func (chain testChain) GetContractState(hash util.Uint160) *state.Contract {
func (chain testChain) GetHeaderHash(int) util.Uint256 { func (chain testChain) GetHeaderHash(int) util.Uint256 {
return 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") panic("TODO")
} }
@ -115,7 +117,7 @@ func (chain testChain) GetUnspentCoinState(util.Uint256) *core.UnspentCoinState
panic("TODO") panic("TODO")
} }
func (chain testChain) GetMemPool() core.MemPool { func (chain testChain) GetMemPool() mempool.Pool {
panic("TODO") panic("TODO")
} }
@ -123,7 +125,7 @@ func (chain testChain) IsLowPriority(*transaction.Transaction) bool {
panic("TODO") panic("TODO")
} }
func (chain testChain) VerifyTx(*transaction.Transaction, *core.Block) error { func (chain testChain) VerifyTx(*transaction.Transaction, *block.Block) error {
panic("TODO") panic("TODO")
} }

View file

@ -7,7 +7,7 @@ import (
"github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/config"
"github.com/CityOfZion/neo-go/pkg/consensus" "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/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/io"
@ -184,7 +184,7 @@ func (m *Message) decodePayload(br *io.BinReader) error {
case CMDAddr: case CMDAddr:
p = &payload.AddressList{} p = &payload.AddressList{}
case CMDBlock: case CMDBlock:
p = &core.Block{} p = &block.Block{}
case CMDConsensus: case CMDConsensus:
p = &consensus.Payload{} p = &consensus.Payload{}
case CMDGetBlocks: case CMDGetBlocks:

View file

@ -1,14 +1,14 @@
package payload package payload
import ( 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/io"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// Headers payload. // Headers payload.
type Headers struct { type Headers struct {
Hdrs []*core.Header Hdrs []*block.Header
} }
// Users can at most request 2k header. // Users can at most request 2k header.
@ -30,10 +30,10 @@ func (p *Headers) DecodeBinary(br *io.BinReader) {
lenHeaders = MaxHeadersAllowed lenHeaders = MaxHeadersAllowed
} }
p.Hdrs = make([]*core.Header, lenHeaders) p.Hdrs = make([]*block.Header, lenHeaders)
for i := 0; i < int(lenHeaders); i++ { for i := 0; i < int(lenHeaders); i++ {
header := &core.Header{} header := &block.Header{}
header.DecodeBinary(br) header.DecodeBinary(br)
p.Hdrs[i] = header p.Hdrs[i] = header
} }

View file

@ -4,7 +4,7 @@ import (
"encoding/hex" "encoding/hex"
"testing" "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/core/transaction"
"github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/io"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -26,11 +26,11 @@ func TestHeadersEncodeDecode(t *testing.T) {
} }
func newTestHeaders(n int) *Headers { func newTestHeaders(n int) *Headers {
headers := &Headers{Hdrs: make([]*core.Header, n)} headers := &Headers{Hdrs: make([]*block.Header, n)}
for i := range headers.Hdrs { for i := range headers.Hdrs {
headers.Hdrs[i] = &core.Header{ headers.Hdrs[i] = &block.Header{
BlockBase: core.BlockBase{ Base: block.Base{
Index: uint32(i + 1), Index: uint32(i + 1),
Script: transaction.Witness{ Script: transaction.Witness{
InvocationScript: []byte{0x0}, InvocationScript: []byte{0x0},

View file

@ -1,14 +1,14 @@
package payload package payload
import ( 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/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
// MerkleBlock represents a merkle block packet payload. // MerkleBlock represents a merkle block packet payload.
type MerkleBlock struct { type MerkleBlock struct {
*core.BlockBase *block.Base
TxCount int TxCount int
Hashes []util.Uint256 Hashes []util.Uint256
Flags []byte Flags []byte
@ -16,8 +16,8 @@ type MerkleBlock struct {
// DecodeBinary implements Serializable interface. // DecodeBinary implements Serializable interface.
func (m *MerkleBlock) DecodeBinary(br *io.BinReader) { func (m *MerkleBlock) DecodeBinary(br *io.BinReader) {
m.BlockBase = &core.BlockBase{} m.Base = &block.Base{}
m.BlockBase.DecodeBinary(br) m.Base.DecodeBinary(br)
m.TxCount = int(br.ReadVarUint()) m.TxCount = int(br.ReadVarUint())
br.ReadArray(&m.Hashes) br.ReadArray(&m.Hashes)
@ -26,8 +26,8 @@ func (m *MerkleBlock) DecodeBinary(br *io.BinReader) {
// EncodeBinary implements Serializable interface. // EncodeBinary implements Serializable interface.
func (m *MerkleBlock) EncodeBinary(bw *io.BinWriter) { func (m *MerkleBlock) EncodeBinary(bw *io.BinWriter) {
m.BlockBase = &core.BlockBase{} m.Base = &block.Base{}
m.BlockBase.EncodeBinary(bw) m.Base.EncodeBinary(bw)
bw.WriteVarUint(uint64(m.TxCount)) bw.WriteVarUint(uint64(m.TxCount))
bw.WriteArray(m.Hashes) bw.WriteArray(m.Hashes)

View file

@ -12,6 +12,8 @@ import (
"github.com/CityOfZion/neo-go/pkg/consensus" "github.com/CityOfZion/neo-go/pkg/consensus"
"github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/core/block"
"github.com/CityOfZion/neo-go/pkg/core/mempool"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/network/payload" "github.com/CityOfZion/neo-go/pkg/network/payload"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
@ -421,7 +423,7 @@ func (s *Server) handleHeadersCmd(p Peer, headers *payload.Headers) {
} }
// handleBlockCmd processes the received block received from its peer. // 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) return s.bQueue.putBlock(block)
} }
@ -545,7 +547,7 @@ func (s *Server) handleGetHeadersCmd(p Peer, gh *payload.GetBlocks) error {
return err return err
} }
resp := payload.Headers{} 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++ { for i := start.Index + 1; i < start.Index+1+payload.MaxHeadersAllowed; i++ {
hash := s.chain.GetHeaderHash(int(i)) hash := s.chain.GetHeaderHash(int(i))
if hash.Equals(util.Uint256{}) || hash.Equals(gh.HashStop) { if hash.Equals(util.Uint256{}) || hash.Equals(gh.HashStop) {
@ -672,7 +674,7 @@ func (s *Server) handleMessage(peer Peer, msg *Message) error {
inventory := msg.Payload.(*payload.Inventory) inventory := msg.Payload.(*payload.Inventory)
return s.handleInvCmd(peer, inventory) return s.handleInvCmd(peer, inventory)
case CMDBlock: case CMDBlock:
block := msg.Payload.(*core.Block) block := msg.Payload.(*block.Block)
return s.handleBlockCmd(peer, block) return s.handleBlockCmd(peer, block)
case CMDConsensus: case CMDConsensus:
cp := msg.Payload.(*consensus.Payload) cp := msg.Payload.(*consensus.Payload)
@ -735,7 +737,7 @@ func (s *Server) relayInventoryCmd(cmd CommandType, t payload.InventoryType, has
} }
// relayBlock tells all the other connected nodes about the given block. // 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()) s.relayInventoryCmd(CMDInv, payload.BlockType, b.Hash())
} }
@ -754,7 +756,7 @@ func (s *Server) RelayTxn(t *transaction.Transaction) RelayReason {
// TODO: Implement Plugin.CheckPolicy? // TODO: Implement Plugin.CheckPolicy?
//if (!Plugin.CheckPolicy(transaction)) //if (!Plugin.CheckPolicy(transaction))
// return RelayResultReason.PolicyFail; // return RelayResultReason.PolicyFail;
if ok := s.chain.GetMemPool().TryAdd(t.Hash(), core.NewPoolItem(t, s.chain)); !ok { if ok := s.chain.GetMemPool().TryAdd(t.Hash(), mempool.NewPoolItem(t, s.chain)); !ok {
return RelayOutOfMemory return RelayOutOfMemory
} }

View file

@ -7,6 +7,7 @@ import (
"github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/config"
"github.com/CityOfZion/neo-go/pkg/core" "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/core/storage"
"github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/network" "github.com/CityOfZion/neo-go/pkg/network"
@ -193,10 +194,10 @@ func initServerWithInMemoryChain(t *testing.T) (*core.Blockchain, http.HandlerFu
nBlocks = br.ReadU32LE() nBlocks = br.ReadU32LE()
require.Nil(t, br.Err) require.Nil(t, br.Err)
for i := 0; i < int(nBlocks); i++ { for i := 0; i < int(nBlocks); i++ {
block := &core.Block{} b := &block.Block{}
block.DecodeBinary(br) b.DecodeBinary(br)
require.Nil(t, br.Err) require.Nil(t, br.Err)
require.NoError(t, chain.AddBlock(block)) require.NoError(t, chain.AddBlock(b))
} }
serverConfig := network.NewServerConfig(cfg) serverConfig := network.NewServerConfig(cfg)

View file

@ -2,14 +2,15 @@ package wrappers
import ( import (
"github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/core/block"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
type ( type (
// Block wrapper used for the representation of // Block wrapper used for the representation of
// core.Block / core.BlockBase on the RPC Server. // block.Block / block.Base on the RPC Server.
Block struct { Block struct {
*core.Block *block.Block
Confirmations uint32 `json:"confirmations"` Confirmations uint32 `json:"confirmations"`
NextBlockHash util.Uint256 `json:"nextblockhash,omitempty"` NextBlockHash util.Uint256 `json:"nextblockhash,omitempty"`
Hash util.Uint256 `json:"hash"` Hash util.Uint256 `json:"hash"`
@ -17,7 +18,7 @@ type (
) )
// NewBlock creates a new Block wrapper. // 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{ blockWrapper := Block{
Block: block, Block: block,
Hash: block.Hash(), Hash: block.Hash(),

View file

@ -2,6 +2,7 @@ package wrappers
import ( import (
"github.com/CityOfZion/neo-go/pkg/core" "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/core/transaction"
"github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
@ -21,9 +22,9 @@ type TransactionOutputRaw struct {
} }
// NewTransactionOutputRaw returns a new ransactionOutputRaw object. // 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 formula
confirmations := int(chain.BlockHeight() - header.BlockBase.Index + 1) confirmations := int(chain.BlockHeight() - header.Base.Index + 1)
// set index position // set index position
for i, o := range tx.Outputs { for i, o := range tx.Outputs {
o.Position = i o.Position = i