diff --git a/op-e2e/actions/user.go b/op-e2e/actions/user.go index 34e1c73999e1..726f53ad472c 100644 --- a/op-e2e/actions/user.go +++ b/op-e2e/actions/user.go @@ -22,6 +22,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/bindingspreview" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" + e2e "github.com/ethereum-optimism/optimism/op-e2e" "github.com/ethereum-optimism/optimism/op-e2e/config" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" @@ -442,7 +443,7 @@ func (s *CrossLayerUser) getLatestWithdrawalParams(t Testing) (*withdrawals.Prov 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.L2.env.EthCl, s.lastL2WithdrawalTxHash, header, &s.L1.env.Bindings.L2OutputOracle.L2OutputOracleCaller, &s.L1.env.Bindings.DisputeGameFactory.DisputeGameFactoryCaller, &s.L1.env.Bindings.OptimismPortal.OptimismPortalCaller, &s.L1.env.Bindings.OptimismPortal2.OptimismPortal2Caller) + params, err := e2e.ProveWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header, &s.L1.env.Bindings.L2OutputOracle.L2OutputOracleCaller, &s.L1.env.Bindings.DisputeGameFactory.DisputeGameFactoryCaller, &s.L1.env.Bindings.OptimismPortal2.OptimismPortal2Caller) require.NoError(t, err) return ¶ms, nil diff --git a/op-e2e/system_tob_test.go b/op-e2e/system_tob_test.go index ec07b7b2726f..c043b2d350b5 100644 --- a/op-e2e/system_tob_test.go +++ b/op-e2e/system_tob_test.go @@ -19,7 +19,6 @@ import ( "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" - "github.com/ethereum-optimism/optimism/op-node/withdrawals" "github.com/ethereum-optimism/optimism/op-service/testutils/fuzzerutils" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi" @@ -454,9 +453,6 @@ func TestMixedWithdrawalValidity(t *testing.T) { disputeGameFactory, err := bindings.NewDisputeGameFactoryCaller(cfg.L1Deployments.DisputeGameFactoryProxy, l1Client) require.NoError(t, err) - optimismPortal, err := bindings.NewOptimismPortalCaller(cfg.L1Deployments.OptimismPortalProxy, l1Client) - require.NoError(t, err) - optimismPortal2, err := bindingspreview.NewOptimismPortal2Caller(cfg.L1Deployments.OptimismPortalProxy, l1Client) require.NoError(t, err) @@ -568,7 +564,7 @@ func TestMixedWithdrawalValidity(t *testing.T) { blockCl := ethclient.NewClient(rpcClient) // Now create the withdrawal - params, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, blockCl, tx.Hash(), header, l2OutputOracle, disputeGameFactory, optimismPortal, optimismPortal2) + params, err := ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, blockCl, tx.Hash(), header, l2OutputOracle, disputeGameFactory, optimismPortal2) require.Nil(t, err) // Obtain our withdrawal parameters diff --git a/op-e2e/withdrawal_helper.go b/op-e2e/withdrawal_helper.go index b7dbaf7893c8..f0457d105db0 100644 --- a/op-e2e/withdrawal_helper.go +++ b/op-e2e/withdrawal_helper.go @@ -123,13 +123,10 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2N factory, err := bindings.NewDisputeGameFactoryCaller(config.L1Deployments.DisputeGameFactoryProxy, l1Client) require.Nil(t, err) - portal1, err := bindings.NewOptimismPortalCaller(config.L1Deployments.OptimismPortalProxy, l1Client) - require.Nil(t, err) - portal2, err := bindingspreview.NewOptimismPortal2Caller(config.L1Deployments.OptimismPortalProxy, l1Client) require.Nil(t, err) - params, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, blockCl, l2WithdrawalReceipt.TxHash, header, oracle, factory, portal1, portal2) + params, err := ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, blockCl, l2WithdrawalReceipt.TxHash, header, oracle, factory, portal2) require.Nil(t, err) portal, err := bindings.NewOptimismPortal(config.L1Deployments.OptimismPortalProxy, l1Client) @@ -162,6 +159,14 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2N return params, proveReceipt } +func ProveWithdrawalParameters(ctx context.Context, proofCl withdrawals.ProofClient, l2ReceiptCl withdrawals.ReceiptClient, l2BlockCl withdrawals.BlockClient, txHash common.Hash, header *types.Header, l2OutputOracleContract *bindings.L2OutputOracleCaller, disputeGameFactoryContract *bindings.DisputeGameFactoryCaller, optimismPortal2Contract *bindingspreview.OptimismPortal2Caller) (withdrawals.ProvenWithdrawalParameters, error) { + if e2eutils.UseFPAC() { + return withdrawals.ProveWithdrawalParametersFPAC(ctx, proofCl, l2ReceiptCl, l2BlockCl, txHash, disputeGameFactoryContract, optimismPortal2Contract) + } else { + return withdrawals.ProveWithdrawalParameters(ctx, proofCl, l2ReceiptCl, l2BlockCl, txHash, header, l2OutputOracleContract) + } +} + func FinalizeWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, privKey *ecdsa.PrivateKey, withdrawalProofReceipt *types.Receipt, params withdrawals.ProvenWithdrawalParameters) (*types.Receipt, *types.Receipt, *types.Receipt) { // Wait for finalization and then create the Finalized Withdrawal Transaction ctx, cancel := context.WithTimeout(context.Background(), 30*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) diff --git a/op-node/withdrawals/utils.go b/op-node/withdrawals/utils.go index 18dc3b1fdeaa..057b56a29945 100644 --- a/op-node/withdrawals/utils.go +++ b/op-node/withdrawals/utils.go @@ -17,7 +17,6 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindingspreview" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" - "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" ) var MessagePassedTopic = crypto.Keccak256Hash([]byte("MessagePassed(uint256,address,address,uint256,uint256,bytes,bytes32)")) @@ -48,10 +47,32 @@ type ProvenWithdrawalParameters struct { WithdrawalProof [][]byte // List of trie nodes to prove L2 storage } -// ProveWithdrawalParameters queries L1 & L2 to generate all withdrawal parameters and proof necessary to prove a withdrawal on L1. +// ProveWithdrawalParameters calls ProveWithdrawalParametersForBlock with the most recent L2 output after the given header. +func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2ReceiptCl ReceiptClient, l2BlockCl BlockClient, txHash common.Hash, header *types.Header, l2OutputOracleContract *bindings.L2OutputOracleCaller) (ProvenWithdrawalParameters, error) { + l2OutputIndex, err := l2OutputOracleContract.GetL2OutputIndexAfter(&bind.CallOpts{}, header.Number) + if err != nil { + return ProvenWithdrawalParameters{}, fmt.Errorf("failed to get l2OutputIndex: %w", err) + } + l2BlockNumber := header.Number + return ProveWithdrawalParametersForBlock(ctx, proofCl, l2ReceiptCl, l2BlockCl, txHash, l2BlockNumber, l2OutputIndex) +} + +// ProveWithdrawalParametersFPAC calls ProveWithdrawalParametersForBlock with the most recent L2 output after the latest game. +func ProveWithdrawalParametersFPAC(ctx context.Context, proofCl ProofClient, l2ReceiptCl ReceiptClient, l2BlockCl BlockClient, txHash common.Hash, disputeGameFactoryContract *bindings.DisputeGameFactoryCaller, optimismPortal2Contract *bindingspreview.OptimismPortal2Caller) (ProvenWithdrawalParameters, error) { + latestGame, err := FindLatestGame(ctx, disputeGameFactoryContract, optimismPortal2Contract) + if err != nil { + return ProvenWithdrawalParameters{}, fmt.Errorf("failed to find latest game: %w", err) + } + + l2BlockNumber := new(big.Int).SetBytes(latestGame.ExtraData[0:32]) + l2OutputIndex := latestGame.Index + return ProveWithdrawalParametersForBlock(ctx, proofCl, l2ReceiptCl, l2BlockCl, txHash, l2BlockNumber, l2OutputIndex) +} + +// ProveWithdrawalParametersForBlock 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, l2BlockCl BlockClient, txHash common.Hash, header *types.Header, l2OutputOracleContract *bindings.L2OutputOracleCaller, disputeGameFactoryContract *bindings.DisputeGameFactoryCaller, optimismPortalContract *bindings.OptimismPortalCaller, optimismPortal2Contract *bindingspreview.OptimismPortal2Caller) (ProvenWithdrawalParameters, error) { +func ProveWithdrawalParametersForBlock(ctx context.Context, proofCl ProofClient, l2ReceiptCl ReceiptClient, l2BlockCl BlockClient, txHash common.Hash, l2BlockNumber, l2OutputIndex *big.Int) (ProvenWithdrawalParameters, error) { // Transaction receipt receipt, err := l2ReceiptCl.TransactionReceipt(ctx, txHash) if err != nil { @@ -72,25 +93,6 @@ func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2Recei } slot := StorageSlotOfWithdrawalHash(withdrawalHash) - var l2OutputIndex *big.Int - var l2BlockNumber *big.Int - if e2eutils.UseFPAC() { - latestGame, err := FindLatestGame(ctx, disputeGameFactoryContract, optimismPortal2Contract) - if err != nil { - return ProvenWithdrawalParameters{}, fmt.Errorf("failed to find latest game: %w", err) - } - - l2BlockNumber = new(big.Int).SetBytes(latestGame.ExtraData[0:32]) - l2OutputIndex = latestGame.Index - } else { - l2OutputIndex, err = l2OutputOracleContract.GetL2OutputIndexAfter(&bind.CallOpts{}, header.Number) - if err != nil { - return ProvenWithdrawalParameters{}, fmt.Errorf("failed to get l2OutputIndex: %w", err) - } - - l2BlockNumber = header.Number - } - // Fetch the block from the L2 node l2Block, err := l2BlockCl.BlockByNumber(ctx, l2BlockNumber) if err != nil {