Remove blockchain dependency from engine. (#4310)

* Consensus doesn't require anymore `Node` as a circular dependency.

* Rebased upon main.

* Removed engine beacon chain dependency.

* Fixed nil error.

* Fixed error.
pull/4318/head
Konstantin 2 years ago committed by GitHub
parent 8547c8c7b8
commit 1c443aee45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      cmd/harmony/main.go
  2. 10
      consensus/engine/consensus_engine.go
  3. 2
      core/block_validator.go
  4. 20
      core/blockchain_impl.go
  5. 2
      core/evm_test.go
  6. 16
      core/state_processor.go
  7. 2
      core/tx_pool_test.go
  8. 2
      hmy/downloader/adapter_test.go
  9. 16
      internal/chain/engine.go
  10. 18
      internal/shardchain/shardchains.go
  11. 3
      node/node.go
  12. 8
      node/worker/worker.go
  13. 8
      node/worker/worker_test.go
  14. 2
      test/chain/chain/chain_makers.go
  15. 4
      test/chain/main.go
  16. 2
      test/chain/reward/main.go

@ -696,7 +696,18 @@ func setupConsensusAndNode(hc harmonyconfig.HarmonyConfig, nodeConfig *nodeconfi
&hc, chainDBFactory, &core.GenesisInitializer{NetworkType: nodeConfig.GetNetworkType()}, engine, &chainConfig,
)
blockchain, err := collection.ShardChain(nodeConfig.ShardID)
var blockchain core.BlockChain
// We are not beacon chain, make sure beacon already initialized.
if nodeConfig.ShardID != shard.BeaconChainShardID {
_, err = collection.ShardChain(shard.BeaconChainShardID)
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "Error :%v \n", err)
os.Exit(1)
}
}
blockchain, err = collection.ShardChain(nodeConfig.ShardID)
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "Error :%v \n", err)
os.Exit(1)

@ -108,12 +108,6 @@ type Engine interface {
// VerifyVRF verifies the vrf of the block
VerifyVRF(chain ChainReader, header *block.Header) error
// Beaconchain provides the handle for Beaconchain
Beaconchain() ChainReader
// SetBeaconchain sets the beaconchain handler on engine
SetBeaconchain(ChainReader)
// Finalize runs any post-transaction state modifications (e.g. block rewards)
// and assembles the final block.
// Note: The block header and state database might be updated to reflect any
@ -121,7 +115,9 @@ type Engine interface {
// sigsReady signal indicates whether the commit sigs are populated in the header object.
// Finalize() will block on sigsReady signal until the first value is send to the channel.
Finalize(
chain ChainReader, header *block.Header,
chain ChainReader,
beacon ChainReader,
header *block.Header,
state *state.DB, txs []*types.Transaction,
receipts []*types.Receipt, outcxs []*types.CXReceipt,
incxs []*types.CXReceiptsProof, stks staking.StakingTransactions,

@ -25,9 +25,9 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/harmony/block"
"github.com/pkg/errors"
"github.com/harmony-one/harmony/block"
consensus_engine "github.com/harmony-one/harmony/consensus/engine"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types"

@ -200,24 +200,25 @@ type BlockChainImpl struct {
// NewBlockChainWithOptions same as NewBlockChain but can accept additional behaviour options.
func NewBlockChainWithOptions(
db ethdb.Database, stateCache state.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig,
db ethdb.Database, stateCache state.Database, beaconChain BlockChain, cacheConfig *CacheConfig, chainConfig *params.ChainConfig,
engine consensus_engine.Engine, vmConfig vm.Config, options Options,
) (*BlockChainImpl, error) {
return newBlockChainWithOptions(db, stateCache, cacheConfig, chainConfig, engine, vmConfig, options)
return newBlockChainWithOptions(db, stateCache, beaconChain, cacheConfig, chainConfig, engine, vmConfig, options)
}
// NewBlockChain returns a fully initialised block chain using information
// available in the database. It initialises the default Ethereum validator and
// Processor.
func NewBlockChain(
db ethdb.Database, stateCache state.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig,
db ethdb.Database, stateCache state.Database, beaconChain BlockChain, cacheConfig *CacheConfig, chainConfig *params.ChainConfig,
engine consensus_engine.Engine, vmConfig vm.Config,
) (*BlockChainImpl, error) {
return newBlockChainWithOptions(db, stateCache, cacheConfig, chainConfig, engine, vmConfig, Options{})
return newBlockChainWithOptions(db, stateCache, beaconChain, cacheConfig, chainConfig, engine, vmConfig, Options{})
}
func newBlockChainWithOptions(
db ethdb.Database, stateCache state.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig,
db ethdb.Database, stateCache state.Database, beaconChain BlockChain,
cacheConfig *CacheConfig, chainConfig *params.ChainConfig,
engine consensus_engine.Engine, vmConfig vm.Config, options Options) (*BlockChainImpl, error) {
if cacheConfig == nil {
cacheConfig = &CacheConfig{
@ -272,8 +273,6 @@ func newBlockChainWithOptions(
maxGarbCollectedBlkNum: -1,
options: options,
}
bc.SetValidator(NewBlockValidator(chainConfig, bc, engine))
bc.SetProcessor(NewStateProcessor(chainConfig, bc, engine))
var err error
bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.getProcInterrupt)
@ -291,6 +290,13 @@ func newBlockChainWithOptions(
return nil, err
}
bc.shardID = bc.CurrentBlock().ShardID()
if beaconChain == nil && bc.shardID == shard.BeaconChainShardID {
beaconChain = bc
}
bc.SetValidator(NewBlockValidator(chainConfig, bc, engine))
bc.SetProcessor(NewStateProcessor(chainConfig, bc, beaconChain, engine))
// Take ownership of this particular state
go bc.update()
return bc, nil

@ -46,7 +46,7 @@ func getTestEnvironment(testBankKey ecdsa.PrivateKey) (*BlockChainImpl, *state.D
genesis := gspec.MustCommit(database)
// fake blockchain
chain, _ := NewBlockChain(database, state.NewDatabase(database), nil, gspec.Config, engine, vm.Config{})
chain, _ := NewBlockChain(database, state.NewDatabase(database), nil, nil, gspec.Config, engine, vm.Config{})
db, _ := chain.StateAt(genesis.Root())
// make a fake block header (use epoch 1 so that locked tokens can be tested)

@ -51,7 +51,8 @@ const (
// StateProcessor implements Processor.
type StateProcessor struct {
config *params.ChainConfig // Chain configuration options
bc BlockChain // Canonical block chain
bc BlockChain // Canonical blockchain
beacon BlockChain // Beacon chain
engine consensus_engine.Engine // Consensus engine used for block rewards
resultCache *lru.Cache // Cache for result after a certain block is processed
}
@ -69,12 +70,19 @@ type ProcessorResult struct {
// NewStateProcessor initialises a new StateProcessor.
func NewStateProcessor(
config *params.ChainConfig, bc BlockChain, engine consensus_engine.Engine,
config *params.ChainConfig, bc BlockChain, beacon BlockChain, engine consensus_engine.Engine,
) *StateProcessor {
if bc == nil {
panic("bc is nil")
}
if beacon == nil {
panic("beacon is nil")
}
resultCache, _ := lru.New(resultCacheLimit)
return &StateProcessor{
config: config,
bc: bc,
beacon: beacon,
engine: engine,
resultCache: resultCache,
}
@ -188,7 +196,9 @@ func (p *StateProcessor) Process(
sigsReady <- true
}()
_, payout, err := p.engine.Finalize(
p.bc, header, statedb, block.Transactions(),
p.bc,
p.beacon,
header, statedb, block.Transactions(),
receipts, outcxs, incxs, block.StakingTransactions(), slashes, sigsReady, func() uint64 { return header.ViewID().Uint64() },
)
if err != nil {

@ -161,7 +161,7 @@ func createBlockChain() *BlockChainImpl {
genesis := gspec.MustCommit(database)
_ = genesis
engine := chain2.NewEngine()
blockchain, _ := NewBlockChain(database, state.NewDatabase(database), nil, gspec.Config, engine, vm.Config{})
blockchain, _ := NewBlockChain(database, state.NewDatabase(database), nil, nil, gspec.Config, engine, vm.Config{})
return blockchain
}

@ -147,7 +147,7 @@ func (e *dummyEngine) VerifyShardState(engine.ChainReader, engine.ChainReader, *
func (e *dummyEngine) Beaconchain() engine.ChainReader { return nil }
func (e *dummyEngine) SetBeaconchain(engine.ChainReader) {}
func (e *dummyEngine) Finalize(
chain engine.ChainReader, header *block.Header,
chain engine.ChainReader, beacon engine.ChainReader, header *block.Header,
state *state.DB, txs []*types.Transaction,
receipts []*types.Receipt, outcxs []*types.CXReceipt,
incxs []*types.CXReceiptsProof, stks staking.StakingTransactions,

@ -40,8 +40,6 @@ const (
)
type engineImpl struct {
beacon engine.ChainReader
// Caching field
epochCtxCache *lru.Cache // epochCtxKey -> epochCtx
verifiedSigCache *lru.Cache // verifiedSigKey -> struct{}{}
@ -52,21 +50,11 @@ func NewEngine() *engineImpl {
sigCache, _ := lru.New(verifiedSigCache)
epochCtxCache, _ := lru.New(epochCtxCache)
return &engineImpl{
beacon: nil,
epochCtxCache: epochCtxCache,
verifiedSigCache: sigCache,
}
}
func (e *engineImpl) Beaconchain() engine.ChainReader {
return e.beacon
}
// SetBeaconchain assigns the beaconchain handle used
func (e *engineImpl) SetBeaconchain(beaconchain engine.ChainReader) {
e.beacon = beaconchain
}
// VerifyHeader checks whether a header conforms to the consensus rules of the bft engine.
// Note that each block header contains the bls signature of the parent block
func (e *engineImpl) VerifyHeader(chain engine.ChainReader, header *block.Header, seal bool) error {
@ -274,7 +262,7 @@ func (e *engineImpl) VerifySeal(chain engine.ChainReader, header *block.Header)
// setting the final state and assembling the block.
// sigsReady signal indicates whether the commit sigs are populated in the header object.
func (e *engineImpl) Finalize(
chain engine.ChainReader, header *block.Header,
chain engine.ChainReader, beacon engine.ChainReader, header *block.Header,
state *state.DB, txs []*types.Transaction,
receipts []*types.Receipt, outcxs []*types.CXReceipt,
incxs []*types.CXReceiptsProof, stks staking.StakingTransactions,
@ -324,7 +312,7 @@ func (e *engineImpl) Finalize(
// Accumulate block rewards and commit the final state root
// Header seems complete, assemble into a block and return
payout, err := AccumulateRewardsAndCountSigs(
chain, state, header, e.Beaconchain(), sigsReady,
chain, state, header, beacon, sigsReady,
)
if err != nil {
return nil, nil, err

@ -124,10 +124,20 @@ func (sc *CollectionImpl) ShardChain(shardID uint32, options ...core.Options) (c
if err != nil {
return nil, err
}
bc, err = core.NewBlockChainWithOptions(
db, stateCache, cacheConfig, &chainConfig, sc.engine, vm.Config{}, opts,
)
if shardID == shard.BeaconChainShardID {
bc, err = core.NewBlockChainWithOptions(
db, stateCache, bc, cacheConfig, &chainConfig, sc.engine, vm.Config{}, opts,
)
} else {
beacon, ok := sc.pool[shard.BeaconChainShardID]
if !ok {
return nil, errors.New("beacon chain is not initialized")
}
bc, err = core.NewBlockChainWithOptions(
db, stateCache, beacon, cacheConfig, &chainConfig, sc.engine, vm.Config{}, opts,
)
}
}
if err != nil {

@ -1081,7 +1081,7 @@ func New(
node.TxPool = core.NewTxPool(txPoolConfig, node.Blockchain().Config(), blockchain, node.TransactionErrorSink)
node.CxPool = core.NewCxPool(core.CxPoolSize)
node.Worker = worker.New(node.Blockchain().Config(), blockchain, engine)
node.Worker = worker.New(node.Blockchain().Config(), blockchain, beaconChain, engine)
node.deciderCache, _ = lru.New(16)
node.committeeCache, _ = lru.New(16)
@ -1089,7 +1089,6 @@ func New(
node.pendingCXReceipts = map[string]*types.CXReceiptsProof{}
node.proposedBlock = map[uint64]*types.Block{}
node.Consensus.VerifiedNewBlock = make(chan *types.Block, 1)
engine.SetBeaconchain(beaconChain)
// the sequence number is the next block number to be added in consensus protocol, which is
// always one more than current chain header block
node.Consensus.SetBlockNum(blockchain.CurrentBlock().NumberU64() + 1)

@ -57,6 +57,7 @@ type Worker struct {
config *params.ChainConfig
factory blockfactory.Factory
chain core.BlockChain
beacon core.BlockChain
current *environment // An environment for current running cycle.
engine consensus_engine.Engine
gasFloor uint64
@ -558,7 +559,9 @@ func (w *Worker) FinalizeNewBlock(
}()
block, payout, err := w.engine.Finalize(
w.chain, copyHeader, state, w.current.txs, w.current.receipts,
w.chain,
w.beacon,
copyHeader, state, w.current.txs, w.current.receipts,
w.current.outcxs, w.current.incxs, w.current.stakingTxs,
w.current.slashes, sigsReady, viewID,
)
@ -571,12 +574,13 @@ func (w *Worker) FinalizeNewBlock(
// New create a new worker object.
func New(
config *params.ChainConfig, chain core.BlockChain, engine consensus_engine.Engine,
config *params.ChainConfig, chain core.BlockChain, beacon core.BlockChain, engine consensus_engine.Engine,
) *Worker {
worker := &Worker{
config: config,
factory: blockfactory.NewFactory(config),
chain: chain,
beacon: beacon,
engine: engine,
}
worker.gasFloor = 80000000

@ -45,13 +45,13 @@ func TestNewWorker(t *testing.T) {
genesis := gspec.MustCommit(database)
_ = genesis
chain, err := core.NewBlockChain(database, state.NewDatabase(database), nil, gspec.Config, engine, vm.Config{})
chain, err := core.NewBlockChain(database, state.NewDatabase(database), &core.BlockChainImpl{}, nil, gspec.Config, engine, vm.Config{})
if err != nil {
t.Error(err)
}
// Create a new worker
worker := New(params.TestChainConfig, chain, engine)
worker := New(params.TestChainConfig, chain, nil, engine)
if worker.GetCurrentState().GetBalance(crypto.PubkeyToAddress(testBankKey.PublicKey)).Cmp(testBankFunds) != 0 {
t.Error("Worker state is not setup correctly")
@ -72,10 +72,10 @@ func TestCommitTransactions(t *testing.T) {
)
gspec.MustCommit(database)
chain, _ := core.NewBlockChain(database, state.NewDatabase(database), nil, gspec.Config, engine, vm.Config{})
chain, _ := core.NewBlockChain(database, state.NewDatabase(database), nil, nil, gspec.Config, engine, vm.Config{})
// Create a new worker
worker := New(params.TestChainConfig, chain, engine)
worker := New(params.TestChainConfig, chain, nil, engine)
// Generate a test tx
baseNonce := worker.GetCurrentState().GetNonce(crypto.PubkeyToAddress(testBankKey.PublicKey))

@ -197,7 +197,7 @@ func GenerateChain(
if b.engine != nil {
// Finalize and seal the block
block, _, err := b.engine.Finalize(
chainreader, b.header, statedb, b.txs, b.receipts, nil, nil, nil, nil, nil, func() uint64 { return 0 },
chainreader, nil, b.header, statedb, b.txs, b.receipts, nil, nil, nil, nil, nil, func() uint64 { return 0 },
)
if err != nil {
panic(err)

@ -94,7 +94,7 @@ func fundFaucetContract(chain core.BlockChain) {
fmt.Println("--------- Funding addresses for Faucet Contract Call ---------")
fmt.Println()
contractworker = pkgworker.New(params.TestChainConfig, chain, chain.Engine())
contractworker = pkgworker.New(params.TestChainConfig, chain, nil, chain.Engine())
nonce = contractworker.GetCurrentState().GetNonce(crypto.PubkeyToAddress(FaucetPriKey.PublicKey))
dataEnc = common.FromHex(FaucetContractBinary)
ftx, _ := types.SignTx(
@ -206,7 +206,7 @@ func playFaucetContract(chain core.BlockChain) {
func main() {
genesis := gspec.MustCommit(database)
chain, _ := core.NewBlockChain(database, harmonyState.NewDatabase(database), nil, gspec.Config, chain.Engine(), vm.Config{})
chain, _ := core.NewBlockChain(database, harmonyState.NewDatabase(database), nil, nil, gspec.Config, chain.Engine(), vm.Config{})
txpool := core.NewTxPool(core.DefaultTxPoolConfig, chainConfig, chain, types.NewTransactionErrorSink())
backend := &testWorkerBackend{

@ -109,7 +109,7 @@ func main() {
genesis := gspec.MustCommit(database)
_ = genesis
engine := chain.NewEngine()
bc, _ := core.NewBlockChain(database, state.NewDatabase(database), nil, gspec.Config, engine, vm.Config{})
bc, _ := core.NewBlockChain(database, state.NewDatabase(database), nil, nil, gspec.Config, engine, vm.Config{})
statedb, _ := state.New(common2.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
msg := createValidator()
statedb.AddBalance(msg.ValidatorAddress, new(big.Int).Mul(big.NewInt(5e18), big.NewInt(2000)))

Loading…
Cancel
Save