Small improvements. (#4477)

pull/4511/head
Konstantin 1 year ago committed by GitHub
parent b798df0c06
commit 6d65d11ac5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 34
      core/block_validator.go
  2. 2
      core/blockchain.go
  3. 36
      core/blockchain_impl.go
  4. 19
      core/staking_verifier.go
  5. 16
      core/staking_verifier_test.go
  6. 34
      core/state_processor.go
  7. 4
      core/types.go
  8. 4
      node/node.go
  9. 5
      node/node_newblock.go
  10. 16
      node/worker/worker.go
  11. 4
      node/worker/worker_test.go
  12. 2
      test/chain/chain/chain_makers.go
  13. 2
      test/chain/main.go

@ -40,17 +40,13 @@ import (
//
// BlockValidator implements validator.
type BlockValidator struct {
config *params.ChainConfig // Chain configuration options
bc BlockChain // Canonical blockchain
engine consensus_engine.Engine // Consensus engine used for validating
bc BlockChain // Canonical blockchain
}
// NewBlockValidator returns a new block validator which is safe for re-use
func NewBlockValidator(config *params.ChainConfig, blockchain BlockChain, engine consensus_engine.Engine) *BlockValidator {
func NewBlockValidator(blockchain BlockChain) *BlockValidator {
validator := &BlockValidator{
config: config,
engine: engine,
bc: blockchain,
bc: blockchain,
}
return validator
}
@ -103,7 +99,7 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.DB, re
return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash(), receiptSha)
}
if v.config.AcceptsCrossTx(block.Epoch()) {
if v.bc.Config().AcceptsCrossTx(block.Epoch()) {
cxsSha := cxReceipts.ComputeMerkleRoot()
if cxsSha != header.OutgoingReceiptHash() {
legacySha := types.DeriveMultipleShardsSha(cxReceipts)
@ -115,7 +111,7 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.DB, re
// Validate the state root against the received state root and throw
// an error if they don't match.
if root := statedb.IntermediateRoot(v.config.IsS3(header.Epoch())); header.Root() != root {
if root := statedb.IntermediateRoot(v.bc.Config().IsS3(header.Epoch())); header.Root() != root {
dump, _ := rlp.EncodeToBytes(header)
const msg = "invalid merkle root (remote: %x local: %x, rlp dump %s)"
return fmt.Errorf(msg, header.Root(), root, hex.EncodeToString(dump))
@ -131,25 +127,11 @@ func (v *BlockValidator) ValidateHeader(block *types.Block, seal bool) error {
return errors.New("block is nil")
}
if h := block.Header(); h != nil {
return v.engine.VerifyHeader(v.bc, h, true)
return v.bc.Engine().VerifyHeader(v.bc, h, true)
}
return errors.New("header field was nil")
}
// ValidateHeaders verifies a batch of blocks' headers concurrently. The method returns a quit channel
// to abort the operations and a results channel to retrieve the async verifications
func (v *BlockValidator) ValidateHeaders(chain []*types.Block) (chan<- struct{}, <-chan error) {
// Start the parallel header verifier
headers := make([]*block.Header, len(chain))
seals := make([]bool, len(chain))
for i, block := range chain {
headers[i] = block.Header()
seals[i] = true
}
return v.engine.VerifyHeaders(v.bc, headers, seals)
}
// CalcGasLimit computes the gas limit of the next block after parent. It aims
// to keep the baseline gas above the provided floor, and increase it towards the
// ceil if the blocks are full. If the ceil is exceeded, it will always decrease
@ -189,7 +171,7 @@ func CalcGasLimit(parent *block.Header, gasFloor, gasCeil uint64) uint64 {
// ValidateCXReceiptsProof checks whether the given CXReceiptsProof is consistency with itself
func (v *BlockValidator) ValidateCXReceiptsProof(cxp *types.CXReceiptsProof) error {
if !v.config.AcceptsCrossTx(cxp.Header.Epoch()) {
if !v.bc.Config().AcceptsCrossTx(cxp.Header.Epoch()) {
return errors.New("[ValidateCXReceiptsProof] cross shard receipt received before cx fork")
}
@ -249,5 +231,5 @@ func (v *BlockValidator) ValidateCXReceiptsProof(cxp *types.CXReceiptsProof) err
// (4) verify blockHeader with seal
var commitSig bls.SerializedSignature
copy(commitSig[:], cxp.CommitSig)
return v.engine.VerifyHeaderSignature(v.bc, cxp.Header, commitSig, cxp.CommitBitmap)
return v.bc.Engine().VerifyHeaderSignature(v.bc, cxp.Header, commitSig, cxp.CommitBitmap)
}

@ -55,8 +55,6 @@ type BlockChain interface {
// CurrentBlock retrieves the current head block of the canonical chain. The
// block is retrieved from the blockchain's internal cache.
CurrentBlock() *types.Block
// Validator returns the current validator.
Validator() Validator
// Processor returns the current processor.
Processor() Processor
// State returns a new mutable state based on the current HEAD block.

@ -215,8 +215,8 @@ type BlockChainImpl struct {
procInterrupt int32 // interrupt signaler for block processing
engine consensus_engine.Engine
processor Processor // block processor interface
validator Validator // block and state validator interface
processor *StateProcessor // block processor interface
validator *BlockValidator
vmConfig vm.Config
badBlocks *lru.Cache // Bad block cache
pendingSlashes slash.Records
@ -335,8 +335,8 @@ func newBlockChainWithOptions(
beaconChain = bc
}
bc.SetValidator(NewBlockValidator(chainConfig, bc, engine))
bc.SetProcessor(NewStateProcessor(chainConfig, bc, beaconChain, engine))
bc.validator = NewBlockValidator(bc)
bc.processor = NewStateProcessor(bc, beaconChain)
// Load any existing snapshot, regenerating it if loading failed
if bc.cacheConfig.SnapshotLimit > 0 {
@ -454,7 +454,7 @@ func VerifyIncomingReceipts(blockchain BlockChain, block *types.Block) error {
}
}
if err := blockchain.Validator().ValidateCXReceiptsProof(cxp); err != nil {
if err := NewBlockValidator(blockchain).ValidateCXReceiptsProof(cxp); err != nil {
return errors.Wrapf(err, "[verifyIncomingReceipts] verification failed")
}
}
@ -486,7 +486,7 @@ func (bc *BlockChainImpl) ValidateNewBlock(block *types.Block, beaconChain Block
if block.NumberU64() <= bc.CurrentBlock().NumberU64() {
return errors.Errorf("block with the same block number is already committed: %d", block.NumberU64())
}
if err := bc.Validator().ValidateHeader(block, true); err != nil {
if err := bc.validator.ValidateHeader(block, true); err != nil {
utils.Logger().Error().
Str("blockHash", block.Hash().Hex()).
Err(err).
@ -548,7 +548,7 @@ func (bc *BlockChainImpl) validateNewBlock(block *types.Block) error {
}
// Verify all the hash roots (state, txns, receipts, cross-shard)
if err := bc.Validator().ValidateState(
if err := bc.validator.ValidateState(
block, state, receipts, cxReceipts, usedGas,
); err != nil {
bc.reportBlock(block, receipts, err)
@ -734,24 +734,6 @@ func (bc *BlockChainImpl) CurrentFastBlock() *types.Block {
return bc.currentFastBlock.Load().(*types.Block)
}
func (bc *BlockChainImpl) SetProcessor(processor Processor) {
bc.procmu.Lock()
defer bc.procmu.Unlock()
bc.processor = processor
}
func (bc *BlockChainImpl) SetValidator(validator Validator) {
bc.procmu.Lock()
defer bc.procmu.Unlock()
bc.validator = validator
}
func (bc *BlockChainImpl) Validator() Validator {
bc.procmu.RLock()
defer bc.procmu.RUnlock()
return bc.validator
}
func (bc *BlockChainImpl) Processor() Processor {
bc.procmu.RLock()
defer bc.procmu.RUnlock()
@ -1804,7 +1786,7 @@ func (bc *BlockChainImpl) insertChain(chain types.Blocks, verifyHeaders bool) (i
err = <-verifyHeadersResults
}
if err == nil {
err = bc.Validator().ValidateBody(block)
err = NewBlockValidator(bc).ValidateBody(block)
}
switch {
case err == ErrKnownBlock:
@ -1922,7 +1904,7 @@ func (bc *BlockChainImpl) insertChain(chain types.Blocks, verifyHeaders bool) (i
// Validate the state using the default validator
substart = time.Now()
if err := bc.Validator().ValidateState(
if err := bc.validator.ValidateState(
block, state, receipts, cxReceipts, usedGas,
); err != nil {
bc.reportBlock(block, receipts, err)

@ -30,14 +30,9 @@ var (
)
func checkDuplicateFields(
bc ChainContext, state vm.StateDB,
addrs []common.Address, state vm.StateDB,
validator common.Address, identity string, blsKeys []bls.SerializedPublicKey,
) error {
addrs, err := bc.ReadValidatorList()
if err != nil {
return err
}
checkIdentity := identity != ""
checkBlsKeys := len(blsKeys) != 0
@ -99,8 +94,12 @@ func VerifyAndCreateValidatorFromMsg(
errValidatorExist, common2.MustAddressToBech32(msg.ValidatorAddress),
)
}
addrs, err := chainContext.ReadValidatorList()
if err != nil {
return nil, err
}
if err := checkDuplicateFields(
chainContext, stateDB,
addrs, stateDB,
msg.ValidatorAddress,
msg.Identity,
msg.SlotPubKeys); err != nil {
@ -151,8 +150,12 @@ func VerifyAndEditValidatorFromMsg(
if msg.SlotKeyToAdd != nil {
newBlsKeys = append(newBlsKeys, *msg.SlotKeyToAdd)
}
addrs, err := chainContext.ReadValidatorList()
if err != nil {
return nil, err
}
if err := checkDuplicateFields(
chainContext, stateDB,
addrs, stateDB,
msg.ValidatorAddress,
msg.Identity,
newBlsKeys); err != nil {

@ -153,16 +153,6 @@ func TestCheckDuplicateFields(t *testing.T) {
expErr: nil,
},
{
// chain error
bc: &fakeErrChainContext{},
sdb: makeStateDBForStake(t),
validator: createValidatorAddr,
identity: makeIdentityStr("new validator"),
pubs: []bls.SerializedPublicKey{blsKeys[11].pub},
expErr: errors.New("error intended"),
},
{
// validators read from chain not in state
bc: func() *fakeChainContext {
@ -201,7 +191,11 @@ func TestCheckDuplicateFields(t *testing.T) {
},
}
for i, test := range tests {
err := checkDuplicateFields(test.bc, test.sdb, test.validator, test.identity, test.pubs)
addrs, err := test.bc.ReadValidatorList()
if err != nil {
t.Fatal(err)
}
err = checkDuplicateFields(addrs, test.sdb, test.validator, test.identity, test.pubs)
if assErr := assertError(err, test.expErr); assErr != nil {
t.Errorf("Test %v: %v", i, assErr)

@ -26,7 +26,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/harmony/block"
consensus_engine "github.com/harmony-one/harmony/consensus/engine"
"github.com/harmony-one/harmony/consensus/reward"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types"
@ -50,11 +49,9 @@ const (
//
// StateProcessor implements Processor.
type StateProcessor struct {
config *params.ChainConfig // Chain configuration options
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
bc BlockChain // Canonical blockchain
beacon BlockChain // Beacon chain
resultCache *lru.Cache // Cache for result after a certain block is processed
}
// this structure is cached, and each individual element is returned
@ -70,7 +67,7 @@ type ProcessorResult struct {
// NewStateProcessor initialises a new StateProcessor.
func NewStateProcessor(
config *params.ChainConfig, bc BlockChain, beacon BlockChain, engine consensus_engine.Engine,
bc BlockChain, beacon BlockChain,
) *StateProcessor {
if bc == nil {
panic("bc is nil")
@ -80,14 +77,14 @@ func NewStateProcessor(
}
resultCache, _ := lru.New(resultCacheLimit)
return &StateProcessor{
config: config,
bc: bc,
beacon: beacon,
engine: engine,
resultCache: resultCache,
}
}
type UsedGas = uint64
// Process processes the state changes according to the Ethereum rules by running
// the transaction messages using the statedb and applying any rewards to both
// the processor (coinbase) and any included uncles.
@ -99,7 +96,7 @@ func (p *StateProcessor) Process(
block *types.Block, statedb *state.DB, cfg vm.Config, readCache bool,
) (
types.Receipts, types.CXReceipts, []staking.StakeMsg,
[]*types.Log, uint64, reward.Reader, *state.DB, error,
[]*types.Log, UsedGas, reward.Reader, *state.DB, error,
) {
cacheKey := block.Hash()
if readCache {
@ -133,7 +130,7 @@ func (p *StateProcessor) Process(
for i, tx := range block.Transactions() {
statedb.Prepare(tx.Hash(), block.Hash(), i)
receipt, cxReceipt, stakeMsgs, _, err := ApplyTransaction(
p.config, p.bc, &beneficiary, gp, statedb, header, tx, usedGas, cfg,
p.bc, &beneficiary, gp, statedb, header, tx, usedGas, cfg,
)
if err != nil {
return nil, nil, nil, nil, 0, nil, statedb, err
@ -155,7 +152,7 @@ func (p *StateProcessor) Process(
for i, tx := range block.StakingTransactions() {
statedb.Prepare(tx.Hash(), block.Hash(), i+L)
receipt, _, err := ApplyStakingTransaction(
p.config, p.bc, &beneficiary, gp, statedb, header, tx, usedGas, cfg,
p.bc, &beneficiary, gp, statedb, header, tx, usedGas, cfg,
)
if err != nil {
return nil, nil, nil, nil, 0, nil, statedb, err
@ -169,7 +166,7 @@ func (p *StateProcessor) Process(
// after transactions (to be consistent with the block proposal)
for _, cx := range block.IncomingReceipts() {
if err := ApplyIncomingReceipt(
p.config, statedb, header, cx,
p.bc.Config(), statedb, header, cx,
); err != nil {
return nil, nil,
nil, nil, 0, nil, statedb, errors.New("[Process] Cannot apply incoming receipts")
@ -195,7 +192,7 @@ func (p *StateProcessor) Process(
// Block processing don't need to block on reward computation as in block proposal
sigsReady <- true
}()
_, payout, err := p.engine.Finalize(
_, payout, err := p.bc.Engine().Finalize(
p.bc,
p.beacon,
header, statedb, block.Transactions(),
@ -246,8 +243,9 @@ func getTransactionType(
// and uses the input parameters for its environment. It returns the receipt
// for the transaction, gas used and an error if the transaction failed,
// indicating the block was invalid.
func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.DB, header *block.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, *types.CXReceipt, []staking.StakeMsg, uint64, error) {
txType := getTransactionType(config, header, tx)
func ApplyTransaction(bc ChainContext, author *common.Address, gp *GasPool, statedb *state.DB, header *block.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, *types.CXReceipt, []staking.StakeMsg, uint64, error) {
config := bc.Config()
txType := getTransactionType(bc.Config(), header, tx)
if txType == types.InvalidTx {
return nil, nil, nil, 0, errors.New("Invalid Transaction Type")
}
@ -350,9 +348,9 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
// indicating the block was invalid.
// staking transaction will use the code field in the account to store the staking information
func ApplyStakingTransaction(
config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.DB,
bc ChainContext, author *common.Address, gp *GasPool, statedb *state.DB,
header *block.Header, tx *staking.StakingTransaction, usedGas *uint64, cfg vm.Config) (receipt *types.Receipt, gas uint64, err error) {
config := bc.Config()
msg, err := StakingToMessage(tx, header.Number())
if err != nil {
return nil, 0, err

@ -40,10 +40,6 @@ type Validator interface {
// via the VerifySeal method.
ValidateHeader(block *types.Block, seal bool) error
// ValidateHeaders verifies a batch of blocks' headers concurrently. The method returns a quit channel
// to abort the operations and a results channel to retrieve the async verifications
ValidateHeaders(chain []*types.Block) (chan<- struct{}, <-chan error)
// ValidateCXReceiptsProof checks whether the given CXReceiptsProof is consistency with itself
ValidateCXReceiptsProof(cxp *types.CXReceiptsProof) error
}

@ -375,7 +375,7 @@ func (node *Node) AddPendingReceipts(receipts *types.CXReceiptsProof) {
// Sanity checks
if err := node.Blockchain().Validator().ValidateCXReceiptsProof(receipts); err != nil {
if err := core.NewBlockValidator(node.Blockchain()).ValidateCXReceiptsProof(receipts); err != nil {
if !strings.Contains(err.Error(), rawdb.MsgNoShardStateFromDB) {
utils.Logger().Error().Err(err).Msg("[AddPendingReceipts] Invalid CXReceiptsProof")
return
@ -1108,7 +1108,7 @@ func New(
node.TxPool = core.NewTxPool(txPoolConfig, node.Blockchain().Config(), blockchain, node.TransactionErrorSink)
node.registry.SetTxPool(node.TxPool)
node.CxPool = node.registry.GetCxPool()
node.Worker = worker.New(node.Blockchain().Config(), blockchain, beaconChain, engine)
node.Worker = worker.New(blockchain, beaconChain)
node.deciderCache, _ = lru.New(16)
node.committeeCache, _ = lru.New(16)

@ -7,6 +7,7 @@ import (
"time"
"github.com/harmony-one/harmony/consensus"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/crypto/bls"
staking "github.com/harmony-one/harmony/staking/types"
@ -286,7 +287,7 @@ func (node *Node) ProposeNewBlock(commitSigs chan []byte) (*types.Block, error)
return nil, err
}
utils.Logger().Info().Msg("[ProposeNewBlock] verifying the new block header")
err = node.Blockchain().Validator().ValidateHeader(finalizedBlock, true)
err = core.NewBlockValidator(node.Blockchain()).ValidateHeader(finalizedBlock, true)
if err != nil {
utils.Logger().Error().Err(err).Msg("[ProposeNewBlock] Failed verifying the new block header")
@ -353,7 +354,7 @@ Loop:
}
}
if err := node.Blockchain().Validator().ValidateCXReceiptsProof(cxp); err != nil {
if err := core.NewBlockValidator(node.Blockchain()).ValidateCXReceiptsProof(cxp); err != nil {
if strings.Contains(err.Error(), rawdb.MsgNoShardStateFromDB) {
pendingReceiptsList = append(pendingReceiptsList, cxp)
} else {

@ -19,7 +19,6 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/harmony/block"
blockfactory "github.com/harmony-one/harmony/block/factory"
consensus_engine "github.com/harmony-one/harmony/consensus/engine"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types"
@ -59,7 +58,6 @@ type Worker struct {
chain core.BlockChain
beacon core.BlockChain
current *environment // An environment for current running cycle.
engine consensus_engine.Engine
gasFloor uint64
gasCeil uint64
}
@ -96,7 +94,7 @@ func (w *Worker) CommitSortedTransactions(
from, _ := types.Sender(signer, tx)
// Check whether the tx is replay protected. If we're not in the EIP155 hf
// phase, start ignoring the sender until we do.
if tx.Protected() && !w.config.IsEIP155(w.current.header.Epoch()) {
if tx.Protected() && !w.chain.Config().IsEIP155(w.current.header.Epoch()) {
utils.Logger().Info().Str("hash", tx.Hash().Hex()).Str("eip155Epoch", w.config.EIP155Epoch.String()).Msg("Ignoring reply protected transaction")
txs.Pop()
continue
@ -202,7 +200,7 @@ func (w *Worker) commitStakingTransaction(
snap := w.current.state.Snapshot()
gasUsed := w.current.header.GasUsed()
receipt, _, err := core.ApplyStakingTransaction(
w.config, w.chain, &coinbase, w.current.gasPool,
w.chain, &coinbase, w.current.gasPool,
w.current.state, w.current.header, tx, &gasUsed, vm.Config{},
)
w.current.header.SetGasUsed(gasUsed)
@ -239,7 +237,6 @@ func (w *Worker) commitTransaction(
snap := w.current.state.Snapshot()
gasUsed := w.current.header.GasUsed()
receipt, cx, stakeMsgs, _, err := core.ApplyTransaction(
w.config,
w.chain,
&coinbase,
w.current.gasPool,
@ -558,7 +555,7 @@ func (w *Worker) FinalizeNewBlock(
}
}()
block, payout, err := w.engine.Finalize(
block, payout, err := w.chain.Engine().Finalize(
w.chain,
w.beacon,
copyHeader, state, w.current.txs, w.current.receipts,
@ -574,14 +571,13 @@ func (w *Worker) FinalizeNewBlock(
// New create a new worker object.
func New(
config *params.ChainConfig, chain core.BlockChain, beacon core.BlockChain, engine consensus_engine.Engine,
chain core.BlockChain, beacon core.BlockChain,
) *Worker {
worker := &Worker{
config: config,
factory: blockfactory.NewFactory(config),
config: chain.Config(),
factory: blockfactory.NewFactory(chain.Config()),
chain: chain,
beacon: beacon,
engine: engine,
}
worker.gasFloor = 80000000
worker.gasCeil = 120000000

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

@ -102,7 +102,7 @@ func (b *BlockGen) AddTxWithChain(bc core.BlockChain, tx *types.Transaction) {
b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs))
coinbase := b.header.Coinbase()
gasUsed := b.header.GasUsed()
receipt, _, _, _, err := core.ApplyTransaction(b.config, bc, &coinbase, b.gasPool, b.statedb, b.header, tx, &gasUsed, vm.Config{})
receipt, _, _, _, err := core.ApplyTransaction(bc, &coinbase, b.gasPool, b.statedb, b.header, tx, &gasUsed, vm.Config{})
b.header.SetGasUsed(gasUsed)
b.header.SetCoinbase(coinbase)
if err != nil {

@ -93,7 +93,7 @@ func fundFaucetContract(chain core.BlockChain) {
fmt.Println("--------- Funding addresses for Faucet Contract Call ---------")
fmt.Println()
contractworker = pkgworker.New(params.TestChainConfig, chain, nil, chain.Engine())
contractworker = pkgworker.New(chain, nil)
nonce = contractworker.GetCurrentState().GetNonce(crypto.PubkeyToAddress(FaucetPriKey.PublicKey))
dataEnc = common.FromHex(FaucetContractBinary)
ftx, _ := types.SignTx(

Loading…
Cancel
Save