Skip to content

Commit 3644639

Browse files
Merge pull request 0xFacet#19 from 0xFacet/bluebird
Bluebird
2 parents 1868f54 + d9d3a25 commit 3644639

25 files changed

Lines changed: 929 additions & 89 deletions

cmd/geth/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,11 @@ func makeFullNode(ctx *cli.Context) *node.Node {
205205
cfg.Eth.OverrideOptimismInterop = &v
206206
}
207207

208+
if ctx.IsSet(utils.OverrideFacetBluebird.Name) {
209+
v := ctx.Uint64(utils.OverrideFacetBluebird.Name)
210+
cfg.Eth.OverrideFacetBluebird = &v
211+
}
212+
208213
if ctx.IsSet(utils.OverrideVerkle.Name) {
209214
v := ctx.Uint64(utils.OverrideVerkle.Name)
210215
cfg.Eth.OverrideVerkle = &v

cmd/geth/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ var (
7272
utils.OverrideOptimismGranite,
7373
utils.OverrideOptimismHolocene,
7474
utils.OverrideOptimismInterop,
75+
utils.OverrideFacetBluebird,
7576
utils.EnablePersonal,
7677
utils.TxPoolLocalsFlag,
7778
utils.TxPoolNoLocalsFlag,

cmd/utils/flags.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,11 @@ var (
294294
Usage: "Manually specify the Optimsim Interop feature-set fork timestamp, overriding the bundled setting",
295295
Category: flags.EthCategory,
296296
}
297+
OverrideFacetBluebird = &cli.Uint64Flag{
298+
Name: "override.bluebird",
299+
Usage: "Manually specify the Facet Bluebird fork timestamp, overriding the bundled setting",
300+
Category: flags.EthCategory,
301+
}
297302
SyncModeFlag = &flags.TextMarshalerFlag{
298303
Name: "syncmode",
299304
Usage: `Blockchain sync mode ("snap" or "full")`,
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
// Copyright 2024 The go-ethereum Authors
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package eip1559
18+
19+
import (
20+
"math/big"
21+
"testing"
22+
23+
"github.com/ethereum/go-ethereum/core/types"
24+
"github.com/ethereum/go-ethereum/params"
25+
)
26+
27+
func TestBluebirdEIP1559Parameters(t *testing.T) {
28+
// Create a config with Bluebird enabled at timestamp 1000
29+
bluebirdTime := uint64(1000)
30+
config := &params.ChainConfig{
31+
ChainID: big.NewInt(1),
32+
HomesteadBlock: big.NewInt(0),
33+
EIP150Block: big.NewInt(0),
34+
EIP155Block: big.NewInt(0),
35+
EIP158Block: big.NewInt(0),
36+
ByzantiumBlock: big.NewInt(0),
37+
ConstantinopleBlock: big.NewInt(0),
38+
PetersburgBlock: big.NewInt(0),
39+
IstanbulBlock: big.NewInt(0),
40+
MuirGlacierBlock: big.NewInt(0),
41+
BerlinBlock: big.NewInt(0),
42+
LondonBlock: big.NewInt(0),
43+
BluebirdTime: &bluebirdTime,
44+
}
45+
46+
// Test ElasticityMultiplier
47+
t.Run("ElasticityMultiplier", func(t *testing.T) {
48+
// Before Bluebird
49+
beforeTime := uint64(999)
50+
elasticity := config.ElasticityMultiplier(beforeTime)
51+
if elasticity != params.DefaultElasticityMultiplier {
52+
t.Errorf("Before Bluebird: expected elasticity %d, got %d", params.DefaultElasticityMultiplier, elasticity)
53+
}
54+
55+
// At Bluebird activation
56+
atTime := uint64(1000)
57+
elasticity = config.ElasticityMultiplier(atTime)
58+
if elasticity != params.BluebirdElasticityMultiplier {
59+
t.Errorf("At Bluebird: expected elasticity %d, got %d", params.BluebirdElasticityMultiplier, elasticity)
60+
}
61+
62+
// After Bluebird
63+
afterTime := uint64(1001)
64+
elasticity = config.ElasticityMultiplier(afterTime)
65+
if elasticity != params.BluebirdElasticityMultiplier {
66+
t.Errorf("After Bluebird: expected elasticity %d, got %d", params.BluebirdElasticityMultiplier, elasticity)
67+
}
68+
})
69+
70+
// Test BaseFeeChangeDenominator
71+
t.Run("BaseFeeChangeDenominator", func(t *testing.T) {
72+
// Before Bluebird
73+
beforeTime := uint64(999)
74+
denominator := config.BaseFeeChangeDenominator(beforeTime)
75+
if denominator != params.DefaultBaseFeeChangeDenominator {
76+
t.Errorf("Before Bluebird: expected denominator %d, got %d", params.DefaultBaseFeeChangeDenominator, denominator)
77+
}
78+
79+
// At Bluebird activation
80+
atTime := uint64(1000)
81+
denominator = config.BaseFeeChangeDenominator(atTime)
82+
if denominator != params.BluebirdBaseFeeChangeDenominator {
83+
t.Errorf("At Bluebird: expected denominator %d, got %d", params.BluebirdBaseFeeChangeDenominator, denominator)
84+
}
85+
86+
// After Bluebird
87+
afterTime := uint64(1001)
88+
denominator = config.BaseFeeChangeDenominator(afterTime)
89+
if denominator != params.BluebirdBaseFeeChangeDenominator {
90+
t.Errorf("After Bluebird: expected denominator %d, got %d", params.BluebirdBaseFeeChangeDenominator, denominator)
91+
}
92+
})
93+
94+
// Test minimum base fee enforcement
95+
t.Run("MinimumBaseFee", func(t *testing.T) {
96+
// Create a parent header with very low base fee
97+
parent := &types.Header{
98+
Number: big.NewInt(1),
99+
GasLimit: 30_000_000,
100+
GasUsed: 0, // No gas used, should decrease base fee
101+
BaseFee: big.NewInt(1000), // Very low base fee
102+
}
103+
104+
// Before Bluebird - base fee can go to near zero
105+
beforeTime := uint64(999)
106+
baseFee := CalcBaseFee(config, parent, beforeTime)
107+
if baseFee.Cmp(big.NewInt(0)) < 0 {
108+
t.Errorf("Base fee should never be negative, got %s", baseFee)
109+
}
110+
111+
// After Bluebird - base fee should respect minimum
112+
afterTime := uint64(1001)
113+
baseFee = CalcBaseFee(config, parent, afterTime)
114+
minBaseFee := new(big.Int).SetUint64(params.BluebirdMinBaseFee)
115+
if baseFee.Cmp(minBaseFee) < 0 {
116+
t.Errorf("After Bluebird: base fee %s is below minimum %s", baseFee, minBaseFee)
117+
}
118+
})
119+
120+
// Test base fee calculation with new parameters
121+
t.Run("BaseFeeCalculationWithNewParams", func(t *testing.T) {
122+
// Test with block at exactly the target gas usage
123+
parent := &types.Header{
124+
Number: big.NewInt(1),
125+
GasLimit: 30_000_000,
126+
GasUsed: 15_000_000, // At target for default elasticity of 2
127+
BaseFee: big.NewInt(1_000_000_000), // 1 gwei
128+
}
129+
130+
// Before Bluebird: gas used = target, so base fee unchanged
131+
beforeTime := uint64(999)
132+
baseFeeBeforeBluebird := CalcBaseFee(config, parent, beforeTime)
133+
if baseFeeBeforeBluebird.Cmp(parent.BaseFee) != 0 {
134+
t.Errorf("At target gas usage, base fee should remain unchanged")
135+
}
136+
137+
// After Bluebird: gas used > new target (7.5M), so base fee increases
138+
afterTime := uint64(1001)
139+
baseFeeAfterBluebird := CalcBaseFee(config, parent, afterTime)
140+
141+
t.Logf("Base fee before Bluebird: %s", baseFeeBeforeBluebird)
142+
t.Logf("Base fee after Bluebird: %s", baseFeeAfterBluebird)
143+
t.Logf("Gas target before Bluebird: %d", parent.GasLimit/params.DefaultElasticityMultiplier)
144+
t.Logf("Gas target after Bluebird: %d", parent.GasLimit/params.BluebirdElasticityMultiplier)
145+
146+
// After Bluebird, with higher elasticity, the same gas usage is now above target
147+
if baseFeeAfterBluebird.Cmp(parent.BaseFee) <= 0 {
148+
t.Errorf("After Bluebird, base fee should increase as gas usage is now above new target")
149+
}
150+
})
151+
152+
// Test that higher denominator makes changes more gradual
153+
t.Run("DenominatorMakesChangesGradual", func(t *testing.T) {
154+
parent := &types.Header{
155+
Number: big.NewInt(1),
156+
GasLimit: 30_000_000,
157+
GasUsed: 30_000_000, // Full block
158+
BaseFee: big.NewInt(1_000_000_000), // 1 gwei
159+
}
160+
161+
// Calculate base fee increase percentage before and after Bluebird
162+
beforeTime := uint64(999)
163+
baseFeeBeforeBluebird := CalcBaseFee(config, parent, beforeTime)
164+
percentIncreaseBeforeBluebird := new(big.Int).Sub(baseFeeBeforeBluebird, parent.BaseFee)
165+
percentIncreaseBeforeBluebird.Mul(percentIncreaseBeforeBluebird, big.NewInt(100))
166+
percentIncreaseBeforeBluebird.Div(percentIncreaseBeforeBluebird, parent.BaseFee)
167+
168+
afterTime := uint64(1001)
169+
baseFeeAfterBluebird := CalcBaseFee(config, parent, afterTime)
170+
percentIncreaseAfterBluebird := new(big.Int).Sub(baseFeeAfterBluebird, parent.BaseFee)
171+
percentIncreaseAfterBluebird.Mul(percentIncreaseAfterBluebird, big.NewInt(100))
172+
percentIncreaseAfterBluebird.Div(percentIncreaseAfterBluebird, parent.BaseFee)
173+
174+
t.Logf("Percent increase before Bluebird: %s%%", percentIncreaseBeforeBluebird)
175+
t.Logf("Percent increase after Bluebird: %s%%", percentIncreaseAfterBluebird)
176+
177+
// Both elasticity and denominator changes affect the calculation
178+
// The test should verify the parameters are applied correctly
179+
if config.ElasticityMultiplier(afterTime) != params.BluebirdElasticityMultiplier {
180+
t.Errorf("Elasticity multiplier not correctly applied")
181+
}
182+
if config.BaseFeeChangeDenominator(afterTime) != params.BluebirdBaseFeeChangeDenominator {
183+
t.Errorf("Base fee denominator not correctly applied")
184+
}
185+
})
186+
}

consensus/misc/eip1559/eip1559.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Heade
3535
// Verify that the gas limit remains within allowed bounds
3636
parentGasLimit := parent.GasLimit
3737
if !config.IsLondon(parent.Number) {
38-
parentGasLimit = parent.GasLimit * config.ElasticityMultiplier()
38+
parentGasLimit = parent.GasLimit * config.ElasticityMultiplier(header.Time)
3939
}
4040
if config.Optimism == nil { // gasLimit can adjust instantly in optimism
4141
if err := misc.VerifyGaslimit(parentGasLimit, header.GasLimit); err != nil {
@@ -63,7 +63,7 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header, time uint64)
6363
return new(big.Int).SetUint64(params.InitialBaseFee)
6464
}
6565

66-
parentGasTarget := parent.GasLimit / config.ElasticityMultiplier()
66+
parentGasTarget := parent.GasLimit / config.ElasticityMultiplier(time)
6767
// If the parent gasUsed is the same as the target, the baseFee remains unchanged.
6868
if parent.GasUsed == parentGasTarget {
6969
return new(big.Int).Set(parent.BaseFee)
@@ -93,6 +93,11 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header, time uint64)
9393
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator(time)))
9494
baseFee := num.Sub(parent.BaseFee, num)
9595

96-
return math.BigMax(baseFee, common.Big0)
96+
// Enforce minimum base fee for Bluebird
97+
minBaseFee := common.Big0
98+
if config.IsBluebird(time) {
99+
minBaseFee = new(big.Int).SetUint64(params.BluebirdMinBaseFee)
100+
}
101+
return math.BigMax(baseFee, minBaseFee)
97102
}
98103
}

core/chain_makers.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ func (b *BlockGen) AddUncle(h *types.Header) {
233233
if b.cm.config.IsLondon(h.Number) {
234234
h.BaseFee = eip1559.CalcBaseFee(b.cm.config, parent, h.Time)
235235
if !b.cm.config.IsLondon(parent.Number) {
236-
parentGasLimit := parent.GasLimit * b.cm.config.ElasticityMultiplier()
236+
parentGasLimit := parent.GasLimit * b.cm.config.ElasticityMultiplier(h.Time)
237237
h.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
238238
}
239239
}
@@ -540,7 +540,7 @@ func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engi
540540
if cm.config.IsLondon(header.Number) {
541541
header.BaseFee = eip1559.CalcBaseFee(cm.config, parent.Header(), header.Time)
542542
if !cm.config.IsLondon(parent.Number()) {
543-
parentGasLimit := parent.GasLimit() * cm.config.ElasticityMultiplier()
543+
parentGasLimit := parent.GasLimit() * cm.config.ElasticityMultiplier(header.Time)
544544
header.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
545545
}
546546
}

core/genesis.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ type ChainOverrides struct {
264264
OverrideOptimismGranite *uint64
265265
OverrideOptimismHolocene *uint64
266266
OverrideOptimismInterop *uint64
267+
OverrideFacetBluebird *uint64
267268
ApplySuperchainUpgrades bool
268269
}
269270

@@ -332,6 +333,9 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
332333
if overrides != nil && overrides.OverrideOptimismInterop != nil {
333334
config.InteropTime = overrides.OverrideOptimismInterop
334335
}
336+
if overrides != nil && overrides.OverrideFacetBluebird != nil {
337+
config.BluebirdTime = overrides.OverrideFacetBluebird
338+
}
335339
}
336340
}
337341
// Just commit the new block if there is no stored genesis block.

core/txpool/validation.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
7878
// No unauthenticated deposits allowed in the transaction pool.
7979
// This is for spam protection, not consensus,
8080
// as the external engine-API user authenticates deposits.
81-
if tx.Type() == types.DepositTxType {
81+
if tx.IsDepositTx() {
8282
return core.ErrTxTypeNotSupported
8383
}
8484
if opts.Config.IsOptimism() && tx.Type() == types.BlobTxType {

core/types/deposit_tx.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ import (
2424
"github.com/ethereum/go-ethereum/rlp"
2525
)
2626

27-
const DepositTxType = 0x7E
27+
const (
28+
DepositTxType = 0x7E // Legacy deposits (pre-Bluebird)
29+
DepositTxV2Type = 0x7D // Bluebird deposits (exclude Mint from hash)
30+
)
2831

2932
type DepositTx struct {
3033
// SourceHash uniquely identifies the source of the deposit

core/types/deposit_tx_v2.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2021 The go-ethereum Authors
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package types
18+
19+
// DepositTxV2 embeds DepositTx to inherit all fields and methods
20+
type DepositTxV2 struct{ DepositTx }
21+
22+
// txType identifies this as a V2 deposit
23+
func (tx *DepositTxV2) txType() byte { return DepositTxV2Type }
24+
25+
// copy creates a deep copy and returns the correct concrete type
26+
func (tx *DepositTxV2) copy() TxData {
27+
depCopy := tx.DepositTx.copy().(*DepositTx) // deep-copy from the embedded value
28+
return &DepositTxV2{DepositTx: *depCopy}
29+
}

0 commit comments

Comments
 (0)