Skip to content
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
12 changes: 4 additions & 8 deletions indexer/integration_tests/bedrock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,14 +201,10 @@ func TestBedrockIndexer(t *testing.T) {
require.NoError(t, err)
proofCl := gethclient.New(rpcClient)
receiptCl := ethclient.NewClient(rpcClient)
wParams, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, wdTx.Hash(), finHeader)
require.NoError(t, err)

oracle, err := bindings.NewL2OutputOracleCaller(predeploys.DevL2OutputOracleAddr, l1Client)
require.Nil(t, err)

l2OutputIndex, err := oracle.GetL2OutputIndexAfter(&bind.CallOpts{}, wParams.BlockNumber)
require.Nil(t, err)
wParams, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, wdTx.Hash(), finHeader, oracle)
require.NoError(t, err)

l1Opts.Value = big.NewInt(0)
// Prove our withdrawal
Expand All @@ -222,7 +218,7 @@ func TestBedrockIndexer(t *testing.T) {
GasLimit: wParams.GasLimit,
Data: wParams.Data,
},
l2OutputIndex,
wParams.L2OutputIndex,
wParams.OutputRootProof,
wParams.WithdrawalProof,
)
Expand All @@ -236,7 +232,7 @@ func TestBedrockIndexer(t *testing.T) {
e2eutils.TimeoutCtx(t, time.Minute),
l1Client,
predeploys.DevOptimismPortalAddr,
wParams.BlockNumber,
finHeader.Number,
)
require.NoError(t, err)

Expand Down
4 changes: 2 additions & 2 deletions op-e2e/actions/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ func (s *CrossLayerUser) ProveWithdrawal(t Testing, l2TxHash common.Hash) common
// We generate a proof for the latest L2 output, which shouldn't require archive-node data if it's recent enough.
header, err := s.L2.env.EthCl.HeaderByNumber(t.Ctx(), l2OutputBlockNr)
require.NoError(t, err)
params, err := withdrawals.ProveWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header)
params, err := withdrawals.ProveWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header, &s.L1.env.Bindings.L2OutputOracle.L2OutputOracleCaller)
require.NoError(t, err)

// Create the prove tx
Expand Down Expand Up @@ -480,7 +480,7 @@ func (s *CrossLayerUser) CompleteWithdrawal(t Testing, l2TxHash common.Hash) com
// params for the `WithdrawalTransaction` type generated in the bindings.
header, err := s.L2.env.EthCl.HeaderByNumber(t.Ctx(), l2OutputBlockNr)
require.NoError(t, err)
params, err := withdrawals.ProveWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header)
params, err := withdrawals.ProveWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header, &s.L1.env.Bindings.L2OutputOracle.L2OutputOracleCaller)
require.NoError(t, err)

// Create the withdrawal tx
Expand Down
13 changes: 5 additions & 8 deletions op-e2e/system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -836,16 +836,13 @@ func TestWithdrawals(t *testing.T) {
receiptCl := ethclient.NewClient(rpcClient)

// Now create withdrawal
params, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, tx.Hash(), header)
require.Nil(t, err)

portal, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client)
oracle, err := bindings.NewL2OutputOracleCaller(predeploys.DevL2OutputOracleAddr, l1Client)
require.Nil(t, err)

oracle, err := bindings.NewL2OutputOracleCaller(predeploys.DevL2OutputOracleAddr, l1Client)
params, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, tx.Hash(), header, oracle)
require.Nil(t, err)

l2OutputIndex, err := oracle.GetL2OutputIndexAfter(&bind.CallOpts{}, params.BlockNumber)
portal, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client)
require.Nil(t, err)

opts.Value = nil
Expand All @@ -861,7 +858,7 @@ func TestWithdrawals(t *testing.T) {
GasLimit: params.GasLimit,
Data: params.Data,
},
l2OutputIndex,
params.L2OutputIndex,
params.OutputRootProof,
params.WithdrawalProof,
)
Expand All @@ -875,7 +872,7 @@ func TestWithdrawals(t *testing.T) {
// Wait for finalization and then create the Finalized Withdrawal Transaction
ctx, cancel = context.WithTimeout(context.Background(), 20*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
defer cancel()
_, err = withdrawals.WaitForFinalizationPeriod(ctx, l1Client, predeploys.DevOptimismPortalAddr, params.BlockNumber)
_, err = withdrawals.WaitForFinalizationPeriod(ctx, l1Client, predeploys.DevOptimismPortalAddr, header.Number)
require.Nil(t, err)

// Finalize withdrawal
Expand Down
26 changes: 16 additions & 10 deletions op-node/withdrawals/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,16 @@ type ProvenWithdrawalParameters struct {
Target common.Address
Value *big.Int
GasLimit *big.Int
BlockNumber *big.Int
L2OutputIndex *big.Int
Data []byte
OutputRootProof bindings.TypesOutputRootProof
WithdrawalProof [][]byte // List of trie nodes to prove L2 storage
}

// ProveWithdrawalParameters queries L2 to generate all withdrawal parameters and proof necessary to prove a withdrawal on L1.
// ProveWithdrawalParameters queries L1 & L2 to generate all withdrawal parameters and proof necessary to prove a withdrawal on L1.
// The header provided is very important. It should be a block (timestamp) for which there is a submitted output in the L2 Output Oracle
// contract. If not, the withdrawal will fail as it the storage proof cannot be verified if there is no submitted state root.
func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2ReceiptCl ReceiptClient, txHash common.Hash, header *types.Header) (ProvenWithdrawalParameters, error) {
func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2ReceiptCl ReceiptClient, txHash common.Hash, header *types.Header, l2OutputOracleContract *bindings.L2OutputOracleCaller) (ProvenWithdrawalParameters, error) {
// Transaction receipt
receipt, err := l2ReceiptCl.TransactionReceipt(ctx, txHash)
if err != nil {
Expand All @@ -170,6 +170,12 @@ func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2Recei
if err != nil {
return ProvenWithdrawalParameters{}, err
}

// Fetch the L2OutputIndex from the L2 Output Oracle caller (on L1)
l2OutputIndex, err := l2OutputOracleContract.GetL2OutputIndexAfter(&bind.CallOpts{}, header.Number)
if err != nil {
return ProvenWithdrawalParameters{}, fmt.Errorf("failed to get l2OutputIndex: %w", err)
}
// TODO: Could skip this step, but it's nice to double check it
err = VerifyProof(header.Root, p)
if err != nil {
Expand All @@ -186,13 +192,13 @@ func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2Recei
}

return ProvenWithdrawalParameters{
Nonce: ev.Nonce,
Sender: ev.Sender,
Target: ev.Target,
Value: ev.Value,
GasLimit: ev.GasLimit,
BlockNumber: new(big.Int).Set(header.Number),
Data: ev.Data,
Nonce: ev.Nonce,
Sender: ev.Sender,
Target: ev.Target,
Value: ev.Value,
GasLimit: ev.GasLimit,
L2OutputIndex: l2OutputIndex,
Data: ev.Data,
OutputRootProof: bindings.TypesOutputRootProof{
Version: [32]byte{}, // Empty for version 1
StateRoot: header.Root,
Expand Down