Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(taiko-client): check if the block is preconfirmed before calling setHead #18864

Merged
merged 16 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"packages/relayer": "0.12.0",
"packages/snaefell-ui": "1.1.0",
"packages/supplementary-contracts": "1.0.0",
"packages/taiko-client": "0.43.1",
"packages/taiko-client": "1.0.1",
"packages/taikoon-ui": "1.3.0",
"packages/ui-lib": "1.0.0"
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ require (
sigs.k8s.io/yaml v1.3.0 // indirect
)

replace github.com/ethereum/go-ethereum v1.14.11 => github.com/taikoxyz/taiko-geth v1.12.1-0.20250204084657-54ca2198a63b
replace github.com/ethereum/go-ethereum v1.14.11 => github.com/taikoxyz/taiko-geth v1.12.1-0.20250205040456-832713781df8

replace github.com/ethereum-optimism/optimism v1.7.4 => github.com/taikoxyz/optimism v0.0.0-20250128202721-1b986d622e1a

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -888,8 +888,8 @@ github.com/taikoxyz/hive v0.0.0-20240827015317-405b241dd082 h1:ymZR+Y88LOnA8i3Ke
github.com/taikoxyz/hive v0.0.0-20240827015317-405b241dd082/go.mod h1:RHnIu3EFehrWX3JhFAMQSXD5uz7l0xaNroTzXrap7EQ=
github.com/taikoxyz/optimism v0.0.0-20250128202721-1b986d622e1a h1:33/0g4tyyoxFoengwPv6sEseEcEGITqfXbCyruSyXxY=
github.com/taikoxyz/optimism v0.0.0-20250128202721-1b986d622e1a/go.mod h1:V0VCkKtCzuaJH6qcL75SRcbdlakM9LhurMEJUhO6VXA=
github.com/taikoxyz/taiko-geth v1.12.1-0.20250204084657-54ca2198a63b h1:KEXW+q9KzW7VPAiPvxbGrY3Ian30tPCVmjgkHpNDeZc=
github.com/taikoxyz/taiko-geth v1.12.1-0.20250204084657-54ca2198a63b/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2egl+ScIVPjhc7E=
github.com/taikoxyz/taiko-geth v1.12.1-0.20250205040456-832713781df8 h1:cgZhkcg8yi6CkhMQUX9Z/Au2qQFcDwm6isibeq/iMMM=
github.com/taikoxyz/taiko-geth v1.12.1-0.20250205040456-832713781df8/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2egl+ScIVPjhc7E=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/testcontainers/testcontainers-go v0.35.0 h1:uADsZpTKFAtp8SLK+hMwSaa+X+JiERHtd4sQAFmXeMo=
github.com/testcontainers/testcontainers-go v0.35.0/go.mod h1:oEVBj5zrfJTrgjwONs1SsRbnBtH9OKl+IGl3UMcr2B4=
Expand Down
2 changes: 1 addition & 1 deletion packages/taiko-client/bindings/pacaya/.githead
Original file line number Diff line number Diff line change
@@ -1 +1 @@
f5938d4b6e54069d11df6b40ede3ad83012cf0e6
1713be26d6226695f393da883a8cf22d4152dcc9
168 changes: 154 additions & 14 deletions packages/taiko-client/driver/chain_syncer/blob/blocks_inserter/common.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
package blocksinserter

import (
"bytes"
"context"
"errors"
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/beacon/engine"
"github.com/ethereum/go-ethereum/common"
consensus "github.com/ethereum/go-ethereum/consensus/taiko"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/rlp"

"github.com/taikoxyz/taiko-mono/packages/taiko-client/bindings/encoding"
"github.com/taikoxyz/taiko-mono/packages/taiko-client/pkg/rpc"
"github.com/taikoxyz/taiko-mono/packages/taiko-client/pkg/utils"
)
Expand All @@ -30,32 +35,68 @@ func createPayloadAndSetHead(
"parentHash", meta.Parent.Hash(),
"l1Origin", meta.L1Origin,
)
// Insert a TaikoL2.anchorV2 / TaikoAnchor.anchorV3 transaction at transactions list head,
// then encode the transactions list.
txListBytes, err := rlp.EncodeToBytes(append([]*types.Transaction{anchorTx}, meta.Txs...))
if err != nil {
log.Error("Encode txList error", "blockID", meta.BlockID, "error", err)
return nil, err
}

// If the Pacaya block is preconfirmed, we don't need to insert it again.
if meta.BlockID.Cmp(new(big.Int).SetUint64(rpc.PacayaClients.ForkHeight)) >= 0 {
header, err := isBlockPreconfirmed(ctx, rpc, meta, txListBytes, anchorTx)
if err != nil {
log.Debug("Failed to check if the block is preconfirmed", "error", err)
YoGhurt111 marked this conversation as resolved.
Show resolved Hide resolved
} else if header != nil {
// Update the l1Origin and headL1Origin cursor for that preconfirmed block.
meta.L1Origin.L2BlockHash = header.Hash()
if _, err := rpc.L2.UpdateL1Origin(ctx, meta.L1Origin); err != nil {
return nil, fmt.Errorf("failed to update L1 origin: %w", err)
}
if _, err := rpc.L2.SetHeadL1Origin(ctx, meta.L1Origin.BlockID); err != nil {
return nil, fmt.Errorf("failed to write head L1 origin: %w", err)
}

log.Info(
"🧬 The block is preconfirmed",
"blockID", meta.BlockID,
"hash", header.Hash(),
"coinbase", header.Coinbase,
"timestamp", header.Time,
"anchorBlockID", meta.AnchorBlockID,
"anchorBlockHash", meta.AnchorBlockHash,
"baseFee", utils.WeiToEther(header.BaseFee),
)

return encoding.ToExecutableData(header), nil
}
}

payload, err := createExecutionPayloads(
ctx,
rpc,
meta.createExecutionPayloadsMetaData,
txListBytes,
anchorTx,
)
if err != nil {
return nil, fmt.Errorf("failed to create execution payloads: %w", err)
}

var (
lastVerifiedBlockHash common.Hash
)
var lastVerifiedBlockHash common.Hash
lastVerifiedTS, err := rpc.GetLastVerifiedTransitionPacaya(ctx)
if err != nil {
lastVerifiedBlockInfo, err := rpc.GetLastVerifiedBlockOntake(ctx)
if err != nil {
return nil, fmt.Errorf("failed to fetch last verified block: %w", err)
}

if payload.Number > lastVerifiedBlockInfo.BlockId {
if meta.BlockID.Uint64() > lastVerifiedBlockInfo.BlockId {
lastVerifiedBlockHash = lastVerifiedBlockInfo.BlockHash
}
} else {
if payload.Number > lastVerifiedTS.BlockId {
if meta.BlockID.Uint64() > lastVerifiedTS.BlockId {
lastVerifiedBlockHash = lastVerifiedTS.Ts.BlockHash
}
}
Expand Down Expand Up @@ -84,16 +125,9 @@ func createExecutionPayloads(
ctx context.Context,
rpc *rpc.Client,
meta *createExecutionPayloadsMetaData,
txListBytes []byte,
anchorTx *types.Transaction,
) (payloadData *engine.ExecutableData, err error) {
// Insert a TaikoL2.anchor / TaikoL2.anchorV2 transaction at transactions list head
txListBytes, err := rlp.EncodeToBytes(append([]*types.Transaction{anchorTx}, meta.Txs...))
if err != nil {
log.Error("Encode txList error", "blockID", meta.BlockID, "error", err)
return nil, err
}

fc := &engine.ForkchoiceStateV1{HeadBlockHash: meta.ParentHash}
attributes := &engine.PayloadAttributes{
Timestamp: meta.Timestamp,
Random: meta.Difficulty,
Expand Down Expand Up @@ -128,7 +162,11 @@ func createExecutionPayloads(
)

// Step 1, prepare a payload
fcRes, err := rpc.L2Engine.ForkchoiceUpdate(ctx, fc, attributes)
fcRes, err := rpc.L2Engine.ForkchoiceUpdate(
ctx,
&engine.ForkchoiceStateV1{HeadBlockHash: meta.ParentHash},
attributes,
)
if err != nil {
return nil, fmt.Errorf("failed to update fork choice: %w", err)
}
Expand Down Expand Up @@ -168,3 +206,105 @@ func createExecutionPayloads(

return payload, nil
}

// isBlockPreconfirmed checks if the block is preconfirmed.
func isBlockPreconfirmed(
ctx context.Context,
rpc *rpc.Client,
meta *createPayloadAndSetHeadMetaData,
txListBytes []byte,
anchorTx *types.Transaction,
davidtaikocha marked this conversation as resolved.
Show resolved Hide resolved
) (*types.Header, error) {
var blockID = new(big.Int).Add(meta.Parent.Number, common.Big1)
block, err := rpc.L2.BlockByNumber(ctx, blockID)
if err != nil {
return nil, fmt.Errorf("failed to get block by number %d: %w", blockID, err)
}

if block == nil {
return nil, fmt.Errorf("block not found by number %d", blockID)
}

var (
txListHash = crypto.Keccak256Hash(txListBytes[:])
args = &miner.BuildPayloadArgs{
Parent: meta.Parent.Hash(),
Timestamp: block.Time(),
FeeRecipient: block.Coinbase(),
Random: block.MixDigest(),
Withdrawals: make([]*types.Withdrawal, 0),
Version: engine.PayloadV2,
TxListHash: &txListHash,
}
id = args.Id()
)
executableData, err := rpc.L2Engine.GetPayload(ctx, &id)
if err != nil {
return nil, fmt.Errorf("failed to get payload: %w", err)
}

defer func() {
if err != nil {
log.Warn("Invalid preconfirmed block", "blockID", blockID, "coinbase", executableData.FeeRecipient, "reason", err)
}
}()

if executableData.BlockHash != block.Hash() {
err = fmt.Errorf("block hash mismatch: %s != %s", executableData.BlockHash, block.Hash())
return nil, err
}
if block.ParentHash() != meta.ParentHash {
err = fmt.Errorf("parent hash mismatch: %s != %s", block.ParentHash(), meta.ParentHash)
return nil, err
}
if block.Transactions().Len() == 0 {
err = errors.New("transactions list is empty")
return nil, err
}
if block.Transactions()[0].Hash() != anchorTx.Hash() {
err = fmt.Errorf("anchor transaction mismatch: %s != %s", block.Transactions()[0].Hash(), anchorTx.Hash())
return nil, err
}
if block.UncleHash() != types.EmptyUncleHash {
err = fmt.Errorf("uncle hash mismatch: %s != %s", block.UncleHash(), types.EmptyUncleHash)
return nil, err
}
if block.Coinbase() != meta.SuggestedFeeRecipient {
err = fmt.Errorf("coinbase mismatch: %s != %s", block.Coinbase(), meta.SuggestedFeeRecipient)
return nil, err
}
if block.Difficulty().Cmp(common.Big0) != 0 {
err = fmt.Errorf("difficulty mismatch: %s != 0", block.Difficulty())
return nil, err
}
if block.MixDigest() != meta.Difficulty {
err = fmt.Errorf("mixDigest mismatch: %s != %s", block.MixDigest(), meta.Difficulty)
return nil, err
}
if block.Number().Uint64() != meta.BlockID.Uint64() {
err = fmt.Errorf("block number mismatch: %d != %d", block.Number(), meta.BlockID)
return nil, err
}
if block.GasLimit() != meta.GasLimit+consensus.AnchorGasLimit {
err = fmt.Errorf("gas limit mismatch: %d != %d", block.GasLimit(), meta.GasLimit+consensus.AnchorGasLimit)
return nil, err
}
if block.Time() != meta.Timestamp {
err = fmt.Errorf("timestamp mismatch: %d != %d", block.Time(), meta.Timestamp)
return nil, err
}
if !bytes.Equal(block.Extra(), meta.ExtraData) {
err = fmt.Errorf("extra data mismatch: %s != %s", block.Extra(), meta.ExtraData)
return nil, err
}
if block.BaseFee().Cmp(meta.BaseFee) != 0 {
err = fmt.Errorf("base fee mismatch: %s != %s", block.BaseFee(), meta.BaseFee)
return nil, err
}
if block.Withdrawals().Len() != 0 {
err = fmt.Errorf("withdrawals mismatch: %d != 0", block.Withdrawals().Len())
return nil, err
}

return block.Header(), nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ func (i *BlocksInserterPacaya) InsertBlocks(

// Get transactions in the block.
txs := types.Transactions{}
if txListCursor+int(blockInfo.NumTransactions) > len(allTxs) {
if txListCursor+int(blockInfo.NumTransactions) <= len(allTxs) {
davidtaikocha marked this conversation as resolved.
Show resolved Hide resolved
txs = allTxs[txListCursor : txListCursor+int(blockInfo.NumTransactions)]
}

Expand Down Expand Up @@ -234,6 +234,7 @@ func (i *BlocksInserterPacaya) InsertBlocks(
"blockID", blockID,
"hash", lastPayloadData.BlockHash,
"transactions", len(lastPayloadData.Transactions),
"timestamp", lastPayloadData.Timestamp,
"baseFee", utils.WeiToGWei(lastPayloadData.BaseFeePerGas),
"withdrawals", len(lastPayloadData.Withdrawals),
"batchID", meta.GetBatchID(),
Expand Down Expand Up @@ -312,7 +313,10 @@ func (i *BlocksInserterPacaya) InsertPreconfBlockFromTransactionsBatch(
if err != nil {
return nil, fmt.Errorf("failed to calculate difficulty: %w", err)
}
extraData := encoding.EncodeBaseFeeConfig(baseFeeConfig)
var (
extraData = encoding.EncodeBaseFeeConfig(baseFeeConfig)
txs = i.txListDecompressor.TryDecompress(i.rpc.L2.ChainID, executableData.Transactions, true, true)
)

payloadData, err := createPayloadAndSetHead(
ctx,
Expand All @@ -332,10 +336,7 @@ func (i *BlocksInserterPacaya) InsertPreconfBlockFromTransactionsBatch(
L1BlockHeight: nil,
L1BlockHash: common.Hash{},
},
Txs: append(
types.Transactions{anchorTx},
i.txListDecompressor.TryDecompress(i.rpc.L2.ChainID, executableData.Transactions, true, true)...,
),
Txs: txs,
Withdrawals: make([]*types.Withdrawal, 0),
BaseFee: baseFee,
},
Expand All @@ -354,7 +355,7 @@ func (i *BlocksInserterPacaya) InsertPreconfBlockFromTransactionsBatch(
"⏰ New preconfirmation L2 block inserted",
"blockID", executableData.Number,
"hash", payloadData.BlockHash,
"transactions", len(payloadData.Transactions[0]),
"transactions", txs.Len(),
"baseFee", utils.WeiToGWei(payloadData.BaseFeePerGas),
"withdrawals", len(payloadData.Withdrawals),
)
Expand Down
1 change: 1 addition & 0 deletions packages/taiko-client/driver/chain_syncer/blob/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ func (s *Syncer) onBlockProposed(
"l1Hash", meta.GetRawBlockHash(),
"batchID", meta.Pacaya().GetBatchID(),
"lastBlockID", lastBlockID,
"lastTimestamp", meta.Pacaya().GetLastBlockTimestamp(),
"blocks", len(meta.Pacaya().GetBlocks()),
)
if err := s.blocksInserterPacaya.InsertBlocks(ctx, meta, tx, endIter); err != nil {
Expand Down
Loading