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 espresso/.env
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ ESPRESSO_ATTESTATION_VERIFIER_NETWORK_PRIVATE_KEY="0x71f8e55f7555c946eadd5a2b589
ESPRESSO_ATTESTATION_VERIFIER_NETWORK_RPC_URL="https://rpc.mainnet.succinct.xyz"
ESPRESSO_ATTESTATION_VERIFIER_NETWORK_USE_DOCKER=1
ESPRESSO_ATTESTATION_VERIFIER_RUST_LOG="info"
ESPRESSO_ATTESTATION_VERIFIER_DOCKER_IMAGE="ghcr.io/espressosystems/attestation-verifier-zk:sha-0e987c3"
ESPRESSO_ATTESTATION_VERIFIER_DOCKER_IMAGE="ghcr.io/espressosystems/attestation-verifier-zk:sha-f5d0a46"

L1_ENGINE_PORT=8551
L1_HTTP_PORT=8545
Expand Down
57 changes: 57 additions & 0 deletions espresso/environment/14_batcher_fallback_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package environment_test

import (
"context"
"testing"

env "github.com/ethereum-optimism/optimism/espresso/environment"
"github.com/ethereum-optimism/optimism/op-batcher/bindings"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-e2e/system/e2esys"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/stretchr/testify/require"
)

func TestBatcherSwitching(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

launcher := new(env.EspressoDevNodeLauncherDocker)

system, espressoDevNode, err := launcher.StartE2eDevnet(ctx, t)
require.NoError(t, err)

l1Client := system.NodeClient(e2esys.RoleL1)

defer env.Stop(t, system)
defer env.Stop(t, espressoDevNode)

// Send Transaction on L1, and wait for verification on the L2 Verifier
env.RunSimpleL1TransferAndVerifier(ctx, t, system)

// Verify everything works
env.RunSimpleL2Burn(ctx, t, system)

// Stop the "TEE" batcher
err = system.BatchSubmitter.TestDriver().StopBatchSubmitting(ctx)
require.NoError(t, err)

// Switch active batcher
options, err := bind.NewKeyedTransactorWithChainID(system.Config().Secrets.Deployer, system.Cfg.L1ChainIDBig())
require.NoError(t, err)

batchAuthenticator, err := bindings.NewBatchAuthenticator(system.RollupConfig.BatchAuthenticatorAddress, l1Client)
require.NoError(t, err)

tx, err := batchAuthenticator.SwitchBatcher(options)
require.NoError(t, err)
_, err = wait.ForReceiptOK(ctx, l1Client, tx.Hash())
require.NoError(t, err)

// Start the fallback batcher
err = system.FallbackBatchSubmitter.TestDriver().StartBatchSubmitting()
require.NoError(t, err)

// Everything should still work
env.RunSimpleL2Burn(ctx, t, system)
}
10 changes: 5 additions & 5 deletions espresso/environment/optitmism_espresso_test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,10 +285,11 @@ func (l *EspressoDevNodeLauncherDocker) GetE2eDevnetSysConfig(ctx context.Contex
// Ensure that we fund the dev accounts
sysConfig.DeployConfig.FundDevAccounts = true

espressoPremine := new(big.Int).Mul(new(big.Int).SetUint64(1_000_000), new(big.Int).SetUint64(params.Ether))
millionEthers := new(big.Int).Mul(new(big.Int).SetUint64(1_000_000), new(big.Int).SetUint64(params.Ether))

sysConfig.L1Allocs[ESPRESSO_CONTRACT_ACCOUNT] = types.Account{
Nonce: 100000, // Set the nonce to avoid collisions with predeployed contracts
Balance: espressoPremine, // Pre-fund Espresso deployer acount with 1M Ether
Nonce: 100000, // Set the nonce to avoid collisions with predeployed contracts
Balance: millionEthers, // Pre-fund Espresso deployer acount with 1M Ether
}

//Set up the L1Allocs in the system config
Expand Down Expand Up @@ -958,8 +959,7 @@ func launchEspressoAttestationVerifierService(ct *E2eDevnetLauncherContext, c *b
Ports: []string{
espressoAttestationVerifierPort,
},
Name: "attestation-verifier-zk",
Platform: "linux/amd64",
Name: "attestation-verifier-zk",
Environment: map[string]string{
"NETWORK_RPC_URL": espressoAttestationVerifierNetworkRPCURL,
"SP1_PROVER": espressoAttestationVerifierSp1Prover,
Expand Down
58 changes: 25 additions & 33 deletions espresso/environment/tx_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"

"math/big"
"testing"
Expand Down Expand Up @@ -42,8 +43,6 @@ func RunSimpleL2Transfer(

t.Log("Receipt", receipt)

cancel()

txHash := receipt.TxHash

return txHash
Expand Down Expand Up @@ -72,28 +71,18 @@ func RunSimpleL1TransferAndVerifier(ctx context.Context, t *testing.T, system *e

// Create a new Keyed Transaction
options, err := bind.NewKeyedTransactorWithChainID(privateKey, system.Cfg.L1ChainIDBig())
if have, want := err, error(nil); have != want {
t.Errorf("attempt to get keyed transaction with chain ID %d failed:\nhave:\n\t\"%v\"\nwant:\n\t\"%v\"\n", system.Cfg.L1ChainIDBig(), have, want)
}
require.NoError(t, err, "failed to create keyed transaction with chain ID %d", system.Cfg.L1ChainIDBig())

if err == nil {
// We can only continue with these tests if the error above was nil
// Send a Deposit Transaction
mintAmount := big.NewInt(1_000_000_000_000)
options.Value = mintAmount
_ = helpers.SendDepositTx(t, system.Cfg, l1Client, l2Verif, options, nil)

// Send a Deposit Transaction
mintAmount := big.NewInt(1_000_000_000_000)
options.Value = mintAmount
_ = helpers.SendDepositTx(t, system.Cfg, l1Client, l2Verif, options, nil)
endBalance, err := wait.ForBalanceChange(ctx, l2Verif, fromAddress, startBalance)
require.NoError(t, err, "waiting for balance change failed")

endBalance, err := wait.ForBalanceChange(ctx, l2Verif, fromAddress, startBalance)
if have, want := err, error(nil); have != want {
t.Errorf("waiting for balance change returned with error:\nhave:\n\t\"%v\"\nwant:\t\n\"%v\"\n", have, want)
}

diff := new(big.Int).Sub(endBalance, startBalance)
if have, want := diff, mintAmount; have.Cmp(want) != 0 {
t.Errorf("balance change does not match mint amount:\nhave;\n\t\"%s\"\nwant:\n\t\"%s\"\n", have, want)
}
}
diff := new(big.Int).Sub(endBalance, startBalance)
require.Equal(t, diff, mintAmount, "balance change does not match mint amount")

cancel()
}
Expand All @@ -104,36 +93,39 @@ func RunSimpleL2Burn(ctx context.Context, t *testing.T, system *e2esys.System) {
ctx, cancel := context.WithTimeout(ctx, 2*time.Minute)
defer cancel()

privateKey := system.Cfg.Secrets.Bob

l2Seq := system.NodeClient(e2esys.RoleSeq)
l2Verif := system.NodeClient(e2esys.RoleVerif)

amountToBurn := big.NewInt(500_000_000)
senderKey := system.Cfg.Secrets.Bob
senderAddress := system.Cfg.Secrets.Addresses().Bob
amountToBurn := big.NewInt(1234)
burnAddress := common.Address{0xff, 0xff}

nonce, err := l2Seq.NonceAt(ctx, senderAddress, nil)
require.NoError(t, err, "failed to get nonce for account %s", senderAddress)

initialBurnAddressBalance, err := l2Seq.BalanceAt(ctx, burnAddress, nil)
require.NoError(t, err, "failed to get initial balance for burn address %s", burnAddress)

_ = helpers.SendL2Tx(
t,
system.Cfg,
l2Seq,
privateKey,
senderKey,
L2TxWithOptions(
L2TxWithAmount(amountToBurn),
L2TxWithNonce(1), // Already have deposit
L2TxWithNonce(nonce),
L2TxWithToAddress(&burnAddress),
L2TxWithVerifyOnClients(l2Verif),
),
)

// Check the balance of hte burn address using the L2 Verifier
balanceBurned, err := wait.ForBalanceChange(ctx, l2Verif, burnAddress, big.NewInt(0))
if have, want := err, error(nil); have != want {
t.Errorf("wait for balance change for burn address %s failed:\nhave:\n\t\"%v\"\nwant:\n\t\"%v\"\n", burnAddress, have, want)
}
burnAddressBalance, err := wait.ForBalanceChange(ctx, l2Verif, burnAddress, initialBurnAddressBalance)
require.NoError(t, err, "burn address balance didn't change")

// Make sure that these match
if have, want := balanceBurned, amountToBurn; have.Cmp(want) != 0 {
t.Errorf("balance of burn address does not match amount burned:\nhave:\n\t\"%s\"\nwant:\n\t\"%s\"\n", have, want)
}
require.Equal(t, new(big.Int).Sub(burnAddressBalance, initialBurnAddressBalance), amountToBurn, "burn address balance doesn't match the amount burned")

cancel()
}
8 changes: 0 additions & 8 deletions op-batcher/batcher/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
Expand Down Expand Up @@ -1044,13 +1043,6 @@ func (l *BatchSubmitter) sendTx(txdata txData, isCancel bool, candidate *txmgr.T
)
return
}
floorDataGas, err := core.FloorDataGas(candidate.TxData)
if err != nil {
// We log instead of return an error here because the txmgr will do its own gas estimation.
l.Log.Warn("Failed to calculate floor data gas", "err", err)
} else {
candidate.GasLimit = floorDataGas
}

queue.Send(txRef{id: txdata.ID(), isCancel: isCancel, isBlob: txdata.daType == DaTypeBlob, daType: txdata.daType, size: txdata.Len()}, *candidate, receiptsCh)
}
Expand Down
8 changes: 8 additions & 0 deletions op-batcher/batcher/espresso.go
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,14 @@ func (l *BatchSubmitter) espressoBatchQueueingLoop(ctx context.Context, wg *sync
batcher: l,
}

// *
// * BEFORE we start:
// * - scan batchInbox from batchInbox.lastBackfilled
// * - enqueue all batches from batchInbox that are _by fallback batcher_ to Espresso
// * - wait for espresso queue to clear
// * - set lastBackfilled to block height of the last of such batches
// *

for {
select {
case <-ticker.C:
Expand Down
9 changes: 5 additions & 4 deletions op-deployer/pkg/deployer/opcm/espresso.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ type DeployAWSNitroVerifierOutput struct {
}

type DeployEspressoInput struct {
Salt common.Hash
NitroTEEVerifier common.Address
NonTeeBatcher common.Address
TeeBatcher common.Address
Salt common.Hash
NitroTEEVerifier common.Address
NonTeeBatcher common.Address
TeeBatcher common.Address
PreRegisteredBatcher common.Address
}

type DeployEspressoOutput struct {
Expand Down
9 changes: 5 additions & 4 deletions op-deployer/pkg/deployer/pipeline/espresso.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,11 @@ func DeployEspresso(env *Env, intent *state.Intent, st *state.State, chainID com
}

eo, err = opcm.DeployEspresso(env.L1ScriptHost, opcm.DeployEspressoInput{
Salt: st.Create2Salt,
NitroTEEVerifier: nvo.NitroTEEVerifierAddress,
NonTeeBatcher: chainIntent.NonTeeBatcher,
TeeBatcher: chainIntent.TeeBatcher,
Salt: st.Create2Salt,
NitroTEEVerifier: nvo.NitroTEEVerifierAddress,
NonTeeBatcher: chainIntent.NonTeeBatcher,
TeeBatcher: chainIntent.TeeBatcher,
PreRegisteredBatcher: chainIntent.PreRegisteredBatcher,
}, batchAuthenticatorOwnwerAddress)
if err != nil {
return fmt.Errorf("failed to deploy espresso contracts: %w", err)
Expand Down
7 changes: 4 additions & 3 deletions op-deployer/pkg/deployer/state/chain_intent.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ type ChainIntent struct {
L2DevGenesisParams *L2DevGenesisParams `json:"l2DevGenesisParams,omitempty" toml:"l2DevGenesisParams,omitempty"`

// Espresso-specific fields
EspressoEnabled bool `json:"espressoEnabled,omitzero" toml:"espressoEnabled,omitzero"`
NonTeeBatcher common.Address `json:"nonTeeBatcher,omitzero" toml:"nonTeeBatcher,omitzero"`
TeeBatcher common.Address `json:"teeBatcher,omitzero" toml:"teeBatcher,omitzero"`
EspressoEnabled bool `json:"espressoEnabled,omitzero" toml:"espressoEnabled,omitzero"`
NonTeeBatcher common.Address `json:"nonTeeBatcher,omitzero" toml:"nonTeeBatcher,omitzero"`
TeeBatcher common.Address `json:"teeBatcher,omitzero" toml:"teeBatcher,omitzero"`
PreRegisteredBatcher common.Address `json:"preRegisteredBatcher,omitzero" toml:"preRegisteredBatcher,omitzero"`
}

type ChainRoles struct {
Expand Down
44 changes: 36 additions & 8 deletions op-e2e/config/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
"golang.org/x/exp/maps"

"github.com/ethereum-optimism/optimism/op-e2e/config/secrets"
Expand All @@ -37,6 +39,9 @@ import (
)

const ESPRESSO_NON_TEE_BATCHER_PRIVATE_KEY = "5fede428b9506dee864b0d85aefb2409f4728313eb41da4121409299c487f816"
const ESPRESSO_TESTING_BATCHER_EPHEMERAL_KEY = "404520dcd0335deccd7d4a01f29136dfd651b89ec3969d53a06c3cc5aae5f515"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this key computed?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a random one.


var ESPRESSO_NON_TEE_BATCHER_ADDRESS = common.HexToAddress("0x78A424C38759DDA4A4F349e661Aa3523CFf3BacB")

// legacy geth log levels - the geth command line --verbosity flag wasn't
// migrated to use slog's numerical levels.
Expand All @@ -58,7 +63,6 @@ const (
AllocTypeL2OO AllocType = "l2oo"
AllocTypeMTCannon AllocType = "mt-cannon"
AllocTypeMTCannonNext AllocType = "mt-cannon-next"
AllocTypeEspresso AllocType = "espresso"
AllocTypeEspressoWithoutEnclave AllocType = "espresso-no-enclave"
AllocTypeEspressoWithEnclave AllocType = "espresso-enclave"

Expand All @@ -74,14 +78,18 @@ func (a AllocType) Check() error {

func (a AllocType) UsesProofs() bool {
switch a {
case AllocTypeStandard, AllocTypeMTCannon, AllocTypeMTCannonNext, AllocTypeAltDA, AllocTypeAltDAGeneric, AllocTypeEspresso, AllocTypeEspressoWithEnclave, AllocTypeEspressoWithoutEnclave:
case AllocTypeStandard, AllocTypeMTCannon, AllocTypeMTCannonNext, AllocTypeAltDA, AllocTypeAltDAGeneric, AllocTypeEspressoWithEnclave, AllocTypeEspressoWithoutEnclave:
return true
default:
return false
}
}

var allocTypes = []AllocType{AllocTypeStandard, AllocTypeAltDA, AllocTypeAltDAGeneric, AllocTypeL2OO, AllocTypeMTCannon, AllocTypeEspresso, AllocTypeMTCannonNext, AllocTypeEspressoWithEnclave, AllocTypeEspressoWithoutEnclave}
func (a AllocType) IsEspresso() bool {
return a == AllocTypeEspressoWithEnclave || a == AllocTypeEspressoWithoutEnclave
}

var allocTypes = []AllocType{AllocTypeStandard, AllocTypeAltDA, AllocTypeAltDAGeneric, AllocTypeL2OO, AllocTypeMTCannon, AllocTypeMTCannonNext, AllocTypeEspressoWithEnclave, AllocTypeEspressoWithoutEnclave}

var (
// All of the following variables are set in the init function
Expand Down Expand Up @@ -288,14 +296,34 @@ func initAllocType(root string, allocType AllocType) {
}

// Configure Espresso allocation types
if allocType == AllocTypeEspressoWithoutEnclave || allocType == AllocTypeEspressoWithEnclave {
batcherPk, err := crypto.HexToECDSA(ESPRESSO_NON_TEE_BATCHER_PRIVATE_KEY)
if allocType.IsEspresso() {
intent.Chains[0].EspressoEnabled = true
intent.Chains[0].TeeBatcher = intent.Chains[0].Roles.Batcher

nonTeeBatcherPk, err := crypto.HexToECDSA(ESPRESSO_NON_TEE_BATCHER_PRIVATE_KEY)
if err != nil {
panic(fmt.Errorf("failed to parse batcher private key: %w", err))
}
intent.Chains[0].EspressoEnabled = true
intent.Chains[0].NonTeeBatcher = crypto.PubkeyToAddress(batcherPk.PublicKey)
intent.Chains[0].TeeBatcher = crypto.PubkeyToAddress(batcherPk.PublicKey)
nonTeeBatcherAddr := crypto.PubkeyToAddress(nonTeeBatcherPk.PublicKey)
intent.Chains[0].NonTeeBatcher = nonTeeBatcherAddr

// Fund the fallback batcher
if intent.L1DevGenesisParams == nil {
intent.L1DevGenesisParams = &state.L1DevGenesisParams{}
}
if intent.L1DevGenesisParams.Prefund == nil {
intent.L1DevGenesisParams.Prefund = make(map[common.Address]*hexutil.U256)
}
millionEth := (*hexutil.U256)(new(uint256.Int).Mul(uint256.NewInt(1_000_000), uint256.NewInt(params.Ether)))
intent.L1DevGenesisParams.Prefund[nonTeeBatcherAddr] = millionEth
}

if allocType == AllocTypeEspressoWithoutEnclave {
ephemeralPk, err := crypto.HexToECDSA(ESPRESSO_TESTING_BATCHER_EPHEMERAL_KEY)
if err != nil {
panic(fmt.Errorf("failed to parse batcher private key: %w", err))
}
intent.Chains[0].PreRegisteredBatcher = crypto.PubkeyToAddress(ephemeralPk.PublicKey)
}

baseUpgradeSchedule := map[string]any{
Expand Down
Loading
Loading