From 56850bc3df6d983ad8b14fbdaeccfb725d618381 Mon Sep 17 00:00:00 2001 From: Javed Khan Date: Mon, 9 May 2022 11:27:33 -0400 Subject: [PATCH 1/3] simulators (op): use newly deployed contract addr --- simulators/optimism/devnet/ethclient.go | 12 ++++++++++++ simulators/optimism/devnet/helper.go | 19 ++++++++++--------- simulators/optimism/devnet/main.go | 1 + 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/simulators/optimism/devnet/ethclient.go b/simulators/optimism/devnet/ethclient.go index 9a9e829fbe..216da508ed 100644 --- a/simulators/optimism/devnet/ethclient.go +++ b/simulators/optimism/devnet/ethclient.go @@ -83,6 +83,16 @@ func genesisBlockByNumberTest(t *TestEnv) { } } +// CodeAtTest tests the code for the pre-deployed contract. +func CodeAtTest(t *TestEnv) { + code, err := t.Eth.CodeAt(t.Ctx(), t.deployedContractAddr, big0) + if err != nil { + t.Fatalf("Could not fetch code for predeployed contract: %v", err) + } + if bytes.Compare(runtimeCode, code) != 0 { + t.Fatalf("Unexpected code, want %x, got %x", runtimeCode, code) + } +} // deployContractTest deploys `contractSrc` and tests if the code and state // on the contract address contain the expected values (as set in the ctor). @@ -140,6 +150,8 @@ func deployContractTest(t *TestEnv) { t.Errorf("Unable to retrieve storage pos 0x01 on address %x: %v", contractAddress, err) } + t.deployedContractAddr = contractAddress + // test contract state, map on pos 1 with key myAccount must be 1234 storageKey := make([]byte, 64) copy(storageKey[12:32], address.Bytes()) diff --git a/simulators/optimism/devnet/helper.go b/simulators/optimism/devnet/helper.go index 17cc043833..0981c8546c 100644 --- a/simulators/optimism/devnet/helper.go +++ b/simulators/optimism/devnet/helper.go @@ -29,7 +29,8 @@ type TestEnv struct { Eth *ethclient.Client Vault *vault - genesis []byte + genesis []byte + deployedContractAddr common.Address // This holds most recent context created by the Ctx method. // Every time Ctx is called, it creates a new context with the default @@ -51,10 +52,10 @@ func runHTTP(t *hivesim.T, c *hivesim.Client, v *vault, g []byte, fn func(*TestE rpcClient, _ := rpc.DialHTTPWithClient(fmt.Sprintf("http://%v:9545/", c.IP), client) defer rpcClient.Close() env := &TestEnv{ - T: t, - RPC: rpcClient, - Eth: ethclient.NewClient(rpcClient), - Vault: v, + T: t, + RPC: rpcClient, + Eth: ethclient.NewClient(rpcClient), + Vault: v, genesis: g, } fn(env) @@ -74,10 +75,10 @@ func runWS(t *hivesim.T, c *hivesim.Client, v *vault, g []byte, fn func(*TestEnv defer rpcClient.Close() env := &TestEnv{ - T: t, - RPC: rpcClient, - Eth: ethclient.NewClient(rpcClient), - Vault: v, + T: t, + RPC: rpcClient, + Eth: ethclient.NewClient(rpcClient), + Vault: v, genesis: g, } fn(env) diff --git a/simulators/optimism/devnet/main.go b/simulators/optimism/devnet/main.go index cfd707fcb1..2ddc1d7963 100644 --- a/simulators/optimism/devnet/main.go +++ b/simulators/optimism/devnet/main.go @@ -20,6 +20,7 @@ var tests = []testSpec{ // HTTP RPC tests. {Name: "http/BalanceAndNonceAt", Run: balanceAndNonceAtTest}, {Name: "http/ContractDeployment", Run: deployContractTest}, + {Name: "http/CodeAt", Run: CodeAtTest}, {Name: "http/ContractDeploymentOutOfGas", Run: deployContractOutOfGasTest}, {Name: "http/GenesisBlockByHash", Run: genesisBlockByHashTest}, {Name: "http/GenesisBlockByNumber", Run: genesisBlockByNumberTest}, From 8c049d82731148c7f1e63a5de48cd5d34084b892 Mon Sep 17 00:00:00 2001 From: Javed Khan Date: Mon, 9 May 2022 17:15:46 -0400 Subject: [PATCH 2/3] simulator (op): setup - deploy contract --- simulators/optimism/devnet/ethclient.go | 18 +++---- simulators/optimism/devnet/helper.go | 41 +++++++-------- simulators/optimism/devnet/main.go | 66 +++++++++++++++++++++++-- 3 files changed, 90 insertions(+), 35 deletions(-) diff --git a/simulators/optimism/devnet/ethclient.go b/simulators/optimism/devnet/ethclient.go index 216da508ed..4d78f35ce9 100644 --- a/simulators/optimism/devnet/ethclient.go +++ b/simulators/optimism/devnet/ethclient.go @@ -85,7 +85,7 @@ func genesisBlockByNumberTest(t *TestEnv) { // CodeAtTest tests the code for the pre-deployed contract. func CodeAtTest(t *TestEnv) { - code, err := t.Eth.CodeAt(t.Ctx(), t.deployedContractAddr, big0) + code, err := t.Eth.CodeAt(t.Ctx(), t.Config.DeployedContractAddr, big0) if err != nil { t.Fatalf("Could not fetch code for predeployed contract: %v", err) } @@ -98,7 +98,7 @@ func CodeAtTest(t *TestEnv) { // on the contract address contain the expected values (as set in the ctor). func deployContractTest(t *TestEnv) { var ( - address = t.Vault.createAccount(t, big.NewInt(params.Ether)) + address = t.Config.Vault.createAccount(t, big.NewInt(params.Ether)) nonce = uint64(0) expectedContractAddress = crypto.CreateAddress(address, nonce) @@ -106,7 +106,7 @@ func deployContractTest(t *TestEnv) { ) rawTx := types.NewContractCreation(nonce, big0, gasLimit, gasPrice, deployCode) - deployTx, err := t.Vault.signTransaction(address, rawTx) + deployTx, err := t.Config.Vault.signTransaction(address, rawTx) if err != nil { t.Fatalf("Unable to sign deploy tx: %v", err) } @@ -150,8 +150,6 @@ func deployContractTest(t *TestEnv) { t.Errorf("Unable to retrieve storage pos 0x01 on address %x: %v", contractAddress, err) } - t.deployedContractAddr = contractAddress - // test contract state, map on pos 1 with key myAccount must be 1234 storageKey := make([]byte, 64) copy(storageKey[12:32], address.Bytes()) @@ -174,7 +172,7 @@ func deployContractTest(t *TestEnv) { // the contract address. func deployContractOutOfGasTest(t *TestEnv) { var ( - address = t.Vault.createAccount(t, big.NewInt(params.Ether)) + address = t.Config.Vault.createAccount(t, big.NewInt(params.Ether)) nonce = uint64(0) contractAddress = crypto.CreateAddress(address, nonce) gasLimit = uint64(240000) // insufficient gas @@ -183,7 +181,7 @@ func deployContractOutOfGasTest(t *TestEnv) { // Deploy the contract. rawTx := types.NewContractCreation(nonce, big0, gasLimit, gasPrice, deployCode) - deployTx, err := t.Vault.signTransaction(address, rawTx) + deployTx, err := t.Config.Vault.signTransaction(address, rawTx) if err != nil { t.Fatalf("unable to sign deploy tx: %v", err) } @@ -261,9 +259,9 @@ func newHeadSubscriptionTest(t *TestEnv) { // address are updated correct. func balanceAndNonceAtTest(t *TestEnv) { var ( - sourceAddr = t.Vault.createAccount(t, big.NewInt(params.Ether)) + sourceAddr = t.Config.Vault.createAccount(t, big.NewInt(params.Ether)) sourceNonce = uint64(0) - targetAddr = t.Vault.createAccount(t, nil) + targetAddr = t.Config.Vault.createAccount(t, nil) ) // Get current balance @@ -291,7 +289,7 @@ func balanceAndNonceAtTest(t *TestEnv) { gasLimit = uint64(50000) ) rawTx := types.NewTransaction(sourceNonce, targetAddr, amount, gasLimit, gasPrice, nil) - valueTx, err := t.Vault.signTransaction(sourceAddr, rawTx) + valueTx, err := t.Config.Vault.signTransaction(sourceAddr, rawTx) if err != nil { t.Fatalf("Unable to sign value tx: %v", err) } diff --git a/simulators/optimism/devnet/helper.go b/simulators/optimism/devnet/helper.go index 0981c8546c..5b795b743f 100644 --- a/simulators/optimism/devnet/helper.go +++ b/simulators/optimism/devnet/helper.go @@ -22,15 +22,18 @@ import ( // default timeout for RPC calls var rpcTimeout = 10 * time.Second +type TestConfig struct { + Vault *vault + L1GenesisBlock []byte + DeployedContractAddr common.Address +} + // TestClient is the environment of a single test. type TestEnv struct { *hivesim.T - RPC *rpc.Client - Eth *ethclient.Client - Vault *vault - - genesis []byte - deployedContractAddr common.Address + RPC *rpc.Client + Eth *ethclient.Client + Config *TestConfig // This holds most recent context created by the Ctx method. // Every time Ctx is called, it creates a new context with the default @@ -40,7 +43,7 @@ type TestEnv struct { } // runHTTP runs the given test function using the HTTP RPC client. -func runHTTP(t *hivesim.T, c *hivesim.Client, v *vault, g []byte, fn func(*TestEnv)) { +func runHTTP(t *hivesim.T, c *hivesim.Client, config *TestConfig, fn func(*TestEnv)) { // This sets up debug logging of the requests and responses. client := &http.Client{ Transport: &loggingRoundTrip{ @@ -52,11 +55,10 @@ func runHTTP(t *hivesim.T, c *hivesim.Client, v *vault, g []byte, fn func(*TestE rpcClient, _ := rpc.DialHTTPWithClient(fmt.Sprintf("http://%v:9545/", c.IP), client) defer rpcClient.Close() env := &TestEnv{ - T: t, - RPC: rpcClient, - Eth: ethclient.NewClient(rpcClient), - Vault: v, - genesis: g, + T: t, + RPC: rpcClient, + Eth: ethclient.NewClient(rpcClient), + Config: config, } fn(env) if env.lastCtx != nil { @@ -65,7 +67,7 @@ func runHTTP(t *hivesim.T, c *hivesim.Client, v *vault, g []byte, fn func(*TestE } // runWS runs the given test function using the WebSocket RPC client. -func runWS(t *hivesim.T, c *hivesim.Client, v *vault, g []byte, fn func(*TestEnv)) { +func runWS(t *hivesim.T, c *hivesim.Client, config *TestConfig, fn func(*TestEnv)) { ctx, done := context.WithTimeout(context.Background(), 5*time.Second) rpcClient, err := rpc.DialWebsocket(ctx, fmt.Sprintf("ws://%v:9546/", c.IP), "") done() @@ -75,11 +77,10 @@ func runWS(t *hivesim.T, c *hivesim.Client, v *vault, g []byte, fn func(*TestEnv defer rpcClient.Close() env := &TestEnv{ - T: t, - RPC: rpcClient, - Eth: ethclient.NewClient(rpcClient), - Vault: v, - genesis: g, + T: t, + RPC: rpcClient, + Eth: ethclient.NewClient(rpcClient), + Config: config, } fn(env) if env.lastCtx != nil { @@ -94,10 +95,10 @@ func (t *TestEnv) CallContext(ctx context.Context, result interface{}, method st return t.RPC.CallContext(ctx, result, method, args...) } -// LoadGenesis returns the genesis block. +// LoadGenesis returns the L1 genesis block. func (t *TestEnv) LoadGenesis() *types.Block { var genesis core.Genesis - if err := json.Unmarshal(t.genesis, &genesis); err != nil { + if err := json.Unmarshal(t.Config.L1GenesisBlock, &genesis); err != nil { panic(fmt.Errorf("can't parse genesis JSON: %v", err)) } return genesis.ToBlock(nil) diff --git a/simulators/optimism/devnet/main.go b/simulators/optimism/devnet/main.go index 2ddc1d7963..fe3daeb352 100644 --- a/simulators/optimism/devnet/main.go +++ b/simulators/optimism/devnet/main.go @@ -1,12 +1,18 @@ package main import ( + "bytes" "context" + "math/big" "time" "fmt" "strings" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/hive/hivesim" ) @@ -16,11 +22,57 @@ type testSpec struct { Run func(*TestEnv) } +func setup(t *TestEnv) { + var ( + address = t.Config.Vault.createAccount(t, big.NewInt(params.Ether)) + nonce = uint64(0) + + expectedContractAddress = crypto.CreateAddress(address, nonce) + gasLimit = uint64(1200000) + ) + + rawTx := types.NewContractCreation(nonce, big0, gasLimit, gasPrice, deployCode) + deployTx, err := t.Config.Vault.signTransaction(address, rawTx) + if err != nil { + t.Fatalf("Unable to sign deploy tx: %v", err) + } + + // deploy contract + if err := t.Eth.SendTransaction(t.Ctx(), deployTx); err != nil { + t.Fatalf("Unable to send transaction: %v", err) + } + + t.Logf("Deploy transaction: 0x%x", deployTx.Hash()) + + // fetch transaction receipt for contract address + var contractAddress common.Address + receipt, err := waitForTxConfirmations(t, deployTx.Hash(), 5) + if err != nil { + t.Fatalf("Unable to retrieve receipt: %v", err) + } + + // ensure receipt has the expected address + if expectedContractAddress != receipt.ContractAddress { + t.Fatalf("Contract deploy on different address, expected %x, got %x", expectedContractAddress, contractAddress) + } + + // test deployed code matches runtime code + code, err := t.Eth.CodeAt(t.Ctx(), receipt.ContractAddress, nil) + if err != nil { + t.Fatalf("Unable to fetch contract code: %v", err) + } + if bytes.Compare(runtimeCode, code) != 0 { + t.Errorf("Deployed code doesn't match, expected %x, got %x", runtimeCode, code) + } + + t.Config.DeployedContractAddr = contractAddress +} + var tests = []testSpec{ // HTTP RPC tests. {Name: "http/BalanceAndNonceAt", Run: balanceAndNonceAtTest}, - {Name: "http/ContractDeployment", Run: deployContractTest}, {Name: "http/CodeAt", Run: CodeAtTest}, + {Name: "http/ContractDeployment", Run: deployContractTest}, {Name: "http/ContractDeploymentOutOfGas", Run: deployContractOutOfGasTest}, {Name: "http/GenesisBlockByHash", Run: genesisBlockByHashTest}, {Name: "http/GenesisBlockByNumber", Run: genesisBlockByNumberTest}, @@ -83,8 +135,12 @@ func runAllTests(t *hivesim.T) { c := d.l2.Client - vault := newVault() - genesis := []byte(d.l2Genesis) + // Setup deployed contract + config := &TestConfig{ + Vault: newVault(), + L1GenesisBlock: []byte(d.l2Genesis), + } + runHTTP(t, c, config, setup) s := newSemaphore(16) for _, test := range tests { @@ -98,9 +154,9 @@ func runAllTests(t *hivesim.T) { Run: func(t *hivesim.T) { switch test.Name[:strings.IndexByte(test.Name, '/')] { case "http": - runHTTP(t, c, vault, genesis, test.Run) + runHTTP(t, c, config, test.Run) case "ws": - runWS(t, c, vault, genesis, test.Run) + runWS(t, c, config, test.Run) default: panic("bad test prefix in name " + test.Name) } From 7193a20710053c8f3e3c70cbe56e189d0a32d132 Mon Sep 17 00:00:00 2001 From: Javed Khan Date: Tue, 10 May 2022 18:11:16 -0400 Subject: [PATCH 3/3] simulators (op): fix failing test codeat --- simulators/optimism/devnet/ethclient.go | 6 +++--- simulators/optimism/devnet/main.go | 16 ++-------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/simulators/optimism/devnet/ethclient.go b/simulators/optimism/devnet/ethclient.go index 4d78f35ce9..1d74b8f637 100644 --- a/simulators/optimism/devnet/ethclient.go +++ b/simulators/optimism/devnet/ethclient.go @@ -83,11 +83,11 @@ func genesisBlockByNumberTest(t *TestEnv) { } } -// CodeAtTest tests the code for the pre-deployed contract. +// CodeAtTest tests the code for the deployed contract. func CodeAtTest(t *TestEnv) { - code, err := t.Eth.CodeAt(t.Ctx(), t.Config.DeployedContractAddr, big0) + code, err := t.Eth.CodeAt(t.Ctx(), t.Config.DeployedContractAddr, nil) if err != nil { - t.Fatalf("Could not fetch code for predeployed contract: %v", err) + t.Fatalf("Could not fetch code for deployed contract: %v", err) } if bytes.Compare(runtimeCode, code) != 0 { t.Fatalf("Unexpected code, want %x, got %x", runtimeCode, code) diff --git a/simulators/optimism/devnet/main.go b/simulators/optimism/devnet/main.go index fe3daeb352..cca5001e25 100644 --- a/simulators/optimism/devnet/main.go +++ b/simulators/optimism/devnet/main.go @@ -1,7 +1,6 @@ package main import ( - "bytes" "context" "math/big" "time" @@ -9,7 +8,6 @@ import ( "fmt" "strings" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" @@ -45,7 +43,6 @@ func setup(t *TestEnv) { t.Logf("Deploy transaction: 0x%x", deployTx.Hash()) // fetch transaction receipt for contract address - var contractAddress common.Address receipt, err := waitForTxConfirmations(t, deployTx.Hash(), 5) if err != nil { t.Fatalf("Unable to retrieve receipt: %v", err) @@ -53,19 +50,10 @@ func setup(t *TestEnv) { // ensure receipt has the expected address if expectedContractAddress != receipt.ContractAddress { - t.Fatalf("Contract deploy on different address, expected %x, got %x", expectedContractAddress, contractAddress) + t.Fatalf("Contract deploy on different address, expected %x, got %x", expectedContractAddress, receipt.ContractAddress) } - // test deployed code matches runtime code - code, err := t.Eth.CodeAt(t.Ctx(), receipt.ContractAddress, nil) - if err != nil { - t.Fatalf("Unable to fetch contract code: %v", err) - } - if bytes.Compare(runtimeCode, code) != 0 { - t.Errorf("Deployed code doesn't match, expected %x, got %x", runtimeCode, code) - } - - t.Config.DeployedContractAddr = contractAddress + t.Config.DeployedContractAddr = receipt.ContractAddress } var tests = []testSpec{