mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-12 06:53:46 +00:00
feat(beacon): remove soft blocks implementation (#366)
* Revert "chore(cmd): add `--taiko` flag (#365)" This reverts commitca784a23df. * Revert "chore(cmd): remove `--taiko.preconfirmationForwardingUrl` flag (#362)" This reverts commit283fedd05b. * Revert "feat(beacon): introduce soft blocks (#342)" This reverts commita2cbf904ea.
This commit is contained in:
parent
ca784a23df
commit
3b305232a5
19 changed files with 78 additions and 421 deletions
8
.github/workflows/docker.yml
vendored
8
.github/workflows/docker.yml
vendored
|
|
@ -2,7 +2,7 @@ name: "Push multi-arch docker image to GAR"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [taiko]
|
branches: [ taiko ]
|
||||||
tags:
|
tags:
|
||||||
- "v*"
|
- "v*"
|
||||||
|
|
||||||
|
|
@ -19,9 +19,9 @@ jobs:
|
||||||
platform: linux/amd64
|
platform: linux/amd64
|
||||||
- runner: arc-runner-set-arm64
|
- runner: arc-runner-set-arm64
|
||||||
platform: linux/arm64
|
platform: linux/arm64
|
||||||
|
|
||||||
runs-on: ${{ matrix.runner }}
|
runs-on: ${{ matrix.runner }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Prepare Environment
|
- name: Prepare Environment
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -80,7 +80,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
platforms: ${{ matrix.platform }}
|
platforms: ${{ matrix.platform }}
|
||||||
push: true
|
push: true
|
||||||
tags: ${{ env.REGISTRY_IMAGE }}
|
tags: ${{ env.REGISTRY_IMAGE }}
|
||||||
|
|
|
||||||
|
|
@ -261,7 +261,7 @@ func init() {
|
||||||
metricsFlags,
|
metricsFlags,
|
||||||
)
|
)
|
||||||
// CHANGE(taiko): append Taiko flags into the original GETH flags
|
// CHANGE(taiko): append Taiko flags into the original GETH flags
|
||||||
app.Flags = append(app.Flags, utils.TaikoFlag)
|
app.Flags = append(app.Flags, &utils.TaikoFlag)
|
||||||
|
|
||||||
flags.AutoEnvVars(app.Flags, "GETH")
|
flags.AutoEnvVars(app.Flags, "GETH")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
@ -13,10 +12,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
TaikoFlag = &cli.BoolFlag{
|
TaikoFlag = cli.BoolFlag{
|
||||||
Name: "taiko",
|
Name: "taiko",
|
||||||
Usage: "Taiko network",
|
Usage: "Taiko network",
|
||||||
Category: flags.TaikoCategory,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,10 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
@ -42,13 +40,12 @@ var (
|
||||||
// Taiko is a consensus engine used by L2 rollup.
|
// Taiko is a consensus engine used by L2 rollup.
|
||||||
type Taiko struct {
|
type Taiko struct {
|
||||||
chainConfig *params.ChainConfig
|
chainConfig *params.ChainConfig
|
||||||
chainDB ethdb.Database
|
|
||||||
taikoL2Address common.Address
|
taikoL2Address common.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = new(Taiko)
|
var _ = new(Taiko)
|
||||||
|
|
||||||
func New(chainConfig *params.ChainConfig, chainDB ethdb.Database) *Taiko {
|
func New(chainConfig *params.ChainConfig) *Taiko {
|
||||||
taikoL2AddressPrefix := strings.TrimPrefix(chainConfig.ChainID.String(), "0")
|
taikoL2AddressPrefix := strings.TrimPrefix(chainConfig.ChainID.String(), "0")
|
||||||
|
|
||||||
return &Taiko{
|
return &Taiko{
|
||||||
|
|
@ -59,7 +56,6 @@ func New(chainConfig *params.ChainConfig, chainDB ethdb.Database) *Taiko {
|
||||||
strings.Repeat("0", common.AddressLength*2-len(taikoL2AddressPrefix)-len(TaikoL2AddressSuffix)) +
|
strings.Repeat("0", common.AddressLength*2-len(taikoL2AddressPrefix)-len(TaikoL2AddressSuffix)) +
|
||||||
TaikoL2AddressSuffix,
|
TaikoL2AddressSuffix,
|
||||||
),
|
),
|
||||||
chainDB: chainDB,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,7 +82,7 @@ func (t *Taiko) VerifyHeader(chain consensus.ChainHeaderReader, header *types.He
|
||||||
return consensus.ErrUnknownAncestor
|
return consensus.ErrUnknownAncestor
|
||||||
}
|
}
|
||||||
// Sanity checks passed, do a proper verification
|
// Sanity checks passed, do a proper verification
|
||||||
return t.verifyHeader(header, parent, time.Now().Unix())
|
return t.verifyHeader(chain, header, parent, time.Now().Unix())
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
|
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
|
||||||
|
|
@ -113,7 +109,7 @@ func (t *Taiko) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*type
|
||||||
if parent == nil {
|
if parent == nil {
|
||||||
err = consensus.ErrUnknownAncestor
|
err = consensus.ErrUnknownAncestor
|
||||||
} else {
|
} else {
|
||||||
err = t.verifyHeader(header, parent, unixNow)
|
err = t.verifyHeader(chain, header, parent, unixNow)
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case <-abort:
|
case <-abort:
|
||||||
|
|
@ -125,7 +121,11 @@ func (t *Taiko) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*type
|
||||||
return abort, results
|
return abort, results
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Taiko) verifyHeader(header, parent *types.Header, unixNow int64) error {
|
func (t *Taiko) verifyHeader(chain consensus.ChainHeaderReader, header, parent *types.Header, unixNow int64) error {
|
||||||
|
if header.Time > uint64(unixNow) {
|
||||||
|
return consensus.ErrFutureBlock
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that the header's extra-data section is of a reasonable size (<= 32 bytes)
|
// Ensure that the header's extra-data section is of a reasonable size (<= 32 bytes)
|
||||||
if uint64(len(header.Extra)) > params.MaximumExtraDataSize {
|
if uint64(len(header.Extra)) > params.MaximumExtraDataSize {
|
||||||
return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize)
|
return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize)
|
||||||
|
|
@ -171,16 +171,6 @@ func (t *Taiko) verifyHeader(header, parent *types.Header, unixNow int64) error
|
||||||
return ErrEmptyWithdrawalsHash
|
return ErrEmptyWithdrawalsHash
|
||||||
}
|
}
|
||||||
|
|
||||||
l1Origin, err := rawdb.ReadL1Origin(t.chainDB, header.Number)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the current block is not a soft block, then check the timestamp.
|
|
||||||
if l1Origin != nil && !l1Origin.IsSoftBlock() && header.Time > uint64(unixNow) {
|
|
||||||
return consensus.ErrFutureBlock
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ func init() {
|
||||||
config.ArrowGlacierBlock = nil
|
config.ArrowGlacierBlock = nil
|
||||||
config.Ethash = nil
|
config.Ethash = nil
|
||||||
config.Taiko = true
|
config.Taiko = true
|
||||||
testEngine = taiko.New(config, rawdb.NewMemoryDatabase())
|
testEngine = taiko.New(config)
|
||||||
|
|
||||||
taikoL2AddressPrefix := strings.TrimPrefix(config.ChainID.String(), "0")
|
taikoL2AddressPrefix := strings.TrimPrefix(config.ChainID.String(), "0")
|
||||||
|
|
||||||
|
|
@ -93,7 +93,44 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateTestChain(t *testing.T) ([]*types.Block, *eth.Ethereum) {
|
func newTestBackend(t *testing.T) (*eth.Ethereum, []*types.Block) {
|
||||||
|
// Generate test chain.
|
||||||
|
blocks := generateTestChain()
|
||||||
|
|
||||||
|
// Create node
|
||||||
|
n, err := node.New(&node.Config{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't create new node: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Ethereum Service
|
||||||
|
config := ðconfig.Config{
|
||||||
|
Genesis: genesis,
|
||||||
|
}
|
||||||
|
|
||||||
|
ethservice, err := eth.New(n, config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't create new ethereum service: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import the test chain.
|
||||||
|
if err := n.Start(); err != nil {
|
||||||
|
t.Fatalf("can't start test node: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := ethservice.BlockChain().InsertChain(blocks[1:]); err != nil {
|
||||||
|
t.Fatalf("can't import test blocks: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ethservice.Engine().(*taiko.Taiko); !ok {
|
||||||
|
t.Fatalf("not use taiko engine")
|
||||||
|
}
|
||||||
|
|
||||||
|
return ethservice, blocks
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateTestChain() []*types.Block {
|
||||||
|
db := rawdb.NewMemoryDatabase()
|
||||||
generate := func(i int, g *core.BlockGen) {
|
generate := func(i int, g *core.BlockGen) {
|
||||||
g.OffsetTime(5)
|
g.OffsetTime(5)
|
||||||
|
|
||||||
|
|
@ -110,56 +147,16 @@ func generateTestChain(t *testing.T) ([]*types.Block, *eth.Ethereum) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create node
|
|
||||||
n, err := node.New(&node.Config{
|
|
||||||
DataDir: t.TempDir(),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("can't create new node: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Ethereum Service
|
|
||||||
ethService, err := eth.New(n, ðconfig.Config{
|
|
||||||
Genesis: genesis,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("can't create new ethereum service: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
db := ethService.ChainDb()
|
|
||||||
|
|
||||||
gblock := genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
|
gblock := genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
|
||||||
|
|
||||||
blocks, _ := core.GenerateChain(genesis.Config, gblock, testEngine, db, 1, generate)
|
blocks, _ := core.GenerateChain(genesis.Config, gblock, testEngine, db, 1, generate)
|
||||||
|
|
||||||
blocks = append([]*types.Block{gblock}, blocks...)
|
blocks = append([]*types.Block{gblock}, blocks...)
|
||||||
|
return blocks
|
||||||
// Insert L1Origins.
|
|
||||||
for _, block := range blocks {
|
|
||||||
rawdb.WriteL1Origin(db, block.Number(), &rawdb.L1Origin{
|
|
||||||
BlockID: block.Number(),
|
|
||||||
L1BlockHeight: block.Number(),
|
|
||||||
L1BlockHash: block.Hash(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Import the test chain.
|
|
||||||
if err := n.Start(); err != nil {
|
|
||||||
t.Fatalf("can't start test node: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := ethService.BlockChain().InsertChain(blocks[1:]); err != nil {
|
|
||||||
t.Fatalf("can't import test blocks: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := ethService.Engine().(*taiko.Taiko); !ok {
|
|
||||||
t.Fatalf("not use taiko engine")
|
|
||||||
}
|
|
||||||
|
|
||||||
return blocks, ethService
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVerifyHeader(t *testing.T) {
|
func TestVerifyHeader(t *testing.T) {
|
||||||
// Generate test chain.
|
ethService, blocks := newTestBackend(t)
|
||||||
blocks, ethService := generateTestChain(t)
|
|
||||||
|
|
||||||
for _, b := range blocks {
|
for _, b := range blocks {
|
||||||
err := testEngine.VerifyHeader(ethService.BlockChain(), b.Header())
|
err := testEngine.VerifyHeader(ethService.BlockChain(), b.Header())
|
||||||
|
|
|
||||||
|
|
@ -2269,12 +2269,7 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
|
||||||
} else {
|
} else {
|
||||||
// len(newChain) == 0 && len(oldChain) > 0
|
// len(newChain) == 0 && len(oldChain) > 0
|
||||||
// rewind the canonical chain to a lower point.
|
// rewind the canonical chain to a lower point.
|
||||||
// CHANGE(taiko): use debug log level to avoid logging too many logs when frequently soft block rollback.
|
log.Error("Impossible reorg, please file an issue", "oldnum", oldBlock.Number(), "oldhash", oldBlock.Hash(), "oldblocks", len(oldChain), "newnum", newBlock.Number(), "newhash", newBlock.Hash(), "newblocks", len(newChain))
|
||||||
if bc.chainConfig.Taiko {
|
|
||||||
log.Debug("Impossible reorg, please file an issue", "oldnum", oldBlock.Number(), "oldhash", oldBlock.Hash(), "oldblocks", len(oldChain), "newnum", newBlock.Number(), "newhash", newBlock.Hash(), "newblocks", len(newChain))
|
|
||||||
} else {
|
|
||||||
log.Error("Impossible reorg, please file an issue", "oldnum", oldBlock.Number(), "oldhash", oldBlock.Hash(), "oldblocks", len(oldChain), "newnum", newBlock.Number(), "newhash", newBlock.Hash(), "newblocks", len(newChain))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Acquire the tx-lookup lock before mutation. This step is essential
|
// Acquire the tx-lookup lock before mutation. This step is essential
|
||||||
// as the txlookups should be changed atomically, and all subsequent
|
// as the txlookups should be changed atomically, and all subsequent
|
||||||
|
|
|
||||||
|
|
@ -18,22 +18,14 @@ func (l L1Origin) MarshalJSON() ([]byte, error) {
|
||||||
type L1Origin struct {
|
type L1Origin struct {
|
||||||
BlockID *math.HexOrDecimal256 `json:"blockID" gencodec:"required"`
|
BlockID *math.HexOrDecimal256 `json:"blockID" gencodec:"required"`
|
||||||
L2BlockHash common.Hash `json:"l2BlockHash"`
|
L2BlockHash common.Hash `json:"l2BlockHash"`
|
||||||
L1BlockHeight *math.HexOrDecimal256 `json:"l1BlockHeight"`
|
L1BlockHeight *math.HexOrDecimal256 `json:"l1BlockHeight" gencodec:"required"`
|
||||||
L1BlockHash common.Hash `json:"l1BlockHash"`
|
L1BlockHash common.Hash `json:"l1BlockHash" gencodec:"required"`
|
||||||
BatchID *big.Int `json:"batchID"`
|
|
||||||
EndOfBlock bool `json:"endOfBlock"`
|
|
||||||
EndOfPreconf bool `json:"endOfPreconf"`
|
|
||||||
Preconfer common.Address `json:"preconfer"`
|
|
||||||
}
|
}
|
||||||
var enc L1Origin
|
var enc L1Origin
|
||||||
enc.BlockID = (*math.HexOrDecimal256)(l.BlockID)
|
enc.BlockID = (*math.HexOrDecimal256)(l.BlockID)
|
||||||
enc.L2BlockHash = l.L2BlockHash
|
enc.L2BlockHash = l.L2BlockHash
|
||||||
enc.L1BlockHeight = (*math.HexOrDecimal256)(l.L1BlockHeight)
|
enc.L1BlockHeight = (*math.HexOrDecimal256)(l.L1BlockHeight)
|
||||||
enc.L1BlockHash = l.L1BlockHash
|
enc.L1BlockHash = l.L1BlockHash
|
||||||
enc.BatchID = l.BatchID
|
|
||||||
enc.EndOfBlock = l.EndOfBlock
|
|
||||||
enc.EndOfPreconf = l.EndOfPreconf
|
|
||||||
enc.Preconfer = l.Preconfer
|
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,12 +34,8 @@ func (l *L1Origin) UnmarshalJSON(input []byte) error {
|
||||||
type L1Origin struct {
|
type L1Origin struct {
|
||||||
BlockID *math.HexOrDecimal256 `json:"blockID" gencodec:"required"`
|
BlockID *math.HexOrDecimal256 `json:"blockID" gencodec:"required"`
|
||||||
L2BlockHash *common.Hash `json:"l2BlockHash"`
|
L2BlockHash *common.Hash `json:"l2BlockHash"`
|
||||||
L1BlockHeight *math.HexOrDecimal256 `json:"l1BlockHeight"`
|
L1BlockHeight *math.HexOrDecimal256 `json:"l1BlockHeight" gencodec:"required"`
|
||||||
L1BlockHash *common.Hash `json:"l1BlockHash"`
|
L1BlockHash *common.Hash `json:"l1BlockHash" gencodec:"required"`
|
||||||
BatchID *big.Int `json:"batchID"`
|
|
||||||
EndOfBlock *bool `json:"endOfBlock"`
|
|
||||||
EndOfPreconf *bool `json:"endOfPreconf"`
|
|
||||||
Preconfer *common.Address `json:"preconfer"`
|
|
||||||
}
|
}
|
||||||
var dec L1Origin
|
var dec L1Origin
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
|
@ -60,23 +48,13 @@ func (l *L1Origin) UnmarshalJSON(input []byte) error {
|
||||||
if dec.L2BlockHash != nil {
|
if dec.L2BlockHash != nil {
|
||||||
l.L2BlockHash = *dec.L2BlockHash
|
l.L2BlockHash = *dec.L2BlockHash
|
||||||
}
|
}
|
||||||
if dec.L1BlockHeight != nil {
|
if dec.L1BlockHeight == nil {
|
||||||
l.L1BlockHeight = (*big.Int)(dec.L1BlockHeight)
|
return errors.New("missing required field 'l1BlockHeight' for L1Origin")
|
||||||
}
|
}
|
||||||
if dec.L1BlockHash != nil {
|
l.L1BlockHeight = (*big.Int)(dec.L1BlockHeight)
|
||||||
l.L1BlockHash = *dec.L1BlockHash
|
if dec.L1BlockHash == nil {
|
||||||
}
|
return errors.New("missing required field 'l1BlockHash' for L1Origin")
|
||||||
if dec.BatchID != nil {
|
|
||||||
l.BatchID = dec.BatchID
|
|
||||||
}
|
|
||||||
if dec.EndOfBlock != nil {
|
|
||||||
l.EndOfBlock = *dec.EndOfBlock
|
|
||||||
}
|
|
||||||
if dec.EndOfPreconf != nil {
|
|
||||||
l.EndOfPreconf = *dec.EndOfPreconf
|
|
||||||
}
|
|
||||||
if dec.Preconfer != nil {
|
|
||||||
l.Preconfer = *dec.Preconfer
|
|
||||||
}
|
}
|
||||||
|
l.L1BlockHash = *dec.L1BlockHash
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,22 +29,10 @@ func l1OriginKey(blockID *big.Int) []byte {
|
||||||
|
|
||||||
// L1Origin represents a L1Origin of a L2 block.
|
// L1Origin represents a L1Origin of a L2 block.
|
||||||
type L1Origin struct {
|
type L1Origin struct {
|
||||||
BlockID *big.Int `json:"blockID" gencodec:"required"`
|
|
||||||
L2BlockHash common.Hash `json:"l2BlockHash"`
|
|
||||||
L1BlockHeight *big.Int `json:"l1BlockHeight"`
|
|
||||||
L1BlockHash common.Hash `json:"l1BlockHash"`
|
|
||||||
BatchID *big.Int `json:"batchID" rlp:"optional"`
|
|
||||||
EndOfBlock bool `json:"endOfBlock" rlp:"optional"`
|
|
||||||
EndOfPreconf bool `json:"endOfPreconf" rlp:"optional"`
|
|
||||||
Preconfer common.Address `json:"preconfer" rlp:"optional"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// L1OriginLegacy represents the legacy L1Origin structure of a L2 block.
|
|
||||||
type L1OriginLegacy struct {
|
|
||||||
BlockID *big.Int `json:"blockID" gencodec:"required"`
|
BlockID *big.Int `json:"blockID" gencodec:"required"`
|
||||||
L2BlockHash common.Hash `json:"l2BlockHash"`
|
L2BlockHash common.Hash `json:"l2BlockHash"`
|
||||||
L1BlockHeight *big.Int `json:"l1BlockHeight"`
|
L1BlockHeight *big.Int `json:"l1BlockHeight" gencodec:"required"`
|
||||||
L1BlockHash common.Hash `json:"l1BlockHash"`
|
L1BlockHash common.Hash `json:"l1BlockHash" gencodec:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type l1OriginMarshaling struct {
|
type l1OriginMarshaling struct {
|
||||||
|
|
@ -52,11 +40,6 @@ type l1OriginMarshaling struct {
|
||||||
L1BlockHeight *math.HexOrDecimal256
|
L1BlockHeight *math.HexOrDecimal256
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsSoftBlock returns true if the L1Origin is a softblock.
|
|
||||||
func (l *L1Origin) IsSoftBlock() bool {
|
|
||||||
return l.BatchID != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteL1Origin stores a L1Origin into the database.
|
// WriteL1Origin stores a L1Origin into the database.
|
||||||
func WriteL1Origin(db ethdb.KeyValueWriter, blockID *big.Int, l1Origin *L1Origin) {
|
func WriteL1Origin(db ethdb.KeyValueWriter, blockID *big.Int, l1Origin *L1Origin) {
|
||||||
data, err := rlp.EncodeToBytes(l1Origin)
|
data, err := rlp.EncodeToBytes(l1Origin)
|
||||||
|
|
@ -69,40 +52,16 @@ func WriteL1Origin(db ethdb.KeyValueWriter, blockID *big.Int, l1Origin *L1Origin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteL1Origin removes the L1Origin.
|
// ReadL1Origin retrieves the given L2 block's L1Origin from database.
|
||||||
func DeleteL1Origin(db ethdb.KeyValueWriter, blockID *big.Int) {
|
|
||||||
_ = db.Delete(l1OriginKey(blockID))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadL1Origin retrieves the L1Origin of the given blockID from the database.
|
|
||||||
func ReadL1Origin(db ethdb.KeyValueReader, blockID *big.Int) (*L1Origin, error) {
|
func ReadL1Origin(db ethdb.KeyValueReader, blockID *big.Int) (*L1Origin, error) {
|
||||||
data, _ := db.Get(l1OriginKey(blockID))
|
data, _ := db.Get(l1OriginKey(blockID))
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// First try to decode the new version (with new fields).
|
|
||||||
l1Origin := new(L1Origin)
|
l1Origin := new(L1Origin)
|
||||||
if err := rlp.Decode(bytes.NewReader(data), l1Origin); err != nil {
|
if err := rlp.Decode(bytes.NewReader(data), l1Origin); err != nil {
|
||||||
// If decoding the new version fails, try to decode the legacy version (without new fields).
|
return nil, fmt.Errorf("invalid L1Origin RLP bytes: %w", err)
|
||||||
l1OriginLegacy := new(L1OriginLegacy)
|
|
||||||
if err := rlp.Decode(bytes.NewReader(data), &l1OriginLegacy); err != nil {
|
|
||||||
return nil, fmt.Errorf("invalid legacy L1Origin RLP bytes: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If decoding legacy version succeeds, manually
|
|
||||||
// construct the new L1Origin with default values for the new fields.
|
|
||||||
l1Origin = &L1Origin{
|
|
||||||
BlockID: l1OriginLegacy.BlockID,
|
|
||||||
L2BlockHash: l1OriginLegacy.L2BlockHash,
|
|
||||||
L1BlockHeight: l1OriginLegacy.L1BlockHeight,
|
|
||||||
L1BlockHash: l1OriginLegacy.L1BlockHash,
|
|
||||||
// default value, as the new fields are not present in the legacy version.
|
|
||||||
BatchID: common.Big0,
|
|
||||||
EndOfBlock: false,
|
|
||||||
EndOfPreconf: false,
|
|
||||||
Preconfer: common.Address{},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return l1Origin, nil
|
return l1Origin, nil
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,6 @@ func TestL1Origin(t *testing.T) {
|
||||||
l1Origin, err := ReadL1Origin(db, testL1Origin.BlockID)
|
l1Origin, err := ReadL1Origin(db, testL1Origin.BlockID)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.NotNil(t, l1Origin)
|
require.NotNil(t, l1Origin)
|
||||||
assert.Equal(t, testL1Origin.BatchID, l1Origin.BatchID)
|
|
||||||
assert.Equal(t, testL1Origin.BlockID, l1Origin.BlockID)
|
assert.Equal(t, testL1Origin.BlockID, l1Origin.BlockID)
|
||||||
assert.Equal(t, testL1Origin.L2BlockHash, l1Origin.L2BlockHash)
|
assert.Equal(t, testL1Origin.L2BlockHash, l1Origin.L2BlockHash)
|
||||||
assert.Equal(t, testL1Origin.L1BlockHeight, l1Origin.L1BlockHeight)
|
assert.Equal(t, testL1Origin.L1BlockHeight, l1Origin.L1BlockHeight)
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
InternalDevnetOntakeBlock = common.Big0
|
InternalDevnetOntakeBlock = new(big.Int).SetUint64(0)
|
||||||
PreconfDevnetOntakeBlock = common.Big0
|
|
||||||
HeklaOntakeBlock = new(big.Int).SetUint64(840_512)
|
HeklaOntakeBlock = new(big.Int).SetUint64(840_512)
|
||||||
MainnetOntakeBlock = new(big.Int).SetUint64(538_304)
|
MainnetOntakeBlock = new(big.Int).SetUint64(538_304)
|
||||||
)
|
)
|
||||||
|
|
@ -55,10 +54,6 @@ func TaikoGenesisBlock(networkID uint64) *Genesis {
|
||||||
chainConfig.ChainID = params.HeklaNetworkID
|
chainConfig.ChainID = params.HeklaNetworkID
|
||||||
chainConfig.OntakeBlock = HeklaOntakeBlock
|
chainConfig.OntakeBlock = HeklaOntakeBlock
|
||||||
allocJSON = taikoGenesis.HeklaGenesisAllocJSON
|
allocJSON = taikoGenesis.HeklaGenesisAllocJSON
|
||||||
case params.PreconfDevnetNetworkID.Uint64():
|
|
||||||
chainConfig.ChainID = params.PreconfDevnetNetworkID
|
|
||||||
chainConfig.OntakeBlock = PreconfDevnetOntakeBlock
|
|
||||||
allocJSON = taikoGenesis.PreconfDevnetGenesisAllocJSON
|
|
||||||
default:
|
default:
|
||||||
chainConfig.ChainID = params.TaikoInternalL2ANetworkID
|
chainConfig.ChainID = params.TaikoInternalL2ANetworkID
|
||||||
chainConfig.OntakeBlock = InternalDevnetOntakeBlock
|
chainConfig.OntakeBlock = InternalDevnetOntakeBlock
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,3 @@ var HeklaGenesisAllocJSON []byte
|
||||||
|
|
||||||
//go:embed mainnet.json
|
//go:embed mainnet.json
|
||||||
var MainnetGenesisAllocJSON []byte
|
var MainnetGenesisAllocJSON []byte
|
||||||
|
|
||||||
//go:embed preconf_devnet.json
|
|
||||||
var PreconfDevnetGenesisAllocJSON []byte
|
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -254,7 +254,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||||
eth.miner = miner.New(eth, config.Miner, eth.engine)
|
eth.miner = miner.New(eth, config.Miner, eth.engine)
|
||||||
eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData))
|
eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData))
|
||||||
|
|
||||||
// CHANGE(taiko): set up the pre-confirmation forwarding URL
|
|
||||||
eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, eth, nil}
|
eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, eth, nil}
|
||||||
if eth.APIBackend.allowUnprotectedTxs {
|
if eth.APIBackend.allowUnprotectedTxs {
|
||||||
log.Info("Unprotected transactions allowed")
|
log.Info("Unprotected transactions allowed")
|
||||||
|
|
|
||||||
|
|
@ -400,11 +400,6 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
|
||||||
// generating the payload. It's a special corner case that a few slots are
|
// generating the payload. It's a special corner case that a few slots are
|
||||||
// missing and we are requested to generate the payload in slot.
|
// missing and we are requested to generate the payload in slot.
|
||||||
} else if isTaiko { // CHANGE(taiko): reorg is allowed in L2.
|
} else if isTaiko { // CHANGE(taiko): reorg is allowed in L2.
|
||||||
// After inserting a new canonical head, we delete all L1Origin data of the pending soft blocks.
|
|
||||||
head := api.eth.BlockChain().CurrentBlock()
|
|
||||||
for number := head.Number.Uint64(); number > block.NumberU64(); number-- {
|
|
||||||
rawdb.DeleteL1Origin(api.eth.ChainDb(), new(big.Int).SetUint64(number))
|
|
||||||
}
|
|
||||||
if latestValid, err := api.eth.BlockChain().SetCanonical(block); err != nil {
|
if latestValid, err := api.eth.BlockChain().SetCanonical(block); err != nil {
|
||||||
return engine.ForkChoiceResponse{PayloadStatus: engine.PayloadStatusV1{Status: engine.INVALID, LatestValidHash: &latestValid}}, err
|
return engine.ForkChoiceResponse{PayloadStatus: engine.PayloadStatusV1{Status: engine.INVALID, LatestValidHash: &latestValid}}, err
|
||||||
}
|
}
|
||||||
|
|
@ -451,17 +446,6 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
|
||||||
if payloadAttributes != nil {
|
if payloadAttributes != nil {
|
||||||
// CHANGE(taiko): create a L2 block by Taiko protocol.
|
// CHANGE(taiko): create a L2 block by Taiko protocol.
|
||||||
if isTaiko {
|
if isTaiko {
|
||||||
// L1Origin is a required field in PayloadAttributesV1.
|
|
||||||
if payloadAttributes.L1Origin == nil {
|
|
||||||
return valid(nil), engine.InvalidPayloadAttributes.With(errors.New("L1Origin is nil"))
|
|
||||||
}
|
|
||||||
// If it's not a softblock creation request, then `L1BlockHash` and `L1BlockHeight` are required.
|
|
||||||
if payloadAttributes.L1Origin.BatchID == nil &&
|
|
||||||
(payloadAttributes.L1Origin.L1BlockHash == (common.Hash{}) ||
|
|
||||||
payloadAttributes.L1Origin.L1BlockHeight == nil) {
|
|
||||||
return valid(nil), engine.InvalidPayloadAttributes.With(errors.New("L1BlockHash or L1BlockHeight is nil"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// No need to check payloadAttribute here, because all its fields are
|
// No need to check payloadAttribute here, because all its fields are
|
||||||
// marked as required.
|
// marked as required.
|
||||||
block, err := api.eth.Miner().SealBlockWith(
|
block, err := api.eth.Miner().SealBlockWith(
|
||||||
|
|
@ -504,10 +488,8 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
|
||||||
|
|
||||||
// Write L1Origin.
|
// Write L1Origin.
|
||||||
rawdb.WriteL1Origin(api.eth.ChainDb(), l1Origin.BlockID, l1Origin)
|
rawdb.WriteL1Origin(api.eth.ChainDb(), l1Origin.BlockID, l1Origin)
|
||||||
// Write the head L1Origin, only when it's not a soft block.
|
// Write the head L1Origin.
|
||||||
if l1Origin.BatchID == nil {
|
rawdb.WriteHeadL1Origin(api.eth.ChainDb(), l1Origin.BlockID)
|
||||||
rawdb.WriteHeadL1Origin(api.eth.ChainDb(), l1Origin.BlockID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return valid(&id), nil
|
return valid(&id), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ type Config struct {
|
||||||
func CreateConsensusEngine(config *params.ChainConfig, db ethdb.Database) (consensus.Engine, error) {
|
func CreateConsensusEngine(config *params.ChainConfig, db ethdb.Database) (consensus.Engine, error) {
|
||||||
// CHANGE(taiko): use Taiko consensus engine when the --taiko flag is set.
|
// CHANGE(taiko): use Taiko consensus engine when the --taiko flag is set.
|
||||||
if config.Taiko {
|
if config.Taiko {
|
||||||
return taiko.New(config, db), nil
|
return taiko.New(config), nil
|
||||||
}
|
}
|
||||||
// Geth v1.14.0 dropped support for non-merged networks in any consensus
|
// Geth v1.14.0 dropped support for non-merged networks in any consensus
|
||||||
// mode. If such a network is requested, reject startup.
|
// mode. If such a network is requested, reject startup.
|
||||||
|
|
|
||||||
|
|
@ -69,10 +69,6 @@ func TestHeadL1Origin(t *testing.T) {
|
||||||
L2BlockHash: headerHash,
|
L2BlockHash: headerHash,
|
||||||
L1BlockHeight: randomBigInt(),
|
L1BlockHeight: randomBigInt(),
|
||||||
L1BlockHash: randomHash(),
|
L1BlockHash: randomHash(),
|
||||||
BatchID: nil,
|
|
||||||
EndOfBlock: false,
|
|
||||||
EndOfPreconf: false,
|
|
||||||
Preconfer: common.Address{},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rawdb.WriteL1Origin(db, testL1Origin.BlockID, testL1Origin)
|
rawdb.WriteL1Origin(db, testL1Origin.BlockID, testL1Origin)
|
||||||
|
|
@ -82,7 +78,6 @@ func TestHeadL1Origin(t *testing.T) {
|
||||||
|
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.Equal(t, testL1Origin, l1OriginFound)
|
require.Equal(t, testL1Origin, l1OriginFound)
|
||||||
require.False(t, l1OriginFound.IsSoftBlock())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestL1OriginByID(t *testing.T) {
|
func TestL1OriginByID(t *testing.T) {
|
||||||
|
|
@ -94,10 +89,6 @@ func TestL1OriginByID(t *testing.T) {
|
||||||
L2BlockHash: headerHash,
|
L2BlockHash: headerHash,
|
||||||
L1BlockHeight: randomBigInt(),
|
L1BlockHeight: randomBigInt(),
|
||||||
L1BlockHash: randomHash(),
|
L1BlockHash: randomHash(),
|
||||||
BatchID: common.Big1,
|
|
||||||
EndOfBlock: false,
|
|
||||||
EndOfPreconf: false,
|
|
||||||
Preconfer: testAddr,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
l1OriginFound, err := ec.L1OriginByID(context.Background(), testL1Origin.BlockID)
|
l1OriginFound, err := ec.L1OriginByID(context.Background(), testL1Origin.BlockID)
|
||||||
|
|
@ -111,7 +102,6 @@ func TestL1OriginByID(t *testing.T) {
|
||||||
|
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.Equal(t, testL1Origin, l1OriginFound)
|
require.Equal(t, testL1Origin, l1OriginFound)
|
||||||
require.True(t, l1OriginFound.IsSoftBlock())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// randomHash generates a random blob of data and returns it as a hash.
|
// randomHash generates a random blob of data and returns it as a hash.
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,6 @@ const (
|
||||||
MiscCategory = "MISC"
|
MiscCategory = "MISC"
|
||||||
TestingCategory = "TESTING"
|
TestingCategory = "TESTING"
|
||||||
DeprecatedCategory = "ALIASED (deprecated)"
|
DeprecatedCategory = "ALIASED (deprecated)"
|
||||||
// CHANGE(taiko): Add a new flag category for Taiko network
|
|
||||||
TaikoCategory = "TAIKO"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
||||||
|
|
@ -300,7 +300,6 @@ var NetworkNames = map[string]string{
|
||||||
JolnirNetworkID.String(): "Taiko Alpha-5 L2 (Jolnir)",
|
JolnirNetworkID.String(): "Taiko Alpha-5 L2 (Jolnir)",
|
||||||
KatlaNetworkID.String(): "Taiko Alpha-6 L2 (Katla)",
|
KatlaNetworkID.String(): "Taiko Alpha-6 L2 (Katla)",
|
||||||
HeklaNetworkID.String(): "Taiko Alpha-7 L2 (Hekla)",
|
HeklaNetworkID.String(): "Taiko Alpha-7 L2 (Hekla)",
|
||||||
PreconfDevnetNetworkID.String(): "Taiko Preconfirmation Devnet",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChainConfig is the core config which determines the blockchain settings.
|
// ChainConfig is the core config which determines the blockchain settings.
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ var (
|
||||||
JolnirNetworkID = big.NewInt(167007)
|
JolnirNetworkID = big.NewInt(167007)
|
||||||
KatlaNetworkID = big.NewInt(167008)
|
KatlaNetworkID = big.NewInt(167008)
|
||||||
HeklaNetworkID = big.NewInt(167009)
|
HeklaNetworkID = big.NewInt(167009)
|
||||||
PreconfDevnetNetworkID = big.NewInt(167010)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var networkIDToChainConfig = map[*big.Int]*ChainConfig{
|
var networkIDToChainConfig = map[*big.Int]*ChainConfig{
|
||||||
|
|
@ -34,7 +33,6 @@ var networkIDToChainConfig = map[*big.Int]*ChainConfig{
|
||||||
JolnirNetworkID: TaikoChainConfig,
|
JolnirNetworkID: TaikoChainConfig,
|
||||||
KatlaNetworkID: TaikoChainConfig,
|
KatlaNetworkID: TaikoChainConfig,
|
||||||
HeklaNetworkID: TaikoChainConfig,
|
HeklaNetworkID: TaikoChainConfig,
|
||||||
PreconfDevnetNetworkID: TaikoChainConfig,
|
|
||||||
MainnetChainConfig.ChainID: MainnetChainConfig,
|
MainnetChainConfig.ChainID: MainnetChainConfig,
|
||||||
SepoliaChainConfig.ChainID: SepoliaChainConfig,
|
SepoliaChainConfig.ChainID: SepoliaChainConfig,
|
||||||
TestChainConfig.ChainID: TestChainConfig,
|
TestChainConfig.ChainID: TestChainConfig,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue