diff --git a/.github/workflows/espresso-devnet-tests.yaml b/.github/workflows/espresso-devnet-tests.yaml index 269ce8b89fccf..c8ffee2e326ff 100644 --- a/.github/workflows/espresso-devnet-tests.yaml +++ b/.github/workflows/espresso-devnet-tests.yaml @@ -41,7 +41,7 @@ jobs: - name: Compile contracts run: just compile-contracts - - name: Build Devnet + - name: Build Devnet without TEE run: | cd op-deployer just @@ -51,16 +51,22 @@ jobs: docker compose build docker compose pull l1-validator espresso-dev-node l1-data-init - - name: Run Smoke test - run: go test -timeout 30m -p 1 -count 1 -run 'TestSmoke' -v ./espresso/devnet-tests/... + - name: Run Smoke test without TEE + run: go test -timeout 30m -p 1 -count 1 -run 'TestSmokeWithoutTEE' -v ./espresso/devnet-tests/... - name: Run Challenge Game test run: go test -timeout 30m -p 1 -count 1 -run 'TestChallengeGame' -v ./espresso/devnet-tests/... - - name: Run Withdraw test run: go test -timeout 30m -p 1 -count 1 -run 'TestWithdrawal' -v ./espresso/devnet-tests/... + - name: Build Devnet with TEE + run: | + cd espresso + COMPOSE_PROFILES=tee docker compose build + + - name: Run Smoke test with TEE + run: go test -timeout 30m -p 1 -count 1 -run 'TestSmokeWithTEE' -v ./espresso/devnet-tests/... - name: Save Nix cache uses: nix-community/cache-nix-action/save@v6 diff --git a/espresso/devnet-tests/batcher_restart_test.go b/espresso/devnet-tests/batcher_restart_test.go index 2088f317e880a..8b5835fd19df7 100644 --- a/espresso/devnet-tests/batcher_restart_test.go +++ b/espresso/devnet-tests/batcher_restart_test.go @@ -13,19 +13,19 @@ func TestBatcherRestart(t *testing.T) { defer cancel() d := NewDevnet(ctx, t) - require.NoError(t, d.Up()) + require.NoError(t, d.Up(false)) defer func() { require.NoError(t, d.Down()) }() // Send a transaction just to check that everything has started up ok. - require.NoError(t, d.RunSimpleL2Burn()) + require.NoError(t, d.RunSimpleL2Burn(false)) // Shut down the batcher and have another transaction submitted while it is down. require.NoError(t, d.ServiceDown("op-batcher")) d.SleepOutageDuration() - receipt, err := d.SubmitSimpleL2Burn() + receipt, err := d.SubmitSimpleL2Burn(false) require.NoError(t, err) // Check that while the batcher is down, the verifier does NOT process submitted transactions. @@ -36,9 +36,9 @@ func TestBatcherRestart(t *testing.T) { // Bring the batcher back up and check that it processes the transaction which was submitted // while it was down. require.NoError(t, d.ServiceUp("op-batcher")) - require.NoError(t, d.VerifySimpleL2Burn(receipt)) + require.NoError(t, d.VerifySimpleL2Burn(receipt, false)) // Submit another transaction at the end just to check that things stay working. d.SleepRecoveryDuration() - require.NoError(t, d.RunSimpleL2Burn()) + require.NoError(t, d.RunSimpleL2Burn(false)) } diff --git a/espresso/devnet-tests/challenge_test.go b/espresso/devnet-tests/challenge_test.go index b4ca7d6151670..9fdc389f366c7 100644 --- a/espresso/devnet-tests/challenge_test.go +++ b/espresso/devnet-tests/challenge_test.go @@ -13,7 +13,7 @@ func TestChallengeGame(t *testing.T) { defer cancel() d := NewDevnet(ctx, t) - require.NoError(t, d.Up()) + require.NoError(t, d.Up(false)) defer func() { require.NoError(t, d.Down()) }() diff --git a/espresso/devnet-tests/devnet_tools.go b/espresso/devnet-tests/devnet_tools.go index c83aab3c9775f..d561a8c547994 100644 --- a/espresso/devnet-tests/devnet_tools.go +++ b/espresso/devnet-tests/devnet_tools.go @@ -97,7 +97,7 @@ func (d *Devnet) isRunning() bool { return len(out) > 0 } -func (d *Devnet) Up() (err error) { +func (d *Devnet) Up(tee bool) (err error) { if d.isRunning() { if err := d.Down(); err != nil { return err @@ -111,6 +111,9 @@ func (d *Devnet) Up() (err error) { d.ctx, "docker", "compose", "up", "-d", ) + if tee { + cmd.Env = append(os.Environ(), "COMPOSE_PROFILES=tee") + } cmd.Env = append( cmd.Env, fmt.Sprintf("OP_BATCHER_PRIVATE_KEY=%s", hex.EncodeToString(crypto.FromECDSA(d.secrets.Batcher))), @@ -229,8 +232,12 @@ func (d *Devnet) SystemConfig(ctx context.Context) (*bindings.SystemConfig, *bin } // Submits a transaction and waits until it is confirmed by the sequencer (but not necessarily the verifier). -func (d *Devnet) SubmitL2Tx(applyTxOpts helpers.TxOptsFn) (*types.Receipt, error) { - ctx, cancel := context.WithTimeout(d.ctx, 3*time.Minute) +func (d *Devnet) SubmitL2Tx(applyTxOpts helpers.TxOptsFn, tee bool) (*types.Receipt, error) { + timeout := 3 * time.Minute + if tee { + timeout = 20 * time.Minute + } + ctx, cancel := context.WithTimeout(d.ctx, timeout) defer cancel() chainID, err := d.L2Seq.ChainID(ctx) @@ -310,8 +317,8 @@ func (d *Devnet) VerifyL2Tx(receipt *types.Receipt) error { } // Submits a transaction and waits for it to be verified. -func (d *Devnet) RunL2Tx(applyTxOpts helpers.TxOptsFn) error { - receipt, err := d.SubmitL2Tx(applyTxOpts) +func (d *Devnet) RunL2Tx(applyTxOpts helpers.TxOptsFn, tee bool) error { + receipt, err := d.SubmitL2Tx(applyTxOpts, tee) if err != nil { return err } @@ -335,7 +342,7 @@ type BurnReceipt struct { } // Submits a burn transaction and waits until it is confirmed by the sequencer (but not necessarily the verifier). -func (d *Devnet) SubmitSimpleL2Burn() (*BurnReceipt, error) { +func (d *Devnet) SubmitSimpleL2Burn(tee bool) (*BurnReceipt, error) { var err error receipt := new(BurnReceipt) @@ -352,15 +359,19 @@ func (d *Devnet) SubmitSimpleL2Burn() (*BurnReceipt, error) { env.L2TxWithToAddress(&receipt.BurnAddress), env.L2TxWithVerifyOnClients(d.L2Verif), ) - if receipt.Receipt, err = d.SubmitL2Tx(tx); err != nil { + if receipt.Receipt, err = d.SubmitL2Tx(tx, tee); err != nil { return nil, err } return receipt, nil } // Waits for a previously submitted burn transaction to be confirmed by the verifier. -func (d *Devnet) VerifySimpleL2Burn(receipt *BurnReceipt) error { - ctx, cancel := context.WithTimeout(d.ctx, 2*time.Minute) +func (d *Devnet) VerifySimpleL2Burn(receipt *BurnReceipt, tee bool) error { + timeout := 2 * time.Minute + if tee { + timeout = 20 * time.Minute + } + ctx, cancel := context.WithTimeout(d.ctx, timeout) defer cancel() if err := d.VerifyL2Tx(receipt.Receipt); err != nil { @@ -381,12 +392,12 @@ func (d *Devnet) VerifySimpleL2Burn(receipt *BurnReceipt) error { } // RunSimpleL2Burn runs a simple L2 burn transaction and verifies it on the L2 Verifier. -func (d *Devnet) RunSimpleL2Burn() error { - receipt, err := d.SubmitSimpleL2Burn() +func (d *Devnet) RunSimpleL2Burn(tee bool) error { + receipt, err := d.SubmitSimpleL2Burn(tee) if err != nil { return err } - return d.VerifySimpleL2Burn(receipt) + return d.VerifySimpleL2Burn(receipt, tee) } // Wait for a configurable amount of time while simulating an outage. @@ -424,7 +435,37 @@ func (d *Devnet) Down() error { d.ctx, "docker", "compose", "down", "-v", "--remove-orphans", "--timeout", "10", ) - return cmd.Run() + if err := cmd.Run(); err != nil { + return fmt.Errorf("failed to shut down docker: %w", err) + } + + outBatcher, _ := exec.Command("docker", "ps", "-q", "--filter", "ancestor=op-batcher-tee:espresso").Output() + batcherContainers := strings.Fields(string(outBatcher)) + if len(batcherContainers) > 0 { + cmd = exec.Command("docker", append([]string{"stop"}, batcherContainers...)...) + if err := cmd.Run(); err != nil { + return fmt.Errorf("failed to stop the batcher container: %w", err) + } + cmd = exec.Command("docker", append([]string{"rm"}, batcherContainers...)...) + if err := cmd.Run(); err != nil { + return fmt.Errorf("failed to remove the batcher container: %w", err) + } + } + + outEnclave, _ := exec.Command("docker", "ps", "-aq", "--filter", "name=batcher-enclaver-").Output() + enclaveContainers := strings.Fields(string(outEnclave)) + if len(enclaveContainers) > 0 { + cmd = exec.Command("docker", append([]string{"stop"}, enclaveContainers...)...) + if err := cmd.Run(); err != nil { + return fmt.Errorf("failed to stop the enclave container: %w", err) + } + cmd = exec.Command("docker", append([]string{"rm"}, enclaveContainers...)...) + if err := cmd.Run(); err != nil { + return fmt.Errorf("failed to remove the enclave container: %w", err) + } + } + + return nil } type TaggedWriter struct { diff --git a/espresso/devnet-tests/key_rotation_test.go b/espresso/devnet-tests/key_rotation_test.go index e9d3084b751c0..29b24d005b6c0 100644 --- a/espresso/devnet-tests/key_rotation_test.go +++ b/espresso/devnet-tests/key_rotation_test.go @@ -19,13 +19,13 @@ func TestRotateBatcherKey(t *testing.T) { // We're going to change batcher key to Bob's, verify that it won't be a no-op require.NotEqual(t, d.secrets.Batcher, d.secrets.Bob) - require.NoError(t, d.Up()) + require.NoError(t, d.Up(false)) defer func() { require.NoError(t, d.Down()) }() // Send a transaction just to check that everything has started up ok. - require.NoError(t, d.RunSimpleL2Burn()) + require.NoError(t, d.RunSimpleL2Burn(false)) // Shut down the batcher require.NoError(t, d.ServiceDown("op-batcher")) @@ -48,7 +48,7 @@ func TestRotateBatcherKey(t *testing.T) { d.SleepOutageDuration() // Send a transaction to check the L2 still runs - require.NoError(t, d.RunSimpleL2Burn()) + require.NoError(t, d.RunSimpleL2Burn(false)) } func TestChangeBatchInboxOwner(t *testing.T) { @@ -57,13 +57,13 @@ func TestChangeBatchInboxOwner(t *testing.T) { d := NewDevnet(ctx, t) - require.NoError(t, d.Up()) + require.NoError(t, d.Up(false)) defer func() { require.NoError(t, d.Down()) }() // Send a transaction just to check that everything has started up ok. - require.NoError(t, d.RunSimpleL2Burn()) + require.NoError(t, d.RunSimpleL2Burn(false)) config, err := d.RollupConfig(ctx) require.NoError(t, err) @@ -82,5 +82,5 @@ func TestChangeBatchInboxOwner(t *testing.T) { require.Equal(t, newOwner, d.secrets.Addresses().Bob) // Check that everything still functions - require.NoError(t, d.RunSimpleL2Burn()) + require.NoError(t, d.RunSimpleL2Burn(false)) } diff --git a/espresso/devnet-tests/smoke_test.go b/espresso/devnet-tests/smoke_test.go index 1e562d18f35bc..3b1a44044de83 100644 --- a/espresso/devnet-tests/smoke_test.go +++ b/espresso/devnet-tests/smoke_test.go @@ -8,16 +8,30 @@ import ( "github.com/stretchr/testify/require" ) -func TestSmoke(t *testing.T) { +func TestSmokeWithoutTEE(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute) defer cancel() d := NewDevnet(ctx, t) - require.NoError(t, d.Up()) + require.NoError(t, d.Up(false)) defer func() { require.NoError(t, d.Down()) }() // Send a transaction just to check that everything has started up ok. - require.NoError(t, d.RunSimpleL2Burn()) + require.NoError(t, d.RunSimpleL2Burn(false)) +} + +func TestSmokeWithTEE(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute) + defer cancel() + + d := NewDevnet(ctx, t) + require.NoError(t, d.Up(true)) + defer func() { + require.NoError(t, d.Down()) + }() + + // Send a transaction just to check that everything has started up ok. + require.NoError(t, d.RunSimpleL2Burn(true)) } diff --git a/espresso/devnet-tests/withdraw_test.go b/espresso/devnet-tests/withdraw_test.go index 69c9942d334c4..b376286c999a4 100644 --- a/espresso/devnet-tests/withdraw_test.go +++ b/espresso/devnet-tests/withdraw_test.go @@ -296,7 +296,7 @@ func TestWithdrawal(t *testing.T) { defer cancel() d := NewDevnet(ctx, t) - require.NoError(t, d.Up()) + require.NoError(t, d.Up(false)) defer func() { require.NoError(t, d.Down()) }() @@ -304,7 +304,7 @@ func TestWithdrawal(t *testing.T) { aliceAddress := crypto.PubkeyToAddress(d.secrets.Alice.PublicKey) // Verify devnet is running - require.NoError(t, d.RunSimpleL2Burn()) + require.NoError(t, d.RunSimpleL2Burn(false)) // Verify Alice has L2 balance userBalance, err := d.L2Verif.BalanceAt(ctx, aliceAddress, nil) diff --git a/justfile b/justfile index 7c843b43042f9..d76131b22743c 100644 --- a/justfile +++ b/justfile @@ -12,8 +12,8 @@ fast-tests: devnet-tests: build-devnet U_ID={{uid}} GID={{gid}} go test -timeout 30m -p 1 -count 1 -v ./espresso/devnet-tests/... -devnet-smoke-test: build-devnet - U_ID={{uid}} GID={{gid}} go test -timeout 30m -p 1 -count 1 -run 'TestSmoke' -v ./espresso/devnet-tests/... +devnet-smoke-test-without-tee: build-devnet + U_ID={{uid}} GID={{gid}} go test -timeout 30m -p 1 -count 1 -run 'TestSmokeWithoutTEE' -v ./espresso/devnet-tests/... devnet-withdrawal-test: build-devnet U_ID={{uid}} GID={{gid}} go test -timeout 30m -p 1 -count 1 -v -run TestWithdraw ./espresso/devnet-tests/...