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
2 changes: 1 addition & 1 deletion op-chain-ops/interopgen/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ func GenesisL2(l2Host *script.Host, cfg *L2Config, deployment *L2Deployment) err
L1FeeVaultWithdrawalNetwork: big.NewInt(int64(cfg.L1FeeVaultWithdrawalNetwork.ToUint8())),
GovernanceTokenOwner: cfg.GovernanceTokenOwner,
Fork: big.NewInt(cfg.SolidityForkNumber(1)),
UseInterop: true,
UseInterop: cfg.UseInterop,
EnableGovernance: cfg.EnableGovernance,
FundDevAccounts: cfg.FundDevAccounts,
}); err != nil {
Expand Down
3 changes: 2 additions & 1 deletion op-chain-ops/interopgen/recipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@ func (r *InteropDevL2Recipe) build(l1ChainID uint64, addrs devkeys.Addresses) (*
L2GenesisJovianTimeOffset: nil,
L1CancunTimeOffset: new(hexutil.Uint64),
L1PragueTimeOffset: new(hexutil.Uint64),
UseInterop: true,
// Don't deploy interop L2 contracts if interop hard fork isn't active at genesis
UseInterop: r.InteropOffset == 0,
},
L2CoreDeployConfig: genesis.L2CoreDeployConfig{
L1ChainID: l1ChainID,
Expand Down
8 changes: 8 additions & 0 deletions op-e2e/actions/interop/dsl/inbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func NewInboxContract(t helpers.Testing) *InboxContract {
type ExecuteOpts struct {
Identifier *inbox.Identifier
Payload *[]byte
GasLimit uint64
}

func WithIdentifier(ident inbox.Identifier) func(opts *ExecuteOpts) {
Expand All @@ -44,6 +45,12 @@ func WithPayload(payload []byte) func(opts *ExecuteOpts) {
}
}

func WithFixedGasLimit() func(opts *ExecuteOpts) {
return func(opts *ExecuteOpts) {
opts.GasLimit = 1_000_000 // Overly large to ensure the tx doesn't OOG.
}
}

func WithPendingMessage(emitter *EmitterContract, chain *Chain, number uint64, logIndex int, msg string) func(opts *ExecuteOpts) {
return func(opts *ExecuteOpts) {
blockTime := chain.RollupCfg.TimestampForBlock(number)
Expand Down Expand Up @@ -87,6 +94,7 @@ func (i *InboxContract) Execute(user *DSLUser, initTx *GeneratedTransaction, arg
payload = initTx.MessagePayload()
}
txOpts, from := user.TransactOpts(chain.ChainID.ToBig())
txOpts.GasLimit = opts.GasLimit
contract, err := inbox.NewInbox(predeploys.CrossL2InboxAddr, chain.SequencerEngine.EthClient())
require.NoError(i.t, err)
id := stypes.Identifier{
Expand Down
12 changes: 12 additions & 0 deletions op-e2e/actions/interop/dsl/interop.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,18 @@ func SetInteropOffsetForAllL2s(offset uint64) setupOption {
}
}

func SetInteropForkScheduledButInactive() setupOption {
return func(recipe *interopgen.InteropDevRecipe) {
// Update in place to avoid making a copy and losing the change.
// Set to a year in the future. Far enough tests won't hit it
// but not so far it will overflow when added to current time.
val := uint64(365 * 24 * 60 * 60)
for key := range recipe.L2s {
recipe.L2s[key].InteropOffset = val
}
}
}

// SetupInterop creates an InteropSetup to instantiate actors on, with 2 L2 chains.
func SetupInterop(t helpers.Testing, opts ...setupOption) *InteropSetup {
recipe := interopgen.InteropDevRecipe{
Expand Down
21 changes: 20 additions & 1 deletion op-e2e/actions/interop/dsl/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,29 @@ func (m *GeneratedTransaction) MessagePayload() []byte {
return stypes.LogToMessagePayload(m.rcpt.Logs[0])
}

func (m *GeneratedTransaction) CheckIncluded() {
type CheckIncludedOpts struct {
ExpectRevert bool
}

func WithRevertExpected() func(*CheckIncludedOpts) {
return func(opts *CheckIncludedOpts) {
opts.ExpectRevert = true
}
}

func (m *GeneratedTransaction) CheckIncluded(args ...func(opts *CheckIncludedOpts)) {
opts := CheckIncludedOpts{}
for _, arg := range args {
arg(&opts)
}
rcpt, err := m.chain.SequencerEngine.EthClient().TransactionReceipt(m.t.Ctx(), m.tx.Hash())
require.NoError(m.t, err, "Transaction should have been included")
require.NotNil(m.t, rcpt, "No receipt found")
if opts.ExpectRevert {
require.Equal(m.t, types.ReceiptStatusFailed, rcpt.Status, "Expected tx to revert")
} else {
require.Equal(m.t, types.ReceiptStatusSuccessful, rcpt.Status, "Expected tx to be successful")
}
}

func (m *GeneratedTransaction) CheckNotIncluded() {
Expand Down
96 changes: 96 additions & 0 deletions op-e2e/actions/interop/proofs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,102 @@ func TestInteropFaultProofs_ConsolidateValidCrossChainMessage(gt *testing.T) {
runFppAndChallengerTests(gt, system, tests)
}

func TestInteropFaultProofs_PreForkActivation(gt *testing.T) {
t := helpers.NewDefaultTesting(gt)
system := dsl.NewInteropDSL(t, dsl.SetInteropForkScheduledButInactive())

actors := system.Actors
endTimestamp := actors.ChainA.RollupCfg.Genesis.L2Time + actors.ChainA.RollupCfg.BlockTime
startTimestamp := endTimestamp - 1
require.False(t, actors.ChainA.RollupCfg.IsInterop(endTimestamp), "Interop should not be active")

alice := system.CreateUser()
emitter := system.DeployEmitterContracts()

system.AddL2Block(system.Actors.ChainA, dsl.WithL2BlockTransactions(emitter.EmitMessage(alice, "hello")))
initMsg := emitter.LastEmittedMessage()
system.AddL2Block(system.Actors.ChainB,
dsl.WithL2BlockTransactions(system.InboxContract.Execute(alice, initMsg,
dsl.WithPayload([]byte("wrong")),
// CrossL2Inbox contract isn't deployed so the tx will revert. Need to avoid using eth_estimateGas
dsl.WithFixedGasLimit())))
system.InboxContract.LastTransaction().CheckIncluded(dsl.WithRevertExpected())

// Submit batch data for each chain in separate L1 blocks so tests can have one chain safe and one unsafe
system.SubmitBatchData(func(opts *dsl.SubmitBatchDataOpts) {
opts.SetChains(system.Actors.ChainA)
})
system.SubmitBatchData(func(opts *dsl.SubmitBatchDataOpts) {
opts.SetChains(system.Actors.ChainB)
})
// Check that the supervisor didn't re-org out this transaction.
// Interop isn't active yet so the extra derivation rules to validate executing messages must not be active.
system.InboxContract.LastTransaction().CheckIncluded(dsl.WithRevertExpected())

start := system.Outputs.SuperRoot(startTimestamp)
end := system.Outputs.SuperRoot(endTimestamp)

step1Expected := system.Outputs.TransitionState(startTimestamp, 1,
system.Outputs.OptimisticBlockAtTimestamp(actors.ChainA, endTimestamp),
).Marshal()

step2Expected := system.Outputs.TransitionState(startTimestamp, 2,
system.Outputs.OptimisticBlockAtTimestamp(actors.ChainA, endTimestamp),
system.Outputs.OptimisticBlockAtTimestamp(actors.ChainB, endTimestamp),
).Marshal()

firstPaddingStep := system.Outputs.TransitionState(startTimestamp, 3,
system.Outputs.OptimisticBlockAtTimestamp(actors.ChainA, endTimestamp),
system.Outputs.OptimisticBlockAtTimestamp(actors.ChainB, endTimestamp),
).Marshal()

lastPaddingStep := system.Outputs.TransitionState(startTimestamp, consolidateStep,
system.Outputs.OptimisticBlockAtTimestamp(actors.ChainA, endTimestamp),
system.Outputs.OptimisticBlockAtTimestamp(actors.ChainB, endTimestamp),
).Marshal()

tests := []*transitionTest{
{
name: "FirstChainOptimisticBlock",
agreedClaim: start.Marshal(),
disputedClaim: step1Expected,
disputedTraceIndex: 0,
expectValid: true,
startTimestamp: startTimestamp,
proposalTimestamp: endTimestamp,
},
{
name: "SecondChainOptimisticBlock",
agreedClaim: step1Expected,
disputedClaim: step2Expected,
disputedTraceIndex: 1,
expectValid: true,
startTimestamp: startTimestamp,
proposalTimestamp: endTimestamp,
},
{
name: "FirstPaddingStep",
agreedClaim: step2Expected,
disputedClaim: firstPaddingStep,
disputedTraceIndex: 2,
expectValid: true,
startTimestamp: startTimestamp,
proposalTimestamp: endTimestamp,
},
{
name: "Consolidate",
agreedClaim: lastPaddingStep,
disputedClaim: end.Marshal(),
disputedTraceIndex: consolidateStep,
expectValid: true,
startTimestamp: startTimestamp,
proposalTimestamp: endTimestamp,
},
}

runFppAndChallengerTests(gt, system, tests)
}

func TestInteropFaultProofs(gt *testing.T) {
t := helpers.NewDefaultTesting(gt)
system := dsl.NewInteropDSL(t)
Expand Down