diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 6908ffeba1..7cfe63be2a 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -215,6 +215,8 @@ func activePrecompiledContracts(rules params.Rules) PrecompiledContracts { switch { case rules.IsUBT: return PrecompiledContractsVerkle + case rules.IsBogota: + return PrecompiledContractsOsaka case rules.IsOsaka: return PrecompiledContractsOsaka case rules.IsPrague: @@ -240,6 +242,8 @@ func ActivePrecompiledContracts(rules params.Rules) PrecompiledContracts { // ActivePrecompiles returns the precompile addresses enabled with the current configuration. func ActivePrecompiles(rules params.Rules) []common.Address { switch { + case rules.IsBogota: + return PrecompiledAddressesOsaka case rules.IsOsaka: return PrecompiledAddressesOsaka case rules.IsPrague: diff --git a/core/vm/evm.go b/core/vm/evm.go index 591663a8d9..18aa50a8c8 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -150,6 +150,8 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon evm.precompiles = activePrecompiledContracts(evm.chainRules) switch { + case evm.chainRules.IsBogota: + evm.table = &bogotaInstructionSet case evm.chainRules.IsAmsterdam: evm.table = &amsterdamInstructionSet case evm.chainRules.IsOsaka: diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 6b931083fe..d92b42aaa5 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -68,6 +68,7 @@ var ( pragueInstructionSet = newPragueInstructionSet() osakaInstructionSet = newOsakaInstructionSet() amsterdamInstructionSet = newAmsterdamInstructionSet() + bogotaInstructionSet = newBogotaInstructionSet() ) // JumpTable contains the EVM opcodes supported at a given fork. @@ -91,6 +92,11 @@ func validate(jt JumpTable) JumpTable { return jt } +func newBogotaInstructionSet() JumpTable { + instructionSet := newOsakaInstructionSet() + return validate(instructionSet) +} + func newVerkleInstructionSet() JumpTable { instructionSet := newShanghaiInstructionSet() enable4762(&instructionSet) diff --git a/core/vm/jump_table_export.go b/core/vm/jump_table_export.go index a4a99ea498..2c4ce0ae8b 100644 --- a/core/vm/jump_table_export.go +++ b/core/vm/jump_table_export.go @@ -28,6 +28,8 @@ func LookupInstructionSet(rules params.Rules) (JumpTable, error) { switch { case rules.IsUBT: return newCancunInstructionSet(), errors.New("verkle-fork not defined yet") + case rules.IsBogota: + return newBogotaInstructionSet(), nil case rules.IsAmsterdam: return newAmsterdamInstructionSet(), nil case rules.IsOsaka: diff --git a/eth/catalyst/witness.go b/eth/catalyst/witness.go index 05bcbbd81f..c0137ae8cc 100644 --- a/eth/catalyst/witness.go +++ b/eth/catalyst/witness.go @@ -74,7 +74,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV3(ctx context.Context, upd return engine.STATUS_INVALID, attributesErr("missing withdrawals") case params.BeaconRoot == nil: return engine.STATUS_INVALID, attributesErr("missing beacon root") - case !api.checkFork(params.Timestamp, forks.Cancun, forks.Prague, forks.Osaka, forks.BPO1, forks.BPO2, forks.BPO3, forks.BPO4, forks.BPO5): + case !api.checkFork(params.Timestamp, forks.Cancun, forks.Prague, forks.Osaka, forks.BPO1, forks.BPO2, forks.BPO3, forks.BPO4, forks.BPO5, forks.Bogota): return engine.STATUS_INVALID, unsupportedForkErr("fcuV3 must only be called for cancun/prague/osaka payloads") } } @@ -152,7 +152,7 @@ func (api *ConsensusAPI) NewPayloadWithWitnessV4(ctx context.Context, params eng return invalidStatus, paramsErr("nil beaconRoot post-cancun") case executionRequests == nil: return invalidStatus, paramsErr("nil executionRequests post-prague") - case !api.checkFork(params.Timestamp, forks.Prague, forks.Osaka, forks.BPO1, forks.BPO2, forks.BPO3, forks.BPO4, forks.BPO5): + case !api.checkFork(params.Timestamp, forks.Prague, forks.Osaka, forks.BPO1, forks.BPO2, forks.BPO3, forks.BPO4, forks.BPO5, forks.Bogota): return invalidStatus, unsupportedForkErr("newPayloadV4 must only be called for prague/osaka payloads") } requests := convertRequests(executionRequests) @@ -259,7 +259,7 @@ func (api *ConsensusAPI) ExecuteStatelessPayloadV4(params engine.ExecutableData, return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil beaconRoot post-cancun") case executionRequests == nil: return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil executionRequests post-prague") - case !api.checkFork(params.Timestamp, forks.Prague, forks.Osaka, forks.BPO1, forks.BPO2, forks.BPO3, forks.BPO4, forks.BPO5): + case !api.checkFork(params.Timestamp, forks.Prague, forks.Osaka, forks.BPO1, forks.BPO2, forks.BPO3, forks.BPO4, forks.BPO5, forks.Bogota): return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, unsupportedForkErr("newPayloadV4 must only be called for prague/osaka payloads") } requests := convertRequests(executionRequests) diff --git a/params/config.go b/params/config.go index 7b4493609f..85c3ae401f 100644 --- a/params/config.go +++ b/params/config.go @@ -64,6 +64,7 @@ var ( OsakaTime: newUint64(1764798551), BPO1Time: newUint64(1765290071), BPO2Time: newUint64(1767747671), + BogotaTime: nil, DepositContractAddress: common.HexToAddress("0x00000000219ab540356cbb839cbe05303d7705fa"), Ethash: new(EthashConfig), BlobScheduleConfig: &BlobScheduleConfig{ @@ -99,6 +100,7 @@ var ( OsakaTime: newUint64(1759308480), BPO1Time: newUint64(1759800000), BPO2Time: newUint64(1760389824), + BogotaTime: nil, DepositContractAddress: common.HexToAddress("0x4242424242424242424242424242424242424242"), Ethash: new(EthashConfig), BlobScheduleConfig: &BlobScheduleConfig{ @@ -134,6 +136,7 @@ var ( OsakaTime: newUint64(1760427360), BPO1Time: newUint64(1761017184), BPO2Time: newUint64(1761607008), + BogotaTime: nil, DepositContractAddress: common.HexToAddress("0x7f02c3e3c98b133055b8b348b2ac625669ed295d"), Ethash: new(EthashConfig), BlobScheduleConfig: &BlobScheduleConfig{ @@ -169,6 +172,7 @@ var ( OsakaTime: newUint64(1761677592), BPO1Time: newUint64(1762365720), BPO2Time: newUint64(1762955544), + BogotaTime: nil, DepositContractAddress: common.HexToAddress("0x00000000219ab540356cBB839Cbe05303d7705Fa"), Ethash: new(EthashConfig), BlobScheduleConfig: &BlobScheduleConfig{ @@ -203,6 +207,7 @@ var ( CancunTime: nil, PragueTime: nil, OsakaTime: nil, + BogotaTime: nil, UBTTime: nil, Ethash: new(EthashConfig), Clique: nil, @@ -228,6 +233,7 @@ var ( TerminalTotalDifficulty: big.NewInt(0), PragueTime: newUint64(0), OsakaTime: newUint64(0), + BogotaTime: newUint64(0), BlobScheduleConfig: &BlobScheduleConfig{ Cancun: DefaultCancunBlobConfig, Prague: DefaultPragueBlobConfig, @@ -258,6 +264,7 @@ var ( CancunTime: nil, PragueTime: nil, OsakaTime: nil, + BogotaTime: nil, UBTTime: nil, TerminalTotalDifficulty: big.NewInt(math.MaxInt64), Ethash: nil, @@ -288,6 +295,7 @@ var ( CancunTime: nil, PragueTime: nil, OsakaTime: nil, + BogotaTime: nil, UBTTime: nil, TerminalTotalDifficulty: big.NewInt(math.MaxInt64), Ethash: new(EthashConfig), @@ -318,6 +326,7 @@ var ( CancunTime: newUint64(0), PragueTime: newUint64(0), OsakaTime: newUint64(0), + BogotaTime: nil, UBTTime: nil, TerminalTotalDifficulty: big.NewInt(0), Ethash: new(EthashConfig), @@ -352,6 +361,7 @@ var ( CancunTime: nil, PragueTime: nil, OsakaTime: nil, + BogotaTime: nil, UBTTime: nil, TerminalTotalDifficulty: big.NewInt(math.MaxInt64), Ethash: new(EthashConfig), @@ -453,6 +463,7 @@ type ChainConfig struct { BPO4Time *uint64 `json:"bpo4Time,omitempty"` // BPO4 switch time (nil = no fork, 0 = already on bpo4) BPO5Time *uint64 `json:"bpo5Time,omitempty"` // BPO5 switch time (nil = no fork, 0 = already on bpo5) AmsterdamTime *uint64 `json:"amsterdamTime,omitempty"` // Amsterdam switch time (nil = no fork, 0 = already on amsterdam) + BogotaTime *uint64 `json:"bogotaTime,omitempty"` // Bogota switch time (nil = no fork, 0 = already on bogota) UBTTime *uint64 `json:"ubtTime,omitempty"` // UBT switch time (nil = no fork, 0 = already on UBT) // TerminalTotalDifficulty is the amount of total difficulty reached by @@ -582,6 +593,9 @@ func (c *ChainConfig) String() string { if c.AmsterdamTime != nil { result += fmt.Sprintf(", AmsterdamTime: %v", *c.AmsterdamTime) } + if c.BogotaTime != nil { + result += fmt.Sprintf(", BogotaTime: %v", *c.BogotaTime) + } if c.UBTTime != nil { result += fmt.Sprintf(", UBTTime: %v", *c.UBTTime) } @@ -677,6 +691,9 @@ func (c *ChainConfig) Description() string { if c.AmsterdamTime != nil { banner += fmt.Sprintf(" - Amsterdam: @%-10v\n", *c.AmsterdamTime) } + if c.BogotaTime != nil { + banner += fmt.Sprintf(" - Bogota: @%-10v\n", *c.BogotaTime) + } if c.UBTTime != nil { banner += fmt.Sprintf(" - UBT: @%-10v\n", *c.UBTTime) } @@ -854,6 +871,11 @@ func (c *ChainConfig) IsAmsterdam(num *big.Int, time uint64) bool { return c.IsLondon(num) && isTimestampForked(c.AmsterdamTime, time) } +// IsBogota returns whether time is either equal to the Bogota fork time or greater. +func (c *ChainConfig) IsBogota(num *big.Int, time uint64) bool { + return c.IsLondon(num) && isTimestampForked(c.BogotaTime, time) +} + // IsUBT returns whether time is either equal to the Verkle fork time or greater. func (c *ChainConfig) IsUBT(num *big.Int, time uint64) bool { return c.IsLondon(num) && isTimestampForked(c.UBTTime, time) @@ -940,6 +962,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error { {name: "bpo4", timestamp: c.BPO4Time, optional: true}, {name: "bpo5", timestamp: c.BPO5Time, optional: true}, {name: "amsterdam", timestamp: c.AmsterdamTime, optional: true}, + {name: "bogota", timestamp: c.BogotaTime, optional: true}, } { if lastFork.name != "" { switch { @@ -1111,6 +1134,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int, if isForkTimestampIncompatible(c.AmsterdamTime, newcfg.AmsterdamTime, headTimestamp) { return newTimestampCompatError("Amsterdam fork timestamp", c.AmsterdamTime, newcfg.AmsterdamTime) } + if isForkTimestampIncompatible(c.BogotaTime, newcfg.BogotaTime, headTimestamp) { + return newTimestampCompatError("Bogota fork timestamp", c.BogotaTime, newcfg.BogotaTime) + } return nil } @@ -1130,6 +1156,8 @@ func (c *ChainConfig) LatestFork(time uint64) forks.Fork { london := c.LondonBlock switch { + case c.IsBogota(london, time): + return forks.Bogota case c.IsAmsterdam(london, time): return forks.Amsterdam case c.IsBPO5(london, time): @@ -1213,6 +1241,10 @@ func (c *ChainConfig) ActiveSystemContracts(time uint64) map[string]common.Addre // the fork isn't defined or isn't a time-based fork. func (c *ChainConfig) Timestamp(fork forks.Fork) *uint64 { switch { + case fork == forks.Bogota: + return c.BogotaTime + case fork == forks.Amsterdam: + return c.AmsterdamTime case fork == forks.BPO5: return c.BPO5Time case fork == forks.BPO4: @@ -1231,8 +1263,6 @@ func (c *ChainConfig) Timestamp(fork forks.Fork) *uint64 { return c.CancunTime case fork == forks.Shanghai: return c.ShanghaiTime - case fork == forks.Amsterdam: - return c.AmsterdamTime default: return nil } @@ -1378,7 +1408,7 @@ type Rules struct { IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool IsBerlin, IsLondon bool IsMerge, IsShanghai, IsCancun, IsPrague, IsOsaka bool - IsAmsterdam, IsUBT bool + IsAmsterdam, IsBogota, IsUBT bool } // Rules ensures c's ChainID is not nil. @@ -1404,6 +1434,7 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules IsPrague: isMerge && c.IsPrague(num, timestamp), IsOsaka: isMerge && c.IsOsaka(num, timestamp), IsAmsterdam: isMerge && c.IsAmsterdam(num, timestamp), + IsBogota: isMerge && c.IsBogota(num, timestamp), IsUBT: isUBT, IsEIP4762: isUBT, } diff --git a/params/forks/forks.go b/params/forks/forks.go index 641d59434b..8308d15fbf 100644 --- a/params/forks/forks.go +++ b/params/forks/forks.go @@ -46,6 +46,7 @@ const ( BPO4 BPO5 Amsterdam + Bogota ) // String implements fmt.Stringer. @@ -84,4 +85,5 @@ var forkToString = map[Fork]string{ BPO4: "BPO4", BPO5: "BPO5", Amsterdam: "Amsterdam", + Bogota: "Bogota", }