Skip to content

Commit

Permalink
core/types: use ParentBeaconRoot to represent milliseconds
Browse files Browse the repository at this point in the history
  • Loading branch information
buddh0 committed Jan 23, 2025
1 parent fde4dd5 commit 085051b
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 19 deletions.
2 changes: 1 addition & 1 deletion common/bidutil/bidutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func BidBetterBefore(parentHeader *types.Header, blockPeriod uint64, delayLeftOv
// BidMustBefore returns the time when the next bid must be received,
// only considering the consensus delay but not bid simulation duration.
func BidMustBefore(parentHeader *types.Header, blockPeriod uint64, delayLeftOver time.Duration) time.Time {
nextHeaderTime := time.UnixMilli(int64(parentHeader.TimeInMilliseconds() + blockPeriod))
nextHeaderTime := time.UnixMilli(int64(parentHeader.TimeWithMilliseconds() + blockPeriod))
nextHeaderTime = nextHeaderTime.Add(-delayLeftOver)
return nextHeaderTime
}
26 changes: 21 additions & 5 deletions consensus/parlia/parlia.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const (
checkpointInterval = 1024 // Number of blocks after which to save the snapshot to the database
defaultEpochLength = uint64(200) // Default number of blocks of checkpoint to update validatorSet from contract
defaultBlockInterval = uint16(3000) // Default block interval in milliseconds
lorentzBlockInterval = uint16(800) // Block interval starting from the Lorentz hard fork
defaultTurnLength = uint8(1) // Default consecutive number of blocks a validator receives priority for block production

extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
Expand Down Expand Up @@ -637,8 +638,18 @@ func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
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)
if header.ParentBeaconRoot == nil {
return fmt.Errorf("nil parentBeaconRoot after bohr hard fork")
}
lorentz := chain.Config().IsLorentz(header.Number, header.Time)
if !lorentz {
if *header.ParentBeaconRoot != (common.Hash{}) { // remove it once bsc mainnet passed lorentz hard fork for simplicity
return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected zero hash", header.ParentBeaconRoot)
}
} else {
if header.Milliseconds() >= 1000 {
return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected the last two bytes to represent milliseconds", header.ParentBeaconRoot)
}
}
}

Expand Down Expand Up @@ -776,6 +787,10 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash
// new snapshot
snap = newSnapshot(p.config, p.signatures, number, blockHash, validators, voteAddrs, p.ethAPI)

if p.chainConfig.IsLorentz(checkpoint.Number, checkpoint.Time) {
snap.BlockInterval = lorentzBlockInterval
}

// get turnLength from headers and use that for new turnLength
turnLength, err := parseTurnLength(checkpoint, p.chainConfig, p.config)
if err != nil {
Expand Down Expand Up @@ -1091,10 +1106,11 @@ func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header
if parent == nil {
return consensus.ErrUnknownAncestor
}
header.Time = uint64(p.blockTimeForRamanujanFork(snap, header, parent).Seconds())
if header.Time < uint64(time.Now().Unix()) {
header.Time = uint64(time.Now().Unix())
blockTime := p.blockTimeForRamanujanFork(snap, header, parent)
if now := uint64(time.Now().UnixMilli()); blockTime < now {
blockTime = now
}
header.SetTime(blockTime, p.chainConfig.IsLorentz(header.Number, header.Time))

header.Extra = header.Extra[:extraVanity-nextForkHashSize]
nextForkHash := forkid.NextForkHash(p.chainConfig, p.genesisHash, chain.GenesisHeader().Time, number, header.Time)
Expand Down
8 changes: 4 additions & 4 deletions consensus/parlia/ramanujanfork.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,17 @@ func (p *Parlia) delayForRamanujanFork(snap *Snapshot, header *types.Header) tim
return delay
}

func (p *Parlia) blockTimeForRamanujanFork(snap *Snapshot, header, parent *types.Header) time.Duration {
blockTime := parent.TimeInMilliseconds() + uint64(snap.BlockInterval)
func (p *Parlia) blockTimeForRamanujanFork(snap *Snapshot, header, parent *types.Header) uint64 {
blockTime := parent.TimeWithMilliseconds() + uint64(snap.BlockInterval)
if p.chainConfig.IsRamanujan(header.Number) {
blockTime = blockTime + p.backOffTime(snap, header, p.val)
}
return time.Duration(blockTime) * time.Millisecond
return blockTime
}

func (p *Parlia) blockTimeVerifyForRamanujanFork(snap *Snapshot, header, parent *types.Header) error {
if p.chainConfig.IsRamanujan(header.Number) {
if header.TimeInMilliseconds() < parent.TimeInMilliseconds()+uint64(snap.BlockInterval)+p.backOffTime(snap, header, header.Coinbase) {
if header.TimeWithMilliseconds() < parent.TimeWithMilliseconds()+uint64(snap.BlockInterval)+p.backOffTime(snap, header, header.Coinbase) {
return consensus.ErrFutureBlock
}
}
Expand Down
2 changes: 1 addition & 1 deletion consensus/parlia/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea
}
// It's better to set it based on IsOnLorentz, but in practice, the effect is the same as using IsLorentz.
if chainConfig.IsLorentz(header.Number, header.Time) {
s.BlockInterval = 800
s.BlockInterval = lorentzBlockInterval
}
snap.Recents[number] = validator
snap.RecentForkHashes[number] = hex.EncodeToString(header.Extra[extraVanity-nextForkHashSize : extraVanity])
Expand Down
2 changes: 1 addition & 1 deletion core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engi
header.ParentBeaconRoot = new(common.Hash)
} else {
header.WithdrawalsHash = &types.EmptyWithdrawalsHash
if cm.config.IsBohr(header.Number, header.Time) {
if cm.config.IsBohr(header.Number, header.Time) && !cm.config.IsLorentz(header.Number, header.Time) {
header.ParentBeaconRoot = new(common.Hash)
}
if cm.config.IsPrague(header.Number, header.Time) {
Expand Down
2 changes: 1 addition & 1 deletion core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *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 || conf.IsBohr(num, g.Timestamp) {
if conf.Parlia == nil || conf.IsBohr(num, g.Timestamp) && !conf.IsLorentz(num, g.Timestamp) {
head.ParentBeaconRoot = new(common.Hash)
}

Expand Down
21 changes: 19 additions & 2 deletions core/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import (

"golang.org/x/crypto/sha3"

"github.com/holiman/uint256"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rlp"
Expand Down Expand Up @@ -156,8 +158,23 @@ func (h *Header) Hash() common.Hash {
return rlpHash(h)
}

func (h *Header) TimeInMilliseconds() uint64 {
return h.Time * 1000
func (h *Header) Milliseconds() uint64 {
if h.ParentBeaconRoot == nil || *h.ParentBeaconRoot == (common.Hash{}) {
return 0
}
return uint256.NewInt(0).SetBytes2(h.ParentBeaconRoot[30:]).Uint64()
}

func (h *Header) TimeWithMilliseconds() uint64 {
return h.Time*1000 + h.Milliseconds()
}

func (h *Header) SetTime(blockTime uint64, countMilliSeconds bool) {
h.Time = blockTime / 1000
if countMilliSeconds {
milliseconds := common.Hash(uint256.NewInt(blockTime % 1000).Bytes32())
h.ParentBeaconRoot = &milliseconds
}
}

var headerSize = common.StorageSize(reflect.TypeOf(Header{}).Size())
Expand Down
2 changes: 1 addition & 1 deletion core/vote/vote_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func (voteManager *VoteManager) loop() {
curHead := cHead.Header
parentHeader := voteManager.chain.GetHeaderByHash(curHead.ParentHash)
blockInterval, _ := voteManager.engine.BlockInterval(voteManager.chain, parentHeader)
nextBlockMinedTime := time.UnixMilli(int64((curHead.TimeInMilliseconds() + blockInterval)))
nextBlockMinedTime := time.UnixMilli(int64((curHead.TimeWithMilliseconds() + blockInterval)))
timeForBroadcast := 50 * time.Millisecond // enough to broadcast a vote
if time.Now().Add(timeForBroadcast).After(nextBlockMinedTime) {
log.Warn("too late to vote", "Head.Time(Second)", curHead.Time, "Now(Millisecond)", time.Now().UnixMilli())
Expand Down
2 changes: 1 addition & 1 deletion miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -1032,7 +1032,7 @@ func (w *worker) prepareWork(genParams *generateParams, witness bool) (*environm
header.ParentBeaconRoot = genParams.beaconRoot
} else {
header.WithdrawalsHash = &types.EmptyWithdrawalsHash
if w.chainConfig.IsBohr(header.Number, header.Time) {
if w.chainConfig.IsBohr(header.Number, header.Time) && !w.chainConfig.IsLorentz(header.Number, header.Time) {
header.ParentBeaconRoot = new(common.Hash)
}
if w.chainConfig.IsPrague(header.Number, header.Time) {
Expand Down
3 changes: 1 addition & 2 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -596,8 +596,7 @@ func (c CliqueConfig) String() string {

// ParliaConfig is the consensus engine configs for proof-of-staked-authority based sealing.
type ParliaConfig struct {
DeprecatedPeriod uint64 `json:"period"` // Number of milliseconds between blocks to enforce; deprecated, existed just for load old `ParliaConfig` from disk
Epoch uint64 `json:"epoch"` // Epoch length to update validatorSet
Epoch uint64 `json:"epoch"` // Epoch length to update validatorSet
}

// String implements the stringer interface, returning the consensus engine details.
Expand Down

0 comments on commit 085051b

Please sign in to comment.