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

feat(prover): update l1Current cursor to record L1 hash #327

Merged
merged 1 commit into from
Jul 23, 2023
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 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