Skip to content
This repository has been archived by the owner on May 11, 2024. It is now read-only.

Commit

Permalink
feat(prover): update l1Current cursor to record L1 hash (#327)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidtaikocha authored Jul 23, 2023
1 parent b292754 commit 4a5adb5
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 40 deletions.
2 changes: 1 addition & 1 deletion driver/chain_syncer/calldata/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func (s *Syncer) onBlockProposed(
l1CurrentToReset = genesisL1Header
lastInsertedBlockIDToReset = common.Big0
} else {
reorged, l1CurrentToReset, lastInsertedBlockIDToReset, err = s.rpc.CheckL1Reorg(
reorged, l1CurrentToReset, lastInsertedBlockIDToReset, err = s.rpc.CheckL1ReorgFromL2EE(
ctx,
new(big.Int).Sub(event.BlockId, common.Big1),
)
Expand Down
2 changes: 1 addition & 1 deletion driver/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func (s *DriverTestSuite) TestCheckL1Reorg() {
s.Greater(l2Head2.Number.Uint64(), l2Head1.Number.Uint64())
s.Greater(l1Head2.Number.Uint64(), l1Head1.Number.Uint64())

reorged, _, _, err := s.RpcClient.CheckL1Reorg(context.Background(), l2Head2.Number)
reorged, _, _, err := s.RpcClient.CheckL1ReorgFromL2EE(context.Background(), l2Head2.Number)
s.Nil(err)
s.False(reorged)

Expand Down
69 changes: 64 additions & 5 deletions pkg/rpc/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func (c *Client) WaitL1Origin(ctx context.Context, blockID *big.Int) (*rawdb.L1O

l1Origin, err = c.L2.L1OriginByID(ctxWithTimeout, blockID)
if err != nil {
log.Warn("L1Origin from L2 execution engine not found, keep retrying", "blockID", blockID, "error", err)
log.Debug("L1Origin from L2 execution engine not found, keep retrying", "blockID", blockID, "error", err)
continue
}

Expand Down Expand Up @@ -328,9 +328,9 @@ func (c *Client) GetStorageRoot(
return proof.StorageHash, nil
}

// CheckL1Reorg checks whether the L1 chain has been reorged, if so, returns the l1Current cursor and L2 blockID
// that need to reset to.
func (c *Client) CheckL1Reorg(ctx context.Context, blockID *big.Int) (bool, *types.Header, *big.Int, error) {
// CheckL1ReorgFromL2EE checks whether the L1 chain has been reorged from the L1Origin records in L2 EE,
// if so, returns the l1Current cursor and L2 blockID that need to reset to.
func (c *Client) CheckL1ReorgFromL2EE(ctx context.Context, blockID *big.Int) (bool, *types.Header, *big.Int, error) {
var (
reorged bool
l1CurrentToReset *types.Header
Expand Down Expand Up @@ -414,7 +414,7 @@ func (c *Client) CheckL1Reorg(ctx context.Context, blockID *big.Int) (bool, *typ
}

log.Debug(
"Check L1 reorg",
"Check L1 reorg from L2 EE",
"reorged", reorged,
"l1CurrentToResetNumber", l1CurrentToReset.Number,
"l1CurrentToResetHash", l1CurrentToReset.Hash(),
Expand All @@ -424,6 +424,65 @@ func (c *Client) CheckL1Reorg(ctx context.Context, blockID *big.Int) (bool, *typ
return reorged, l1CurrentToReset, blockIDToReset, nil
}

// CheckL1ReorgFromL1Cursor checks whether the L1 chain has been reorged from the given l1Current cursor,
// if so, returns the l1Current cursor that need to reset to.
func (c *Client) CheckL1ReorgFromL1Cursor(
ctx context.Context,
l1Current *types.Header,
genesisHeightL1 uint64,
) (bool, *types.Header, error) {
var (
reorged bool
l1CurrentToReset *types.Header
)
for {
if l1Current.Number.Uint64() <= genesisHeightL1 {
newL1Current, err := c.L1.HeaderByNumber(ctx, new(big.Int).SetUint64(genesisHeightL1))
if err != nil {
return false, nil, err
}

l1CurrentToReset = newL1Current
break
}

l1Header, err := c.L1.BlockByNumber(ctx, l1Current.Number)
if err != nil {
if err.Error() == ethereum.NotFound.Error() {
continue
}

return false, nil, err
}

if l1Header.Hash() != l1Current.Hash() {
log.Info(
"Reorg detected",
"l1Height", l1Current.Number,
"l1HashOld", l1Current.Hash(),
"l1HashNew", l1Header.Hash(),
)
reorged = true
if l1Current, err = c.L1.HeaderByHash(ctx, l1Current.ParentHash); err != nil {
return false, nil, err
}
continue
}

l1CurrentToReset = l1Current
break
}

log.Debug(
"Check L1 reorg from l1Current cursor",
"reorged", reorged,
"l1CurrentToResetNumber", l1CurrentToReset.Number,
"l1CurrentToResetHash", l1CurrentToReset.Hash(),
)

return reorged, l1CurrentToReset, nil
}

// IsJustSyncedByP2P checks whether the given L2 execution engine has just finished a P2P
// sync.
func (c *Client) IsJustSyncedByP2P(ctx context.Context) (bool, error) {
Expand Down
27 changes: 27 additions & 0 deletions pkg/rpc/methods_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package rpc

import (
"context"
"math/big"
"testing"

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -63,3 +64,29 @@ func TestGetProtocolStateVariables(t *testing.T) {
_, err := client.GetProtocolStateVariables(nil)
require.Nil(t, err)
}

func TestCheckL1ReorgFromL1Cursor(t *testing.T) {
client := newTestClient(t)

l1Head, err := client.L1.HeaderByNumber(context.Background(), nil)
require.Nil(t, err)

_, newL1Current, err := client.CheckL1ReorgFromL1Cursor(context.Background(), l1Head, l1Head.Number.Uint64())
require.Nil(t, err)

require.Equal(t, l1Head.Number.Uint64(), newL1Current.Number.Uint64())

stateVar, err := client.TaikoL1.GetStateVariables(nil)
require.Nil(t, err)

reorged, _, err := client.CheckL1ReorgFromL1Cursor(context.Background(), l1Head, stateVar.GenesisHeight)
require.Nil(t, err)
require.False(t, reorged)

l1Head.BaseFee = new(big.Int).Add(l1Head.BaseFee, common.Big1)

reorged, newL1Current, err = client.CheckL1ReorgFromL1Cursor(context.Background(), l1Head, stateVar.GenesisHeight)
require.Nil(t, err)
require.True(t, reorged)
require.Equal(t, l1Head.ParentHash, newL1Current.Hash())
}
1 change: 1 addition & 0 deletions prover/proof_producer/proof_producer.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type ProofRequestOptions struct {
BlockHash common.Hash
ParentHash common.Hash
SignalRoot common.Hash
EventL1Hash common.Hash
Graffiti string
GasUsed uint64
ParentGasUsed uint64
Expand Down
41 changes: 31 additions & 10 deletions prover/proof_producer/special_proof_producer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"math/big"
"time"

"github.com/cenkalti/backoff/v4"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
Expand Down Expand Up @@ -76,9 +77,31 @@ func (p *SpecialProofProducer) RequestProof(
"beneficiary", meta.Beneficiary,
"height", header.Number,
"hash", header.Hash(),
"delay", p.delay,
)

block, err := p.rpc.L2.BlockByHash(ctx, header.Hash())
time.AfterFunc(p.delay, func() {
if err := backoff.Retry(
func() error { return p.requestSpecialProof(ctx, opts, blockID, meta, header, resultCh) },
backoff.NewExponentialBackOff(),
); err != nil {
log.Error("Failed to request special proof", "blockID", blockID)
}
})

return nil
}

// requestSpecialProof tries to generate a special proof for protocol.
func (p *SpecialProofProducer) requestSpecialProof(
ctx context.Context,
opts *ProofRequestOptions,
blockID *big.Int,
meta *bindings.TaikoDataBlockMetadata,
header *types.Header,
resultCh chan *ProofWithHeader,
) error {
block, err := p.rpc.L2.BlockByNumber(ctx, header.Number)
if err != nil {
return fmt.Errorf("failed to get L2 block with given hash %s: %w", header.Hash(), err)
}
Expand Down Expand Up @@ -127,15 +150,13 @@ func (p *SpecialProofProducer) RequestProof(
return fmt.Errorf("failed to sign evidence: %w", err)
}

time.AfterFunc(p.delay, func() {
resultCh <- &ProofWithHeader{
BlockID: blockID,
Header: header,
Meta: meta,
ZkProof: proof,
Opts: opts,
}
})
resultCh <- &ProofWithHeader{
BlockID: blockID,
Header: header,
Meta: meta,
ZkProof: proof,
Opts: opts,
}

return nil
}
Expand Down
12 changes: 6 additions & 6 deletions prover/proof_submitter/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ func sendTxWithBackoff(
ctx context.Context,
cli *rpc.Client,
blockID *big.Int,
eventL1Hash common.Hash,
proposedAt uint64,
meta *bindings.TaikoDataBlockMetadata,
sendTxFunc func() (*types.Transaction, error),
Expand All @@ -81,23 +82,22 @@ func sendTxWithBackoff(
}

// Check if the corresponding L1 block is still in the canonical chain.
l1Header, err := cli.L1.HeaderByNumber(ctx, new(big.Int).SetUint64(meta.L1Height))
l1Header, err := cli.L1.HeaderByNumber(ctx, new(big.Int).SetUint64(meta.L1Height+1))
if err != nil {
log.Warn(
"Failed to fetch L1 block",
"blockID", blockID,
"l1Height", meta.L1Height,
"l1Hash", common.BytesToHash(meta.L1Hash[:]),
"l1Height", meta.L1Height+1,
"error", err,
)
return err
}
if l1Header.Hash() != meta.L1Hash {
if l1Header.Hash() != eventL1Hash {
log.Warn(
"Reorg detected, skip the current proof submission",
"blockID", blockID,
"l1Height", meta.L1Height,
"l1HashOld", common.BytesToHash(meta.L1Hash[:]),
"l1Height", meta.L1Height+1,
"l1HashOld", eventL1Hash,
"l1HashNew", l1Header.Hash(),
)
return nil
Expand Down
6 changes: 5 additions & 1 deletion prover/proof_submitter/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,14 @@ func (s *ProofSubmitterTestSuite) TestGetProveBlocksTxOpts() {
func (s *ProofSubmitterTestSuite) TestSendTxWithBackoff() {
l1Head, err := s.RpcClient.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)
meta := &bindings.TaikoDataBlockMetadata{L1Height: l1Head.Number.Uint64(), L1Hash: l1Head.Hash()}
l1HeadChild, err := s.RpcClient.L1.HeaderByNumber(context.Background(), new(big.Int).Sub(l1Head.Number, common.Big1))
s.Nil(err)
meta := &bindings.TaikoDataBlockMetadata{L1Height: l1HeadChild.Number.Uint64(), L1Hash: l1HeadChild.Hash()}
s.NotNil(sendTxWithBackoff(
context.Background(),
s.RpcClient,
common.Big1,
l1Head.Hash(),
0,
meta,
func() (*types.Transaction, error) { return nil, errors.New("L1_TEST") },
Expand All @@ -46,6 +49,7 @@ func (s *ProofSubmitterTestSuite) TestSendTxWithBackoff() {
context.Background(),
s.RpcClient,
common.Big1,
l1Head.Hash(),
0,
meta,
func() (*types.Transaction, error) {
Expand Down
2 changes: 2 additions & 0 deletions prover/proof_submitter/valid_proof_submitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ func (s *ValidProofSubmitter) RequestProof(ctx context.Context, event *bindings.
BlockHash: block.Hash(),
ParentHash: block.ParentHash(),
SignalRoot: signalRoot,
EventL1Hash: event.Raw.BlockHash,
Graffiti: common.Bytes2Hex(s.graffiti[:]),
GasUsed: block.GasUsed(),
ParentGasUsed: parent.GasUsed(),
Expand Down Expand Up @@ -255,6 +256,7 @@ func (s *ValidProofSubmitter) SubmitProof(
ctx,
s.rpc,
blockID,
proofWithHeader.Opts.EventL1Hash,
block.Header().Time,
proofWithHeader.Meta,
sendTx,
Expand Down
Loading

0 comments on commit 4a5adb5

Please sign in to comment.