Skip to content

Commit f27dbd7

Browse files
Merge branch 'develop' into haoyu/new_L2_base_fee
2 parents aa531d5 + b84f4ed commit f27dbd7

File tree

17 files changed

+307
-71
lines changed

17 files changed

+307
-71
lines changed

cmd/geth/main.go

+1
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ var (
169169
utils.L1DeploymentBlockFlag,
170170
utils.CircuitCapacityCheckEnabledFlag,
171171
utils.RollupVerifyEnabledFlag,
172+
utils.ShadowforkPeersFlag,
172173
}
173174

174175
rpcFlags = []cli.Flag{

cmd/geth/usage.go

+1
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ var AppHelpFlagGroups = []flags.FlagGroup{
237237
utils.BloomFilterSizeFlag,
238238
cli.HelpFlag,
239239
utils.CatalystFlag,
240+
utils.ShadowforkPeersFlag,
240241
},
241242
},
242243
}

cmd/utils/flags.go

+10
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,12 @@ var (
858858
Name: "rpc.getlogs.maxrange",
859859
Usage: "Limit max fetched block range for `eth_getLogs` method",
860860
}
861+
862+
// Shadowfork peers
863+
ShadowforkPeersFlag = cli.StringSliceFlag{
864+
Name: "net.shadowforkpeers",
865+
Usage: "peer ids of shadow fork peers",
866+
}
861867
)
862868

863869
// MakeDataDir retrieves the currently requested data directory, terminating
@@ -1651,6 +1657,10 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
16511657
setCircuitCapacityCheck(ctx, cfg)
16521658
setEnableRollupVerify(ctx, cfg)
16531659
setMaxBlockRange(ctx, cfg)
1660+
if ctx.GlobalIsSet(ShadowforkPeersFlag.Name) {
1661+
cfg.ShadowForkPeerIDs = ctx.GlobalStringSlice(ShadowforkPeersFlag.Name)
1662+
log.Info("Shadow fork peers", "ids", cfg.ShadowForkPeerIDs)
1663+
}
16541664

16551665
// Cap the cache allowance and tune the garbage collector
16561666
mem, err := gopsutil.VirtualMemory()

consensus/clique/clique.go

+22-11
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,9 @@ var (
6666

6767
uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW.
6868

69-
diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures
70-
diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures
69+
diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures
70+
diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures
71+
diffShadowFork = diffNoTurn
7172
)
7273

7374
// Various error messages to mark blocks invalid. These should be private to
@@ -195,6 +196,7 @@ func New(config *params.CliqueConfig, db ethdb.Database) *Clique {
195196
if conf.Epoch == 0 {
196197
conf.Epoch = epochLength
197198
}
199+
198200
// Allocate the snapshot caches and create the engine
199201
recents, _ := lru.NewARC(inmemorySnapshots)
200202
signatures, _ := lru.NewARC(inmemorySignatures)
@@ -291,7 +293,7 @@ func (c *Clique) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
291293
}
292294
// Ensure that the block's difficulty is meaningful (may not be correct at this point)
293295
if number > 0 {
294-
if header.Difficulty == nil || (header.Difficulty.Cmp(diffInTurn) != 0 && header.Difficulty.Cmp(diffNoTurn) != 0) {
296+
if header.Difficulty == nil || (header.Difficulty.Cmp(diffInTurn) != 0 && header.Difficulty.Cmp(diffNoTurn) != 0 && header.Difficulty.Cmp(diffShadowFork) != 0) {
295297
return errInvalidDifficulty
296298
}
297299
}
@@ -375,6 +377,14 @@ func (c *Clique) snapshot(chain consensus.ChainHeaderReader, number uint64, hash
375377
snap *Snapshot
376378
)
377379
for snap == nil {
380+
if c.config.ShadowForkHeight > 0 && number == c.config.ShadowForkHeight {
381+
c.signatures.Purge()
382+
c.recents.Purge()
383+
c.proposals = make(map[common.Address]bool)
384+
snap = newSnapshot(c.config, c.signatures, number, hash, []common.Address{c.config.ShadowForkSigner})
385+
break
386+
}
387+
378388
// If an in-memory snapshot was found, use that
379389
if s, ok := c.recents.Get(hash); ok {
380390
snap = s.(*Snapshot)
@@ -485,11 +495,8 @@ func (c *Clique) verifySeal(snap *Snapshot, header *types.Header, parents []*typ
485495
}
486496
// Ensure that the difficulty corresponds to the turn-ness of the signer
487497
if !c.fakeDiff {
488-
inturn := snap.inturn(header.Number.Uint64(), signer)
489-
if inturn && header.Difficulty.Cmp(diffInTurn) != 0 {
490-
return errWrongDifficulty
491-
}
492-
if !inturn && header.Difficulty.Cmp(diffNoTurn) != 0 {
498+
expected := c.calcDifficulty(snap, signer)
499+
if header.Difficulty.Cmp(expected) != 0 {
493500
return errWrongDifficulty
494501
}
495502
}
@@ -534,7 +541,7 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header
534541
c.lock.RUnlock()
535542

536543
// Set the correct difficulty
537-
header.Difficulty = calcDifficulty(snap, signer)
544+
header.Difficulty = c.calcDifficulty(snap, signer)
538545

539546
// Ensure the extra data has all its components
540547
if len(header.Extra) < extraVanity {
@@ -678,10 +685,14 @@ func (c *Clique) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64,
678685
c.lock.RLock()
679686
signer := c.signer
680687
c.lock.RUnlock()
681-
return calcDifficulty(snap, signer)
688+
return c.calcDifficulty(snap, signer)
682689
}
683690

684-
func calcDifficulty(snap *Snapshot, signer common.Address) *big.Int {
691+
func (c *Clique) calcDifficulty(snap *Snapshot, signer common.Address) *big.Int {
692+
if c.config.ShadowForkHeight > 0 && snap.Number >= c.config.ShadowForkHeight {
693+
// if we are past shadow fork point, set a low difficulty so that mainnet nodes don't try to switch to forked chain
694+
return new(big.Int).Set(diffShadowFork)
695+
}
685696
if snap.inturn(snap.Number+1, signer) {
686697
return new(big.Int).Set(diffInTurn)
687698
}

consensus/clique/clique_test.go

+89
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
package clique
1818

1919
import (
20+
"bytes"
2021
"math/big"
22+
"strings"
2123
"testing"
2224

2325
"github.com/scroll-tech/go-ethereum/common"
@@ -125,3 +127,90 @@ func TestSealHash(t *testing.T) {
125127
t.Errorf("have %x, want %x", have, want)
126128
}
127129
}
130+
131+
func TestShadowFork(t *testing.T) {
132+
engineConf := *params.AllCliqueProtocolChanges.Clique
133+
engineConf.Epoch = 2
134+
forkedEngineConf := engineConf
135+
forkedEngineConf.ShadowForkHeight = 3
136+
shadowForkKey, _ := crypto.HexToECDSA(strings.Repeat("11", 32))
137+
shadowForkAddr := crypto.PubkeyToAddress(shadowForkKey.PublicKey)
138+
forkedEngineConf.ShadowForkSigner = shadowForkAddr
139+
140+
// Initialize a Clique chain with a single signer
141+
var (
142+
db = rawdb.NewMemoryDatabase()
143+
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
144+
addr = crypto.PubkeyToAddress(key.PublicKey)
145+
engine = New(&engineConf, db)
146+
signer = new(types.HomesteadSigner)
147+
forkedEngine = New(&forkedEngineConf, db)
148+
)
149+
genspec := &core.Genesis{
150+
ExtraData: make([]byte, extraVanity+common.AddressLength+extraSeal),
151+
Alloc: map[common.Address]core.GenesisAccount{
152+
addr: {Balance: big.NewInt(10000000000000000)},
153+
},
154+
BaseFee: big.NewInt(params.InitialBaseFee),
155+
}
156+
copy(genspec.ExtraData[extraVanity:], addr[:])
157+
genesis := genspec.MustCommit(db)
158+
159+
// Generate a batch of blocks, each properly signed
160+
chain, _ := core.NewBlockChain(db, nil, params.AllCliqueProtocolChanges, engine, vm.Config{}, nil, nil)
161+
defer chain.Stop()
162+
163+
forkedChain, _ := core.NewBlockChain(db, nil, params.AllCliqueProtocolChanges, forkedEngine, vm.Config{}, nil, nil)
164+
defer forkedChain.Stop()
165+
166+
blocks, _ := core.GenerateChain(params.AllCliqueProtocolChanges, genesis, forkedEngine, db, 16, func(i int, block *core.BlockGen) {
167+
// The chain maker doesn't have access to a chain, so the difficulty will be
168+
// lets unset (nil). Set it here to the correct value.
169+
if block.Number().Uint64() > forkedEngineConf.ShadowForkHeight {
170+
block.SetDifficulty(diffShadowFork)
171+
} else {
172+
block.SetDifficulty(diffInTurn)
173+
}
174+
175+
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(addr), common.Address{0x00}, new(big.Int), params.TxGas, block.BaseFee(), nil), signer, key)
176+
if err != nil {
177+
panic(err)
178+
}
179+
block.AddTxWithChain(chain, tx)
180+
})
181+
for i, block := range blocks {
182+
header := block.Header()
183+
if i > 0 {
184+
header.ParentHash = blocks[i-1].Hash()
185+
}
186+
187+
signingAddr, signingKey := addr, key
188+
if header.Number.Uint64() > forkedEngineConf.ShadowForkHeight {
189+
// start signing with shadow fork authority key
190+
signingAddr, signingKey = shadowForkAddr, shadowForkKey
191+
}
192+
193+
header.Extra = make([]byte, extraVanity)
194+
if header.Number.Uint64()%engineConf.Epoch == 0 {
195+
header.Extra = append(header.Extra, signingAddr.Bytes()...)
196+
}
197+
header.Extra = append(header.Extra, bytes.Repeat([]byte{0}, extraSeal)...)
198+
199+
sig, _ := crypto.Sign(SealHash(header).Bytes(), signingKey)
200+
copy(header.Extra[len(header.Extra)-extraSeal:], sig)
201+
blocks[i] = block.WithSeal(header)
202+
}
203+
204+
if _, err := chain.InsertChain(blocks); err == nil {
205+
t.Fatalf("should've failed to insert some blocks to canonical chain")
206+
}
207+
if chain.CurrentHeader().Number.Uint64() != forkedEngineConf.ShadowForkHeight {
208+
t.Fatalf("unexpected canonical chain height")
209+
}
210+
if _, err := forkedChain.InsertChain(blocks); err != nil {
211+
t.Fatalf("failed to insert blocks to forked chain: %v %d", err, forkedChain.CurrentHeader().Number)
212+
}
213+
if forkedChain.CurrentHeader().Number.Uint64() != uint64(len(blocks)) {
214+
t.Fatalf("unexpected forked chain height")
215+
}
216+
}

consensus/misc/eip1559.go

+3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ func VerifyEip1559Header(config *params.ChainConfig, parent, header *types.Heade
5151

5252
// CalcBaseFee calculates the basefee of the header.
5353
func CalcBaseFee(config *params.ChainConfig, parent *types.Header, parentL1BaseFee *big.Int) *big.Int {
54+
if config.Clique != nil && config.Clique.ShadowForkHeight != 0 && parent.Number.Uint64() >= config.Clique.ShadowForkHeight {
55+
return big.NewInt(10000000) // 0.01 Gwei
56+
}
5457
l2SequencerFee := big.NewInt(1000000) // 0.001 Gwei
5558
provingFee := big.NewInt(33700000) // 0.0337 Gwei
5659

core/types/l2trace.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ type ExecutionResult struct {
7070
// currently they are just `from` and `to` account
7171
AccountsAfter []*AccountWrapper `json:"accountAfter"`
7272

73-
StructLogs []*StructLogRes `json:"structLogs"`
73+
StructLogs []StructLogRes `json:"structLogs"`
7474
CallTrace json.RawMessage `json:"callTrace"`
7575
}
7676

@@ -91,8 +91,8 @@ type StructLogRes struct {
9191

9292
// NewStructLogResBasic Basic StructLogRes skeleton, Stack&Memory&Storage&ExtraData are separated from it for GC optimization;
9393
// still need to fill in with Stack&Memory&Storage&ExtraData
94-
func NewStructLogResBasic(pc uint64, op string, gas, gasCost uint64, depth int, refundCounter uint64, err error) *StructLogRes {
95-
logRes := &StructLogRes{
94+
func NewStructLogResBasic(pc uint64, op string, gas, gasCost uint64, depth int, refundCounter uint64, err error) StructLogRes {
95+
logRes := StructLogRes{
9696
Pc: pc,
9797
Op: op,
9898
Gas: gas,

core/vm/logger.go

+7-15
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ type StructLog struct {
7979
Err error `json:"-"`
8080
}
8181

82-
func NewStructlog(pc uint64, op OpCode, gas, cost uint64, depth int, err error) *StructLog {
83-
return &StructLog{
82+
func NewStructlog(pc uint64, op OpCode, gas, cost uint64, depth int, err error) StructLog {
83+
return StructLog{
8484
Pc: pc,
8585
Op: op,
8686
Gas: gas,
@@ -90,14 +90,6 @@ func NewStructlog(pc uint64, op OpCode, gas, cost uint64, depth int, err error)
9090
}
9191
}
9292

93-
func (s *StructLog) clean() {
94-
s.Memory.Reset()
95-
s.Stack = s.Stack[:0]
96-
s.ReturnData.Reset()
97-
s.Storage = nil
98-
s.Err = nil
99-
}
100-
10193
// overrides for gencodec
10294
type structLogMarshaling struct {
10395
Gas math.HexOrDecimal64
@@ -159,7 +151,7 @@ type StructLogger struct {
159151
createdAccount *types.AccountWrapper
160152

161153
callStackLogInd []int
162-
logs []*StructLog
154+
logs []StructLog
163155
output []byte
164156
err error
165157
}
@@ -359,7 +351,7 @@ func (l *StructLogger) TracedBytecodes() map[common.Hash]CodeInfo {
359351
func (l *StructLogger) CreatedAccount() *types.AccountWrapper { return l.createdAccount }
360352

361353
// StructLogs returns the captured log entries.
362-
func (l *StructLogger) StructLogs() []*StructLog { return l.logs }
354+
func (l *StructLogger) StructLogs() []StructLog { return l.logs }
363355

364356
// Error returns the VM error captured by the trace.
365357
func (l *StructLogger) Error() error { return l.err }
@@ -368,7 +360,7 @@ func (l *StructLogger) Error() error { return l.err }
368360
func (l *StructLogger) Output() []byte { return l.output }
369361

370362
// WriteTrace writes a formatted trace to the given writer
371-
func WriteTrace(writer io.Writer, logs []*StructLog) {
363+
func WriteTrace(writer io.Writer, logs []StructLog) {
372364
for _, log := range logs {
373365
fmt.Fprintf(writer, "%-16spc=%08d gas=%v cost=%v", log.Op, log.Pc, log.Gas, log.GasCost)
374366
if log.Err != nil {
@@ -488,8 +480,8 @@ func (t *mdLogger) CaptureEnter(typ OpCode, from common.Address, to common.Addre
488480
func (t *mdLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
489481

490482
// FormatLogs formats EVM returned structured logs for json output
491-
func FormatLogs(logs []*StructLog) []*types.StructLogRes {
492-
formatted := make([]*types.StructLogRes, 0, len(logs))
483+
func FormatLogs(logs []StructLog) []types.StructLogRes {
484+
formatted := make([]types.StructLogRes, 0, len(logs))
493485

494486
for _, trace := range logs {
495487
logRes := types.NewStructLogResBasic(trace.Pc, trace.Op.String(), trace.Gas, trace.GasCost, trace.Depth, trace.RefundCounter, trace.Err)

eth/backend.go

+10-9
Original file line numberDiff line numberDiff line change
@@ -239,15 +239,16 @@ func New(stack *node.Node, config *ethconfig.Config, l1Client sync_service.EthCl
239239
checkpoint = params.TrustedCheckpoints[genesisHash]
240240
}
241241
if eth.handler, err = newHandler(&handlerConfig{
242-
Database: chainDb,
243-
Chain: eth.blockchain,
244-
TxPool: eth.txPool,
245-
Network: config.NetworkId,
246-
Sync: config.SyncMode,
247-
BloomCache: uint64(cacheLimit),
248-
EventMux: eth.eventMux,
249-
Checkpoint: checkpoint,
250-
Whitelist: config.Whitelist,
242+
Database: chainDb,
243+
Chain: eth.blockchain,
244+
TxPool: eth.txPool,
245+
Network: config.NetworkId,
246+
Sync: config.SyncMode,
247+
BloomCache: uint64(cacheLimit),
248+
EventMux: eth.eventMux,
249+
Checkpoint: checkpoint,
250+
Whitelist: config.Whitelist,
251+
ShadowForkPeerIDs: config.ShadowForkPeerIDs,
251252
}); err != nil {
252253
return nil, err
253254
}

eth/ethconfig/config.go

+3
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ type Config struct {
214214

215215
// Max block range for eth_getLogs api method
216216
MaxBlockRange int64
217+
218+
// List of peer ids that take part in the shadow-fork
219+
ShadowForkPeerIDs []string
217220
}
218221

219222
// CreateConsensusEngine creates a consensus engine for the given chain configuration.

0 commit comments

Comments
 (0)