diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index fb4f0e0f9..d008678e0 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -6,6 +6,7 @@ import ( "encoding/hex" "errors" "fmt" + "io" "math" "math/big" "math/rand" @@ -604,15 +605,11 @@ func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.H return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas) case header.BlobGasUsed != nil: return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed) - case header.ParentBeaconRoot != nil: - return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot) case header.WithdrawalsHash != nil: return fmt.Errorf("invalid WithdrawalsHash, have %#x, expected nil", header.WithdrawalsHash) } } else { switch { - case header.ParentBeaconRoot != nil: - return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot) case !header.EmptyWithdrawalsHash(): return errors.New("header has wrong WithdrawalsHash") } @@ -621,6 +618,17 @@ func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.H } } + bohr := chain.Config().IsBohr(header.Number, header.Time) + if !bohr { + if header.ParentBeaconRoot != nil { + return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot) + } + } else { + if header.ParentBeaconRoot == nil || *header.ParentBeaconRoot != (common.Hash{}) { + return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected zero hash", header.ParentBeaconRoot) + } + } + // All basic checks passed, verify cascading fields return p.verifyCascadingFields(chain, header, parents) } @@ -1594,11 +1602,35 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int { return new(big.Int).Set(diffNoTurn) } +func encodeSigHeaderWithoutVoteAttestation(w io.Writer, header *types.Header, chainId *big.Int) { + err := rlp.Encode(w, []interface{}{ + chainId, + 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[:extraVanity], // this will panic if extra is too short, should check before calling encodeSigHeaderWithoutVoteAttestation + header.MixDigest, + header.Nonce, + }) + if err != nil { + panic("can't encode: " + err.Error()) + } +} + // SealHash returns the hash of a block without vote attestation prior to it being sealed. // So it's not the real hash of a block, just used as unique id to distinguish task func (p *Parlia) SealHash(header *types.Header) (hash common.Hash) { hasher := sha3.NewLegacyKeccak256() - types.EncodeSigHeaderWithoutVoteAttestation(hasher, header, p.chainConfig.ChainID) + encodeSigHeaderWithoutVoteAttestation(hasher, header, p.chainConfig.ChainID) hasher.Sum(hash[:0]) return hash } diff --git a/core/chain_makers.go b/core/chain_makers.go index a5edc32a6..29306c522 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -486,7 +486,7 @@ func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engi if cm.config.Parlia != nil { header.WithdrawalsHash = &types.EmptyWithdrawalsHash } - if cm.config.Parlia == nil { + if cm.config.Parlia == nil || cm.config.IsBohr(header.Number, header.Time) { header.ParentBeaconRoot = new(common.Hash) } } diff --git a/core/genesis.go b/core/genesis.go index 71787ce2b..544d7104f 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -444,7 +444,7 @@ func (g *Genesis) ToBlock() *types.Block { // EIP-4788: The parentBeaconBlockRoot of the genesis block is always // the zero hash. This is because the genesis block does not have a parent // by definition. - if conf.Parlia == nil { + if conf.Parlia == nil || conf.IsBohr(num, g.Timestamp) { head.ParentBeaconRoot = new(common.Hash) } diff --git a/core/types/block.go b/core/types/block.go index 422363b32..c7619f3f7 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -673,10 +673,7 @@ type DiffAccountsInBlock struct { Transactions []DiffAccountsInTx } -var ( - extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity - extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal -) +var extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal // SealHash returns the hash of a block prior to it being sealed. func SealHash(header *Header, chainId *big.Int) (hash common.Hash) { @@ -687,48 +684,51 @@ func SealHash(header *Header, chainId *big.Int) (hash common.Hash) { } func EncodeSigHeader(w io.Writer, header *Header, chainId *big.Int) { - err := rlp.Encode(w, []interface{}{ - chainId, - 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[:len(header.Extra)-extraSeal], // this will panic if extra is too short, should check before calling encodeSigHeader - header.MixDigest, - header.Nonce, - }) - if err != nil { - panic("can't encode: " + err.Error()) - } -} - -func EncodeSigHeaderWithoutVoteAttestation(w io.Writer, header *Header, chainId *big.Int) { - err := rlp.Encode(w, []interface{}{ - chainId, - 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[:extraVanity], // this will panic if extra is too short, should check before calling encodeSigHeaderWithoutVoteAttestation - header.MixDigest, - header.Nonce, - }) + var err error + if header.ParentBeaconRoot != nil && *header.ParentBeaconRoot == (common.Hash{}) { + err = rlp.Encode(w, []interface{}{ + chainId, + 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[:len(header.Extra)-extraSeal], // this will panic if extra is too short, should check before calling encodeSigHeader + header.MixDigest, + header.Nonce, + header.BaseFee, + header.WithdrawalsHash, + header.BlobGasUsed, + header.ExcessBlobGas, + header.ParentBeaconRoot, + }) + } else { + err = rlp.Encode(w, []interface{}{ + chainId, + 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[:len(header.Extra)-extraSeal], // this will panic if extra is too short, should check before calling encodeSigHeader + header.MixDigest, + header.Nonce, + }) + } if err != nil { panic("can't encode: " + err.Error()) } diff --git a/miner/worker.go b/miner/worker.go index 0a48d9035..c316c1271 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -1032,6 +1032,8 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) { } if w.chainConfig.Parlia == nil { header.ParentBeaconRoot = genParams.beaconRoot + } else if w.chainConfig.IsBohr(header.Number, header.Time) { + header.ParentBeaconRoot = new(common.Hash) } } // Could potentially happen if starting to mine in an odd state.