ErrBadStateRoot = errors.New("invalid state merkle root")
)
+// BlockExist check is a block in chain or orphan
func (c *Chain) BlockExist(hash *bc.Hash) bool {
return c.orphanManage.BlockExist(hash) || c.store.BlockExist(hash)
}
+// GetBlockByHash return a block by given hash
func (c *Chain) GetBlockByHash(hash *bc.Hash) (*legacy.Block, error) {
return c.store.GetBlock(hash)
}
+// GetBlockByHeight return a block by given height
func (c *Chain) GetBlockByHeight(height uint64) (*legacy.Block, error) {
c.state.cond.L.Lock()
hash, ok := c.state.mainChain[height]
return nil
}
+// ConnectBlock append block to end of chain
func (c *Chain) ConnectBlock(block *legacy.Block) error {
c.state.cond.L.Lock()
defer c.state.cond.L.Unlock()
return c.setState(block, newSnapshot, chainChanges)
}
+// SaveBlock will validate and save block into storage
func (c *Chain) SaveBlock(block *legacy.Block) error {
preBlock, _ := c.GetBlockByHash(&block.PreviousBlockHash)
if err := c.ValidateBlock(block, preBlock); err != nil {
return
}
+// ProcessBlock is the entry for handle block insert
func (c *Chain) ProcessBlock(block *legacy.Block) (bool, error) {
blockHash := block.Hash()
if c.BlockExist(&blockHash) {
return false, c.connectBlock(bestBlock)
}
- if bestBlock.Height > c.state.height && bestBlock.Bits >= c.state.block.Bits {
+ if bestBlock.Height > c.state.block.Height && bestBlock.Bits >= c.state.block.Bits {
defer c.state.cond.L.Unlock()
return false, c.reorganizeChain(bestBlock)
}
)
var (
- maxCachedErrTxs = 1000
- maxNewTxChSize = 1000
+ maxCachedErrTxs = 1000
+ maxNewTxChSize = 1000
+ // ErrTransactionNotExist is the pre-defined error message
ErrTransactionNotExist = errors.New("transaction are not existed in the mempool")
)
+// TxDesc store tx and related info for mining strategy
type TxDesc struct {
Tx *legacy.Tx
Added time.Time
FeePerKB uint64
}
+// TxPool is use for store the unconfirmed transaction
type TxPool struct {
lastUpdated int64
mtx sync.RWMutex
newTxCh chan *legacy.Tx
}
+// NewTxPool init a new TxPool
func NewTxPool() *TxPool {
return &TxPool{
lastUpdated: time.Now().Unix(),
}
}
+// GetNewTxCh return a unconfirmed transaction feed channel
func (mp *TxPool) GetNewTxCh() chan *legacy.Tx {
return mp.newTxCh
}
+// AddTransaction add a verified transaction to pool
func (mp *TxPool) AddTransaction(tx *legacy.Tx, height, fee uint64) *TxDesc {
txD := &TxDesc{
Tx: tx,
return txD
}
+// AddErrCache add a failed transaction record to lru cache
func (mp *TxPool) AddErrCache(txHash *bc.Hash, err error) {
mp.mtx.Lock()
defer mp.mtx.Unlock()
mp.errCache.Add(txHash, err)
}
+// GetErrCache return the error of the transaction
func (mp *TxPool) GetErrCache(txHash *bc.Hash) error {
mp.mtx.Lock()
defer mp.mtx.Unlock()
return v.(error)
}
+// RemoveTransaction remove a transaction from the pool
func (mp *TxPool) RemoveTransaction(txHash *bc.Hash) {
mp.mtx.Lock()
defer mp.mtx.Unlock()
}
}
+// GetTransaction return the TxDesc by hash
func (mp *TxPool) GetTransaction(txHash *bc.Hash) (*TxDesc, error) {
mp.mtx.RLock()
defer mp.mtx.RUnlock()
return nil, ErrTransactionNotExist
}
+// GetTransactions return all the transactions in the pool
func (mp *TxPool) GetTransactions() []*TxDesc {
mp.mtx.RLock()
defer mp.mtx.RUnlock()
return txDs
}
+// IsTransactionInPool check wheather a transaction in pool or not
func (mp *TxPool) IsTransactionInPool(txHash *bc.Hash) bool {
mp.mtx.RLock()
defer mp.mtx.RUnlock()
return false
}
+// IsTransactionInErrCache check wheather a transaction in errCache or not
func (mp *TxPool) IsTransactionInErrCache(txHash *bc.Hash) bool {
mp.mtx.RLock()
defer mp.mtx.RUnlock()
return ok
}
+// HaveTransaction IsTransactionInErrCache check is transaction in errCache or pool
func (mp *TxPool) HaveTransaction(txHash *bc.Hash) bool {
return mp.IsTransactionInPool(txHash) || mp.IsTransactionInErrCache(txHash)
}
+// Count return number of transcation in pool
func (mp *TxPool) Count() int {
mp.mtx.RLock()
defer mp.mtx.RUnlock()
SaveStoreStatus(uint64, *bc.Hash)
}
+// OrphanManage is use to handle all the orphan block
type OrphanManage struct {
//TODO: add orphan cached block limit
orphan map[bc.Hash]*legacy.Block
mtx sync.RWMutex
}
+// NewOrphanManage return a new orphan block
func NewOrphanManage() *OrphanManage {
return &OrphanManage{
orphan: make(map[bc.Hash]*legacy.Block),
}
}
+// BlockExist check is the block in OrphanManage
func (o *OrphanManage) BlockExist(hash *bc.Hash) bool {
o.mtx.RLock()
_, ok := o.orphan[*hash]
return ok
}
+// Add will add the block to OrphanManage
func (o *OrphanManage) Add(block *legacy.Block) {
blockHash := block.Hash()
o.mtx.Lock()
o.preOrphans[block.PreviousBlockHash] = append(o.preOrphans[block.PreviousBlockHash], &blockHash)
}
+// Delete will delelte the block from OrphanManage
func (o *OrphanManage) Delete(hash *bc.Hash) {
o.mtx.Lock()
defer o.mtx.Unlock()
}
}
+// Get return the orphan block by hash
func (o *OrphanManage) Get(hash *bc.Hash) (*legacy.Block, bool) {
o.mtx.RLock()
block, ok := o.orphan[*hash]
state struct {
cond sync.Cond
block *legacy.Block
- height uint64
hash *bc.Hash
mainChain map[uint64]*bc.Hash
snapshot *state.Snapshot
}
c.state.cond.L = new(sync.Mutex)
storeStatus := store.GetStoreStatus()
- c.state.height = storeStatus.Height
- if c.state.height == 0 {
+ if storeStatus.Height == 0 {
c.state.snapshot = state.Empty()
c.state.mainChain = make(map[uint64]*bc.Hash)
return c, nil
func (c *Chain) Height() uint64 {
c.state.cond.L.Lock()
defer c.state.cond.L.Unlock()
- return c.state.height
+ return c.state.block.Height
}
func (c *Chain) BestBlockHash() *bc.Hash {
blockHash := block.Hash()
c.state.block = block
- c.state.height = block.Height
c.state.hash = &blockHash
c.state.snapshot = s
for k, v := range m {
go func() {
c.state.cond.L.Lock()
defer c.state.cond.L.Unlock()
- for c.state.height < height {
+ for c.state.block.Height < height {
c.state.cond.Wait()
}
ch <- struct{}{}