102 lines
2.6 KiB
Go
102 lines
2.6 KiB
Go
package pool
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/asaskevich/EventBus"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"github.com/Secured-Finance/dione/blockchain/types"
|
|
"github.com/Secured-Finance/dione/cache"
|
|
)
|
|
|
|
// BlockPool is pool for blocks that isn't not validated or committed yet
|
|
type BlockPool struct {
|
|
mempool *Mempool
|
|
knownBlocks cache.Cache
|
|
acceptedBlocks cache.Cache
|
|
bus EventBus.Bus
|
|
}
|
|
|
|
func NewBlockPool(mp *Mempool, bus EventBus.Bus) (*BlockPool, error) {
|
|
bp := &BlockPool{
|
|
acceptedBlocks: cache.NewInMemoryCache(), // here we need to use separate cache
|
|
knownBlocks: cache.NewInMemoryCache(),
|
|
mempool: mp,
|
|
bus: bus,
|
|
}
|
|
|
|
return bp, nil
|
|
}
|
|
|
|
func (bp *BlockPool) AddBlock(block *types.Block) error {
|
|
err := bp.knownBlocks.StoreWithTTL(hex.EncodeToString(block.Header.Hash), block, 10*time.Minute)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
logrus.WithField("hash", fmt.Sprintf("%x", block.Header.Hash)).Debug("New block discovered")
|
|
bp.bus.Publish("blockpool:knownBlockAdded", block)
|
|
return nil
|
|
}
|
|
|
|
func (bp *BlockPool) GetBlock(blockhash []byte) (*types.Block, error) {
|
|
var block types.Block
|
|
err := bp.knownBlocks.Get(hex.EncodeToString(blockhash), &block)
|
|
return &block, err
|
|
}
|
|
|
|
// PruneBlocks cleans known blocks list. It is called when new consensus round starts.
|
|
func (bp *BlockPool) PruneBlocks() {
|
|
for k := range bp.knownBlocks.Items() {
|
|
bp.knownBlocks.Delete(k)
|
|
}
|
|
bp.bus.Publish("blockpool:pruned")
|
|
}
|
|
|
|
func (bp *BlockPool) AddAcceptedBlock(block *types.Block) error {
|
|
err := bp.acceptedBlocks.Store(hex.EncodeToString(block.Header.Hash), block)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
bp.bus.Publish("blockpool:acceptedBlockAdded", block)
|
|
return nil
|
|
}
|
|
|
|
func (bp *BlockPool) GetAllAcceptedBlocks() []*types.Block {
|
|
var blocks []*types.Block
|
|
for _, v := range bp.acceptedBlocks.Items() {
|
|
blocks = append(blocks, v.(*types.Block))
|
|
}
|
|
return blocks
|
|
}
|
|
|
|
// PruneAcceptedBlocks cleans accepted blocks list. It is called when new consensus round starts.
|
|
func (bp *BlockPool) PruneAcceptedBlocks(committedBlock *types.Block) {
|
|
for k, v := range bp.acceptedBlocks.Items() {
|
|
block := v.(*types.Block)
|
|
for _, v := range block.Data {
|
|
if !containsTx(committedBlock.Data, v) {
|
|
v.MerkleProof = nil
|
|
err := bp.mempool.StoreTx(v) // return transactions back to mempool
|
|
if err != nil {
|
|
logrus.Error(err)
|
|
}
|
|
}
|
|
}
|
|
bp.acceptedBlocks.Delete(k)
|
|
}
|
|
}
|
|
|
|
func containsTx(s []*types.Transaction, e *types.Transaction) bool {
|
|
for _, a := range s {
|
|
if bytes.Equal(a.Hash, e.Hash) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|