Skip to content
63 changes: 63 additions & 0 deletions crates/optimism/tests/proofs/resyncing_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package proofs

import (
"testing"
"time"

"github.com/ethereum-optimism/optimism/op-devstack/devtest"
"github.com/ethereum-optimism/optimism/op-devstack/presets"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/require"
)

func TestResyncing(gt *testing.T) {
t := devtest.SerialT(gt)
ctx := t.Ctx()

sys := presets.NewSingleChainMultiNode(t)

alice := sys.FunderL2.NewFundedEOA(eth.OneEther)
bob := sys.FunderL2.NewFundedEOA(eth.OneEther)

tx := alice.Transfer(bob.Address(), eth.OneHundredthEther)
receipt, err := tx.Included.Eval(ctx)
require.NoError(gt, err)
require.Equal(gt, types.ReceiptStatusSuccessful, receipt.Status)

t.Logf("Stopping L2 CLB and ELB to simulate downtime")
sys.L2CLB.Stop()
sys.L2ELB.Stop()

var blockNumbers []uint64
// produce some transactions while the node is down
for i := 0; i < 5; i++ {
tx := alice.Transfer(bob.Address(), eth.OneHundredthEther)
receipt, err := tx.Included.Eval(ctx)
require.NoError(gt, err)
require.Equal(gt, types.ReceiptStatusSuccessful, receipt.Status)
blockNumbers = append(blockNumbers, receipt.BlockNumber.Uint64())
}

// restart the node and ensure it can sync the missing blocks
t.Logf("Restarting L2 CLB and ELB to resync")
sys.L2ELB.Start()
sys.L2CLB.Start()

time.Sleep(3 * time.Second)

err = wait.For(t.Ctx(), 2*time.Second, func() (bool, error) {
status := sys.L2CLB.SyncStatus()
return status.UnsafeL2.Number > blockNumbers[len(blockNumbers)-1], nil
})
require.NoError(gt, err, "L2 CLB failed to resync to latest block")

t.Logf("Fetching and verifying proofs for transactions produced while node was down")
// verify the proofs for the transactions produced while the node was down
for _, blockNumber := range blockNumbers {
fetchAndVerifyProofs(t, sys, bob.Address(), []common.Hash{}, blockNumber)
fetchAndVerifyProofs(t, sys, alice.Address(), []common.Hash{}, blockNumber)
}
}
16 changes: 8 additions & 8 deletions crates/optimism/tests/proofs/simple_storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func TestStorageProofUsingSimpleStorageContract(gt *testing.T) {
t.Logf("contract deployed at address %s in L2 block %d", contractAddress.Hex(), blockNum)

// fetch and verify initial proof (should be zeroed storage)
fetchAndVerifyProofs(ctx, t, sys, contractAddress, []common.Hash{common.HexToHash("0x0")}, blockNum)
fetchAndVerifyProofs(t, sys, contractAddress, []common.Hash{common.HexToHash("0x0")}, blockNum)

type caseEntry struct {
Block uint64
Expand Down Expand Up @@ -88,12 +88,12 @@ func TestStorageProofUsingSimpleStorageContract(gt *testing.T) {

// for each case, get proof and verify
for _, c := range cases {
fetchAndVerifyProofs(ctx, t, sys, contractAddress, []common.Hash{common.HexToHash("0x0")}, c.Block)
fetchAndVerifyProofs(t, sys, contractAddress, []common.Hash{common.HexToHash("0x0")}, c.Block)
}

// test with non-existent storage slot
nonExistentSlot := common.HexToHash("0xdeadbeef")
fetchAndVerifyProofs(ctx, t, sys, contractAddress, []common.Hash{nonExistentSlot}, cases[len(cases)-1].Block)
fetchAndVerifyProofs(t, sys, contractAddress, []common.Hash{nonExistentSlot}, cases[len(cases)-1].Block)
}

func multiStorageSetValues(t devtest.T, parsedABI *abi.ABI, user *dsl.EOA, contractAddress common.Address, aVal, bVal *big.Int) *types.Receipt {
Expand Down Expand Up @@ -142,7 +142,7 @@ func TestStorageProofUsingMultiStorageContract(gt *testing.T) {
t.Logf("contract deployed at address %s in L2 block %d", contractAddress.Hex(), blockNum)

// fetch and verify initial proof (should be zeroed storage)
fetchAndVerifyProofs(ctx, t, sys, contractAddress, []common.Hash{common.HexToHash("0x0"), common.HexToHash("0x1")}, blockNum)
fetchAndVerifyProofs(t, sys, contractAddress, []common.Hash{common.HexToHash("0x0"), common.HexToHash("0x1")}, blockNum)

// set multiple storage slots
type caseEntry struct {
Expand Down Expand Up @@ -184,7 +184,7 @@ func TestStorageProofUsingMultiStorageContract(gt *testing.T) {
slots = append(slots, slot)
}

fetchAndVerifyProofs(ctx, t, sys, contractAddress, slots, c.Block)
fetchAndVerifyProofs(t, sys, contractAddress, slots, c.Block)
}
}

Expand Down Expand Up @@ -322,11 +322,11 @@ func TestTokenVaultStorageProofs(gt *testing.T) {
// fetch & verify proofs at appropriate blocks
// balance after deposit (depositBlock)
t.Logf("Verifying balance slot %s at deposit block %d", balanceSlot.Hex(), depositBlock)
fetchAndVerifyProofs(ctx, t, sys, contractAddr, []common.Hash{balanceSlot, depositor0Slot}, depositBlock)
fetchAndVerifyProofs(t, sys, contractAddr, []common.Hash{balanceSlot, depositor0Slot}, depositBlock)
// allowance after approve (approveBlock)
t.Logf("Verifying allowance slot %s at approve block %d", allowanceSlot.Hex(), approveBlock)
fetchAndVerifyProofs(ctx, t, sys, contractAddr, []common.Hash{allowanceSlot}, approveBlock)
fetchAndVerifyProofs(t, sys, contractAddr, []common.Hash{allowanceSlot}, approveBlock)
// after deactivation, allowance should be zero at deactBlock
t.Logf("Verifying allowance slot %s at deactivate block %d", allowanceSlot.Hex(), deactBlock)
fetchAndVerifyProofs(ctx, t, sys, contractAddr, []common.Hash{allowanceSlot}, deactBlock)
fetchAndVerifyProofs(t, sys, contractAddr, []common.Hash{allowanceSlot}, deactBlock)
}
3 changes: 2 additions & 1 deletion crates/optimism/tests/proofs/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ func VerifyProof(res *eth.AccountResult, stateRoot common.Hash) error {
return err
}

func fetchAndVerifyProofs(ctx context.Context, t devtest.T, sys *presets.SingleChainMultiNode, contractAddress common.Address, slots []common.Hash, block uint64) {
func fetchAndVerifyProofs(t devtest.T, sys *presets.SingleChainMultiNode, contractAddress common.Address, slots []common.Hash, block uint64) {
ctx := t.Ctx()
gethProofRes, err := sys.L2EL.Escape().L2EthClient().GetProof(ctx, contractAddress, slots, hexutil.Uint64(block).String())
if err != nil {
t.Errorf("failed to get proof from L2EL at block %d: %v", block, err)
Expand Down
Loading