diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 3c0e9a331f..358b45d59c 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -619,9 +619,43 @@ func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.H if header.ParentBeaconRoot != nil { return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot) } + if header.ParentRoot != nil { + return fmt.Errorf("invalid ParentRoot, have %#x, expected nil", header.ParentRoot) + } + if header.ParentReceiptHash != nil { + return fmt.Errorf("invalid ParentReceiptHash, have %#x, expected nil", header.ParentReceiptHash) + } + if header.ParentBloom != nil { + return fmt.Errorf("invalid ParentBloom, have %#x, expected nil", header.ParentBloom) + } + if header.ParentGasUsed != nil { + return fmt.Errorf("invalid ParentGasUsed, have %#x, expected nil", header.ParentGasUsed) + } } else { - if header.ParentBeaconRoot == nil || *header.ParentBeaconRoot != (common.Hash{}) { - return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected zero hash", header.ParentBeaconRoot) + if header.ParentBeaconRoot == nil { + return fmt.Errorf("invalid parentBeaconRoot, have nil, expected %s", common.Hash{}) + } else if *header.ParentBeaconRoot != (common.Hash{}) { + return fmt.Errorf("invalid parentBeaconRoot, have %s, expected %s", *header.ParentBeaconRoot, common.Hash{}) + } + if header.ParentRoot == nil { + return fmt.Errorf("invalid ParentRoot, have nil, expected %s", parent.Root) + } else if *header.ParentRoot != parent.Root { + return fmt.Errorf("invalid ParentRoot, have %s, expected %s", *header.ParentRoot, parent.Root) + } + if header.ParentReceiptHash == nil { + return fmt.Errorf("invalid ParentReceiptHash, have nil, expected %s", parent.ReceiptHash) + } else if *header.ParentRoot != parent.Root { + return fmt.Errorf("invalid ParentReceiptHash, have %s, expected %s", *header.ParentReceiptHash, parent.ReceiptHash) + } + if header.ParentBloom == nil { + return fmt.Errorf("invalid ParentBloom, have nil, expected %s", parent.Bloom) + } else if *header.ParentRoot != parent.Root { + return fmt.Errorf("invalid ParentBloom, have %s, expected %s", *header.ParentBloom, parent.Bloom) + } + if header.ParentGasUsed == nil { + return fmt.Errorf("invalid ParentGasUsed, have nil, expected %d", parent.GasUsed) + } else if *header.ParentGasUsed != parent.GasUsed { + return fmt.Errorf("invalid ParentGasUsed, have %d, expected %d", *header.ParentGasUsed, parent.GasUsed) } } diff --git a/core/blockchain.go b/core/blockchain.go index 25b9cbd7cb..dac91d3756 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -53,6 +53,7 @@ import ( "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/triedb" "github.com/ethereum/go-ethereum/triedb/hashdb" "github.com/ethereum/go-ethereum/triedb/pathdb" @@ -259,17 +260,18 @@ type BlockChain struct { triesInMemory uint64 txIndexer *txIndexer // Transaction indexer, might be nil if not enabled - hc *HeaderChain - rmLogsFeed event.Feed - chainFeed event.Feed - chainSideFeed event.Feed - chainHeadFeed event.Feed - chainBlockFeed event.Feed - logsFeed event.Feed - blockProcFeed event.Feed - finalizedHeaderFeed event.Feed - scope event.SubscriptionScope - genesisBlock *types.Block + hc *HeaderChain + rmLogsFeed event.Feed + chainFeed event.Feed + chainSideFeed event.Feed + chainHeadFeed event.Feed + chainBlockFeed event.Feed + logsFeed event.Feed + blockProcFeed event.Feed + finalizedHeaderFeed event.Feed + highestVerifiedHeaderFeed event.Feed + scope event.SubscriptionScope + genesisBlock *types.Block // This mutex synchronizes chain write operations. // Readers don't need to take it, they can just read the database. @@ -1962,6 +1964,7 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types } } if emitHeadEvent { + bc.highestVerifiedHeaderFeed.Send(HighestVerifiedHeaderEvent{Header: block.Header()}) bc.chainHeadFeed.Send(ChainHeadEvent{Block: block}) if finalizedHeader != nil { bc.finalizedHeaderFeed.Send(FinalizedHeaderEvent{finalizedHeader}) @@ -2266,11 +2269,21 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error) // Validate the state using the default validator vstart := time.Now() - if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil { - log.Error("validate state failed", "error", err) - bc.reportBlock(block, receipts, err) - statedb.StopPrefetcher() - return it.index, err + bohr := bc.chainConfig.IsBohr(block.Number(), block.Time()) + if !bohr { + if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil { + log.Error("validate state failed", "error", err) + bc.reportBlock(block, receipts, err) + statedb.StopPrefetcher() + return it.index, err + } + } else { + if err := bc.fillStateFields(block, statedb, receipts, usedGas); err != nil { + log.Error("fill state failed", "error", err) + bc.reportBlock(block, receipts, err) + statedb.StopPrefetcher() + return it.index, err + } } vtime := time.Since(vstart) proctime := time.Since(start) // processing + validation @@ -2391,6 +2404,7 @@ func (bc *BlockChain) updateHighestVerifiedHeader(header *types.Header) { reorg, err := bc.forker.ReorgNeededWithFastFinality(currentBlock, header) if err == nil && reorg { bc.highestVerifiedHeader.Store(types.CopyHeader(header)) + bc.highestVerifiedHeaderFeed.Send(HighestVerifiedHeaderEvent{Header: header}) log.Trace("updateHighestVerifiedHeader", "number", header.Number.Uint64(), "hash", header.Hash()) } } @@ -3253,3 +3267,57 @@ func (bc *BlockChain) SetTrieFlushInterval(interval time.Duration) { func (bc *BlockChain) GetTrieFlushInterval() time.Duration { return time.Duration(bc.flushInterval.Load()) } + +func (bc *BlockChain) fillStateFields(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error { + header := block.Header() + if block.GasUsed() != usedGas { + log.Error("invalid gasUsed", "remote", block.GasUsed(), "local", usedGas) + header.GasUsed = usedGas + } + CheckAndFillFuns := []func() error{ + func() error { + rbloom := types.CreateBloom(receipts) + if rbloom != header.Bloom { + log.Error("invalid logsBloom", "remote", header.Bloom, "local", rbloom) + header.Bloom = rbloom + } + return nil + }, + func() error { + receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil)) + if receiptSha != header.ReceiptHash { + log.Error("invalid receiptsRoot", "remote", header.ReceiptHash, "local", receiptSha) + header.ReceiptHash = receiptSha + } + return nil + }, + func() error { + if root := statedb.IntermediateRoot(bc.chainConfig.IsEIP158(header.Number)); header.Root != root { + if statedb.Error() != nil { + return fmt.Errorf("invalid stateRoott dberr: %w", statedb.Error()) + } else { + log.Error("invalid stateRoot", "remote", header.Root, "local", root) + header.Root = root + } + } + return nil + }, + } + + CheckAndFillRes := make(chan error, len(CheckAndFillFuns)) + for _, f := range CheckAndFillFuns { + tmpFunc := f + go func() { + CheckAndFillRes <- tmpFunc() + }() + } + + var err error + for i := 0; i < len(CheckAndFillFuns); i++ { + r := <-CheckAndFillRes + if r != nil && err == nil { + err = r + } + } + return err +} diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index d440590b8b..4445014b7d 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -92,6 +92,15 @@ func (bc *BlockChain) GetHeader(hash common.Hash, number uint64) *types.Header { return bc.hc.GetHeader(hash, number) } +// GetVerifiedHeaderByHash retrieves a verified block header, it may be only in memory. +func (bc *BlockChain) GetVerifiedHeaderByHash(hash common.Hash) *types.Header { + highestVerifiedHeader := bc.highestVerifiedHeader.Load() + if highestVerifiedHeader != nil && highestVerifiedHeader.Hash() == hash { + return highestVerifiedHeader + } + return bc.hc.GetHeaderByHash(hash) +} + // GetHeaderByHash retrieves a block header from the database by hash, caching it if // found. func (bc *BlockChain) GetHeaderByHash(hash common.Hash) *types.Header { @@ -486,6 +495,11 @@ func (bc *BlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Su return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch)) } +// SubscribeHighestVerifiedHeaderEvent registers a subscription of HighestVerifiedHeaderEvent. +func (bc *BlockChain) SubscribeHighestVerifiedHeaderEvent(ch chan<- HighestVerifiedHeaderEvent) event.Subscription { + return bc.scope.Track(bc.highestVerifiedHeaderFeed.Subscribe(ch)) +} + // SubscribeChainBlockEvent registers a subscription of ChainBlockEvent. func (bc *BlockChain) SubscribeChainBlockEvent(ch chan<- ChainHeadEvent) event.Subscription { return bc.scope.Track(bc.chainBlockFeed.Subscribe(ch)) diff --git a/core/chain_makers.go b/core/chain_makers.go index 3aff332aca..c9d777992a 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -488,6 +488,10 @@ func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engi } if cm.config.Parlia == nil || cm.config.IsBohr(header.Number, header.Time) { header.ParentBeaconRoot = new(common.Hash) + header.ParentRoot = &parent.Header().Root + header.ParentReceiptHash = &parent.Header().ReceiptHash + header.ParentBloom = &parent.Header().Bloom + header.ParentGasUsed = &parent.Header().GasUsed } } return header diff --git a/core/events.go b/core/events.go index ce8bcca744..e99b346105 100644 --- a/core/events.go +++ b/core/events.go @@ -50,3 +50,5 @@ type ChainSideEvent struct { } type ChainHeadEvent struct{ Block *types.Block } + +type HighestVerifiedHeaderEvent struct{ Header *types.Header } diff --git a/core/genesis.go b/core/genesis.go index 544d7104f4..dcaf29c72d 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -446,6 +446,10 @@ func (g *Genesis) ToBlock() *types.Block { // by definition. if conf.Parlia == nil || conf.IsBohr(num, g.Timestamp) { head.ParentBeaconRoot = new(common.Hash) + head.ParentRoot = nil + head.ParentReceiptHash = nil + head.ParentBloom = nil + head.ParentGasUsed = nil } // EIP-4844 fields diff --git a/core/types/block.go b/core/types/block.go index c7619f3f76..b878263b81 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -30,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" ) @@ -121,6 +122,11 @@ type Header struct { // ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers. ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` + + ParentRoot *common.Hash `json:"parentStateRoot" rlp:"optional"` + ParentReceiptHash *common.Hash `json:"parentReceiptsRoot" rlp:"optional"` + ParentBloom *Bloom `json:"parentLogsBloom" rlp:"optional"` + ParentGasUsed *uint64 `json:"parentGasUsed" rlp:"optional"` } // field type overrides for gencodec @@ -140,7 +146,7 @@ type headerMarshaling struct { // Hash returns the block hash of the header, which is simply the keccak256 hash of its // RLP encoding. func (h *Header) Hash() common.Hash { - return rlpHash(h) + return rlpForBlockHash(h) } var headerSize = common.StorageSize(reflect.TypeOf(Header{}).Size()) @@ -708,6 +714,10 @@ func EncodeSigHeader(w io.Writer, header *Header, chainId *big.Int) { header.BlobGasUsed, header.ExcessBlobGas, header.ParentBeaconRoot, + header.ParentRoot, + header.ParentReceiptHash, + header.ParentBloom, + header.ParentGasUsed, }) } else { err = rlp.Encode(w, []interface{}{ @@ -733,3 +743,41 @@ func EncodeSigHeader(w io.Writer, header *Header, chainId *big.Int) { panic("can't encode: " + err.Error()) } } + +func rlpForBlockHash(header *Header) (h common.Hash) { + if header.ParentBeaconRoot != nil && *header.ParentBeaconRoot == (common.Hash{}) { + sha := hasherPool.Get().(crypto.KeccakState) + defer hasherPool.Put(sha) + sha.Reset() + rlp.Encode(sha, []interface{}{ + header.ParentHash, + header.UncleHash, + header.Coinbase, + // header.Root, + header.TxHash, + // header.ReceiptHash, + // header.Bloom, + header.Difficulty, + header.Number, + header.GasLimit, + // header.GasUsed, + header.Time, + header.Extra, + header.MixDigest, + header.Nonce, + header.BaseFee, + header.WithdrawalsHash, + header.BlobGasUsed, + header.ExcessBlobGas, + header.ParentBeaconRoot, + header.ParentRoot, + header.ParentReceiptHash, + header.ParentBloom, + header.ParentGasUsed, + }) + sha.Read(h[:]) + return h + } else { + return rlpHash(header) + } +} diff --git a/core/types/gen_header_json.go b/core/types/gen_header_json.go index fb1f915d01..87719dd451 100644 --- a/core/types/gen_header_json.go +++ b/core/types/gen_header_json.go @@ -16,27 +16,31 @@ var _ = (*headerMarshaling)(nil) // MarshalJSON marshals as JSON. func (h Header) MarshalJSON() ([]byte, error) { type Header struct { - ParentHash common.Hash `json:"parentHash" gencodec:"required"` - UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` - Coinbase common.Address `json:"miner"` - Root common.Hash `json:"stateRoot" gencodec:"required"` - TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` - ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` - Bloom Bloom `json:"logsBloom" gencodec:"required"` - Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` - Number *hexutil.Big `json:"number" gencodec:"required"` - GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Time hexutil.Uint64 `json:"timestamp" gencodec:"required"` - Extra hexutil.Bytes `json:"extraData" gencodec:"required"` - MixDigest common.Hash `json:"mixHash"` - Nonce BlockNonce `json:"nonce"` - BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` - WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` - ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` - Hash common.Hash `json:"hash"` + ParentHash common.Hash `json:"parentHash" gencodec:"required"` + UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` + Coinbase common.Address `json:"miner"` + Root common.Hash `json:"stateRoot" gencodec:"required"` + TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` + ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` + Bloom Bloom `json:"logsBloom" gencodec:"required"` + Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` + Number *hexutil.Big `json:"number" gencodec:"required"` + GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` + GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + Time hexutil.Uint64 `json:"timestamp" gencodec:"required"` + Extra hexutil.Bytes `json:"extraData" gencodec:"required"` + MixDigest common.Hash `json:"mixHash"` + Nonce BlockNonce `json:"nonce"` + BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` + WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"` + ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` + ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` + ParentRoot *common.Hash `json:"parentStateRoot" rlp:"optional"` + ParentReceiptHash *common.Hash `json:"parentReceiptsRoot" rlp:"optional"` + ParentBloom *Bloom `json:"parentLogsBloom" rlp:"optional"` + ParentGasUsed *uint64 `json:"parentGasUsed" rlp:"optional"` + Hash common.Hash `json:"hash"` } var enc Header enc.ParentHash = h.ParentHash @@ -59,6 +63,10 @@ func (h Header) MarshalJSON() ([]byte, error) { enc.BlobGasUsed = (*hexutil.Uint64)(h.BlobGasUsed) enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas) enc.ParentBeaconRoot = h.ParentBeaconRoot + enc.ParentRoot = h.ParentRoot + enc.ParentReceiptHash = h.ParentReceiptHash + enc.ParentBloom = h.ParentBloom + enc.ParentGasUsed = h.ParentGasUsed enc.Hash = h.Hash() return json.Marshal(&enc) } @@ -66,26 +74,30 @@ func (h Header) MarshalJSON() ([]byte, error) { // UnmarshalJSON unmarshals from JSON. func (h *Header) UnmarshalJSON(input []byte) error { type Header struct { - ParentHash *common.Hash `json:"parentHash" gencodec:"required"` - UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"` - Coinbase *common.Address `json:"miner"` - Root *common.Hash `json:"stateRoot" gencodec:"required"` - TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"` - ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"` - Bloom *Bloom `json:"logsBloom" gencodec:"required"` - Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` - Number *hexutil.Big `json:"number" gencodec:"required"` - GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"` - Extra *hexutil.Bytes `json:"extraData" gencodec:"required"` - MixDigest *common.Hash `json:"mixHash"` - Nonce *BlockNonce `json:"nonce"` - BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` - WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` - ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` + ParentHash *common.Hash `json:"parentHash" gencodec:"required"` + UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"` + Coinbase *common.Address `json:"miner"` + Root *common.Hash `json:"stateRoot" gencodec:"required"` + TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"` + ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"` + Bloom *Bloom `json:"logsBloom" gencodec:"required"` + Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` + Number *hexutil.Big `json:"number" gencodec:"required"` + GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` + GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"` + Extra *hexutil.Bytes `json:"extraData" gencodec:"required"` + MixDigest *common.Hash `json:"mixHash"` + Nonce *BlockNonce `json:"nonce"` + BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` + WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"` + ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` + ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` + ParentRoot *common.Hash `json:"parentStateRoot" rlp:"optional"` + ParentReceiptHash *common.Hash `json:"parentReceiptsRoot" rlp:"optional"` + ParentBloom *Bloom `json:"parentLogsBloom" rlp:"optional"` + ParentGasUsed *uint64 `json:"parentGasUsed" rlp:"optional"` } var dec Header if err := json.Unmarshal(input, &dec); err != nil { @@ -163,5 +175,17 @@ func (h *Header) UnmarshalJSON(input []byte) error { if dec.ParentBeaconRoot != nil { h.ParentBeaconRoot = dec.ParentBeaconRoot } + if dec.ParentRoot != nil { + h.ParentRoot = dec.ParentRoot + } + if dec.ParentReceiptHash != nil { + h.ParentReceiptHash = dec.ParentReceiptHash + } + if dec.ParentBloom != nil { + h.ParentBloom = dec.ParentBloom + } + if dec.ParentGasUsed != nil { + h.ParentGasUsed = dec.ParentGasUsed + } return nil } diff --git a/core/types/gen_header_rlp.go b/core/types/gen_header_rlp.go index ed6a1a002c..137bf7b0d4 100644 --- a/core/types/gen_header_rlp.go +++ b/core/types/gen_header_rlp.go @@ -42,7 +42,11 @@ func (obj *Header) EncodeRLP(_w io.Writer) error { _tmp3 := obj.BlobGasUsed != nil _tmp4 := obj.ExcessBlobGas != nil _tmp5 := obj.ParentBeaconRoot != nil - if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 { + _tmp6 := obj.ParentRoot != nil + _tmp7 := obj.ParentReceiptHash != nil + _tmp8 := obj.ParentBloom != nil + _tmp9 := obj.ParentGasUsed != nil + if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 || _tmp8 || _tmp9 { if obj.BaseFee == nil { w.Write(rlp.EmptyString) } else { @@ -52,34 +56,62 @@ func (obj *Header) EncodeRLP(_w io.Writer) error { w.WriteBigInt(obj.BaseFee) } } - if _tmp2 || _tmp3 || _tmp4 || _tmp5 { + if _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 || _tmp8 || _tmp9 { if obj.WithdrawalsHash == nil { w.Write([]byte{0x80}) } else { w.WriteBytes(obj.WithdrawalsHash[:]) } } - if _tmp3 || _tmp4 || _tmp5 { + if _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 || _tmp8 || _tmp9 { if obj.BlobGasUsed == nil { w.Write([]byte{0x80}) } else { w.WriteUint64((*obj.BlobGasUsed)) } } - if _tmp4 || _tmp5 { + if _tmp4 || _tmp5 || _tmp6 || _tmp7 || _tmp8 || _tmp9 { if obj.ExcessBlobGas == nil { w.Write([]byte{0x80}) } else { w.WriteUint64((*obj.ExcessBlobGas)) } } - if _tmp5 { + if _tmp5 || _tmp6 || _tmp7 || _tmp8 || _tmp9 { if obj.ParentBeaconRoot == nil { w.Write([]byte{0x80}) } else { w.WriteBytes(obj.ParentBeaconRoot[:]) } } + if _tmp6 || _tmp7 || _tmp8 || _tmp9 { + if obj.ParentRoot == nil { + w.Write([]byte{0x80}) + } else { + w.WriteBytes(obj.ParentRoot[:]) + } + } + if _tmp7 || _tmp8 || _tmp9 { + if obj.ParentReceiptHash == nil { + w.Write([]byte{0x80}) + } else { + w.WriteBytes(obj.ParentReceiptHash[:]) + } + } + if _tmp8 || _tmp9 { + if obj.ParentBloom == nil { + w.Write([]byte{0x80}) + } else { + w.WriteBytes(obj.ParentBloom[:]) + } + } + if _tmp9 { + if obj.ParentGasUsed == nil { + w.Write([]byte{0x80}) + } else { + w.WriteUint64((*obj.ParentGasUsed)) + } + } w.ListEnd(_tmp0) return w.Flush() } diff --git a/core/vote/vote_manager.go b/core/vote/vote_manager.go index a7eaf10b09..10e338110e 100644 --- a/core/vote/vote_manager.go +++ b/core/vote/vote_manager.go @@ -31,8 +31,8 @@ type VoteManager struct { chain *core.BlockChain - chainHeadCh chan core.ChainHeadEvent - chainHeadSub event.Subscription + highestVerifiedHeaderCh chan core.HighestVerifiedHeaderEvent + highestVerifiedHeaderSub event.Subscription // used for backup validators to sync votes from corresponding mining validator syncVoteCh chan core.NewVoteEvent @@ -47,12 +47,12 @@ type VoteManager struct { func NewVoteManager(eth Backend, chain *core.BlockChain, pool *VotePool, journalPath, blsPasswordPath, blsWalletPath string, engine consensus.PoSA) (*VoteManager, error) { voteManager := &VoteManager{ - eth: eth, - chain: chain, - chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize), - syncVoteCh: make(chan core.NewVoteEvent, voteBufferForPut), - pool: pool, - engine: engine, + eth: eth, + chain: chain, + highestVerifiedHeaderCh: make(chan core.HighestVerifiedHeaderEvent, highestVerifiedHeaderChanSize), + syncVoteCh: make(chan core.NewVoteEvent, voteBufferForPut), + pool: pool, + engine: engine, } // Create voteSigner. @@ -72,7 +72,7 @@ func NewVoteManager(eth Backend, chain *core.BlockChain, pool *VotePool, journal voteManager.journal = voteJournal // Subscribe to chain head event. - voteManager.chainHeadSub = voteManager.chain.SubscribeChainHeadEvent(voteManager.chainHeadCh) + voteManager.highestVerifiedHeaderSub = voteManager.chain.SubscribeHighestVerifiedHeaderEvent(voteManager.highestVerifiedHeaderCh) voteManager.syncVoteSub = voteManager.pool.SubscribeNewVoteEvent(voteManager.syncVoteCh) go voteManager.loop() @@ -82,7 +82,7 @@ func NewVoteManager(eth Backend, chain *core.BlockChain, pool *VotePool, journal func (voteManager *VoteManager) loop() { log.Debug("vote manager routine loop started") - defer voteManager.chainHeadSub.Unsubscribe() + defer voteManager.highestVerifiedHeaderSub.Unsubscribe() defer voteManager.syncVoteSub.Unsubscribe() events := voteManager.eth.EventMux().Subscribe(downloader.StartEvent{}, downloader.DoneEvent{}, downloader.FailedEvent{}) @@ -117,7 +117,7 @@ func (voteManager *VoteManager) loop() { log.Debug("downloader is in DoneEvent mode, set the startVote flag to true") startVote = true } - case cHead := <-voteManager.chainHeadCh: + case cHead := <-voteManager.highestVerifiedHeaderCh: if !startVote { log.Debug("startVote flag is false, continue") continue @@ -133,12 +133,12 @@ func (voteManager *VoteManager) loop() { continue } - if cHead.Block == nil { - log.Debug("cHead.Block is nil, continue") + if cHead.Header == nil { + log.Debug("cHead.Header is nil, continue") continue } - curHead := cHead.Block.Header() + curHead := cHead.Header // Check if cur validator is within the validatorSet at curHead if !voteManager.engine.IsActiveValidatorAt(voteManager.chain, curHead, func(bLSPublicKey *types.BLSPublicKey) bool { @@ -206,7 +206,7 @@ func (voteManager *VoteManager) loop() { case <-voteManager.syncVoteSub.Err(): log.Debug("voteManager subscribed votes failed") return - case <-voteManager.chainHeadSub.Err(): + case <-voteManager.highestVerifiedHeaderSub.Err(): log.Debug("voteManager subscribed chainHead failed") return } diff --git a/core/vote/vote_pool.go b/core/vote/vote_pool.go index defa92674b..755cb86864 100644 --- a/core/vote/vote_pool.go +++ b/core/vote/vote_pool.go @@ -24,7 +24,7 @@ const ( lowerLimitOfVoteBlockNumber = 256 upperLimitOfVoteBlockNumber = 11 // refer to fetcher.maxUncleDist - chainHeadChanSize = 10 // chainHeadChanSize is the size of channel listening to ChainHeadEvent. + highestVerifiedHeaderChanSize = 10 // highestVerifiedHeaderChanSize is the size of channel listening to HighestVerifiedHeaderEvent. ) var ( @@ -57,8 +57,8 @@ type VotePool struct { curVotesPq *votesPriorityQueue futureVotesPq *votesPriorityQueue - chainHeadCh chan core.ChainHeadEvent - chainHeadSub event.Subscription + highestVerifiedHeaderCh chan core.HighestVerifiedHeaderEvent + highestVerifiedHeaderSub event.Subscription votesCh chan *types.VoteEnvelope @@ -69,19 +69,19 @@ type votesPriorityQueue []*types.VoteData func NewVotePool(chain *core.BlockChain, engine consensus.PoSA) *VotePool { votePool := &VotePool{ - chain: chain, - receivedVotes: mapset.NewSet[common.Hash](), - curVotes: make(map[common.Hash]*VoteBox), - futureVotes: make(map[common.Hash]*VoteBox), - curVotesPq: &votesPriorityQueue{}, - futureVotesPq: &votesPriorityQueue{}, - chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize), - votesCh: make(chan *types.VoteEnvelope, voteBufferForPut), - engine: engine, + chain: chain, + receivedVotes: mapset.NewSet[common.Hash](), + curVotes: make(map[common.Hash]*VoteBox), + futureVotes: make(map[common.Hash]*VoteBox), + curVotesPq: &votesPriorityQueue{}, + futureVotesPq: &votesPriorityQueue{}, + highestVerifiedHeaderCh: make(chan core.HighestVerifiedHeaderEvent, highestVerifiedHeaderChanSize), + votesCh: make(chan *types.VoteEnvelope, voteBufferForPut), + engine: engine, } // Subscribe events from blockchain and start the main event loop. - votePool.chainHeadSub = votePool.chain.SubscribeChainHeadEvent(votePool.chainHeadCh) + votePool.highestVerifiedHeaderSub = votePool.chain.SubscribeHighestVerifiedHeaderEvent(votePool.highestVerifiedHeaderCh) go votePool.loop() return votePool @@ -89,18 +89,18 @@ func NewVotePool(chain *core.BlockChain, engine consensus.PoSA) *VotePool { // loop is the vote pool's main even loop, waiting for and reacting to outside blockchain events and votes channel event. func (pool *VotePool) loop() { - defer pool.chainHeadSub.Unsubscribe() + defer pool.highestVerifiedHeaderSub.Unsubscribe() for { select { // Handle ChainHeadEvent. - case ev := <-pool.chainHeadCh: - if ev.Block != nil { - latestBlockNumber := ev.Block.NumberU64() + case ev := <-pool.highestVerifiedHeaderCh: + if ev.Header != nil { + latestBlockNumber := ev.Header.Number.Uint64() pool.prune(latestBlockNumber) - pool.transferVotesFromFutureToCur(ev.Block.Header()) + pool.transferVotesFromFutureToCur(ev.Header) } - case <-pool.chainHeadSub.Err(): + case <-pool.highestVerifiedHeaderSub.Err(): return // Handle votes channel and put the vote into vote pool. @@ -135,7 +135,7 @@ func (pool *VotePool) putIntoVotePool(vote *types.VoteEnvelope) bool { var votesPq *votesPriorityQueue isFutureVote := false - voteBlock := pool.chain.GetHeaderByHash(targetHash) + voteBlock := pool.chain.GetVerifiedHeaderByHash(targetHash) if voteBlock == nil { votes = pool.futureVotes votesPq = pool.futureVotesPq @@ -158,6 +158,7 @@ func (pool *VotePool) putIntoVotePool(vote *types.VoteEnvelope) bool { // Send vote for handler usage of broadcasting to peers. voteEv := core.NewVoteEvent{Vote: vote} + log.Trace("The vote info to send is:", "voteBlockNumber", targetNumber, "voteBlockHash", targetHash) pool.votesFeed.Send(voteEv) } @@ -226,7 +227,7 @@ func (pool *VotePool) transferVotesFromFutureToCur(latestBlockHeader *types.Head futurePqBuffer := make([]*types.VoteData, 0) for futurePq.Len() > 0 && futurePq.Peek().TargetNumber <= latestBlockNumber { blockHash := futurePq.Peek().TargetHash - header := pool.chain.GetHeaderByHash(blockHash) + header := pool.chain.GetVerifiedHeaderByHash(blockHash) if header == nil { // Put into pq buffer used for later put again into futurePq futurePqBuffer = append(futurePqBuffer, heap.Pop(futurePq).(*types.VoteData)) diff --git a/miner/worker.go b/miner/worker.go index 8f09819d7d..17c66c1f05 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -1034,6 +1034,10 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) { header.ParentBeaconRoot = genParams.beaconRoot } else if w.chainConfig.IsBohr(header.Number, header.Time) { header.ParentBeaconRoot = new(common.Hash) + header.ParentRoot = &parent.Root + header.ParentReceiptHash = &parent.ReceiptHash + header.ParentBloom = &parent.Bloom + header.ParentGasUsed = &parent.GasUsed } } // Could potentially happen if starting to mine in an odd state.