Skip to content
This repository has been archived by the owner on Jan 15, 2024. It is now read-only.

Arbitrum tests #1230

Merged
merged 24 commits into from
Nov 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e97acc9
WIP: use EIP1559 transactions
sveitser Oct 27, 2022
1f45ae0
Merge branch 'eip-1559-txns' into arbitrum-tests
sveitser Oct 28, 2022
c43ecd9
WIP: run all tests against arbitrum
sveitser Oct 28, 2022
a919d18
Fix tests in cap-rust-sandbox
sveitser Oct 28, 2022
9d7f67e
Fix cap-rust-sandbox integration tests
sveitser Oct 28, 2022
44b1315
WIP: define constant for gas limit
sveitser Oct 28, 2022
0297e75
Extract constant for gas limit override
sveitser Oct 28, 2022
e198c5c
Merge branch 'eip-1559-txns' into arbitrum-tests
sveitser Oct 28, 2022
353aea0
fixup
sveitser Oct 28, 2022
365179f
Undo retry
sveitser Oct 28, 2022
ae238df
Higher gas limit override for arbitrum
sveitser Oct 28, 2022
e444772
Remove hardcoded provider URL
sveitser Nov 1, 2022
e410ebb
Ensure non-deployer is not deployer
sveitser Nov 1, 2022
790d8cd
Enable running wallet tests on arbitrum
sveitser Nov 1, 2022
048c02a
Update docs for arbitrum testing
sveitser Nov 1, 2022
3023322
arbitrum: run all tests by default
sveitser Nov 1, 2022
7b5ce66
Merge remote-tracking branch 'origin/main' into arbitrum-tests
sveitser Nov 1, 2022
c5099b0
Set `from` address when funding wallet
sveitser Nov 1, 2022
58a2d9e
relayer: add extra gas to transaction
sveitser Nov 1, 2022
aa2b055
Remove unused import
sveitser Nov 1, 2022
6d585b1
Abort early if transactions fail to mine
sveitser Nov 1, 2022
e525a0a
Add 1M extra gas for tx that sometimes runs out
sveitser Nov 1, 2022
bdace37
Remove debug print statements
sveitser Nov 2, 2022
3480fd8
Return errors instead of unwrapping
sveitser Nov 3, 2022
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
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -676,14 +676,32 @@ env MY_FAUCET_MANAGER_MNEMONIC="$TEST_MNEMONIC" smoke-test-goerli --reset

To run the tests against Arbitrum Goerli follow these steps:

- Install [Metamask](https://metamask.io/) in your browser and copy the mnemonic.
- Install [Metamask](https://metamask.io/) in your browser and restore with
your GOERLI_MNEMONIC.
- Switch metamask to the Goerli network.
- Get some Goerli ethers at some faucet (see Goerli section above)
- Go to the [Arbitrum bridge](https://bridge.arbitrum.io/) and deposit your
Goerli eth. Leave a bit for the ethereum gas fees. Wait a few minutes until
your account is funded.
- Deploy the contracts

```
hardhat deploy --tags CAPE --network arbitrum_goerli --reset
```

- Run the tests

```
> env ETH_MNEMONIC="$YOUR_ETH_MNEMONIC" CAPE_WEB3_PROVIDER_URL=https://goerli-rollup.arbitrum.io/rpc cargo test --release test_2user_and_submit -- --nocapture
run-tests-arbitrum
```

This script will re-use the stateless libraries in order to save gas and speed
up test execution. To run a single test, pass the test name to the script as
argument, e.g. `run-tests-arbitrum backend::test::test_transfer`.

If you are getting `Too Many Requests` errors, you may want to set up an infura
project and use their arbitrum goerli RPC and use it via

```
CAPE_WEB3_PROVIDER_URL=https://arbitrum-goerli.infura.io/v3/... run-tests-arbitrum
```
23 changes: 23 additions & 0 deletions bin/run-tests-arbitrum
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Copyright (c) 2022 Espresso Systems (espressosys.com)
# This file is part of the Configurable Asset Privacy for Ethereum (CAPE) library.
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.

set -euo pipefail

function get_addr() {
cat contracts/deployments/arbitrum/$1.json | jq -r .address
}

export VERIFYING_KEYS_LIB_ADDRESS=$(get_addr VerifyingKeys)
export RESCUE_LIB_ADDRESS=$(get_addr RescueLib)
export VERIFIER_ADDRESS=$(get_addr PlonkVerifier)

export CAPE_WEB3_PROVIDER_URL=${CAPE_WEB3_PROVIDER_URL:-https://goerli-rollup.arbitrum.io/rpc}
export ETH_MNEMONIC="${ETH_MNEMONIC:-$GOERLI_MNEMONIC}"

echo "Running tests..."
cargo test --release -- --test-threads 1 "$@"
2 changes: 1 addition & 1 deletion contracts/deploy/00_cape.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
// Wait for 2 confirmations on public networks.
waitConfirmations: hre.network.tags.public ? 2 : 1,
// Avoid deployment failures due to potentially failing `estimateGas` calls.
gasLimit: 10_000_000,
// gasLimit: 10_000_000, // This is better set in hardhat config.networks.<network>.gas
};

log("Deploy options:", opts);
Expand Down
5 changes: 5 additions & 0 deletions contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ const config: HardhatUserConfig = {
accounts: { mnemonic: process.env.GOERLI_MNEMONIC },
tags: ["public"],
},
arbitrum_goerli: {
url: "https://goerli-rollup.arbitrum.io/rpc",
gasPrice: 100_000_000,
accounts: { mnemonic: process.env.GOERLI_MNEMONIC },
},
localhost: {
url: `http://localhost:${process.env.RPC_PORT || 8545}`,
timeout: 120000, // when running against hardhat, some tests are very slow
Expand Down
16 changes: 11 additions & 5 deletions contracts/rust/src/cape/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ pub fn decode_cape_block_from_event(block: BlockCommittedFilter) -> Result<CapeB
#[cfg(test)]
mod tests {
use crate::{
assertion::EnsureMined,
cape::{
events::decode_cape_block_from_event,
submit_block::{fetch_cape_memos, submit_cape_block_with_memos},
BlockWithMemos, CapeBlock,
},
ethereum::{EthConnection, GAS_LIMIT_OVERRIDE},
ethereum::EthConnection,
ledger::CapeLedger,
types::{GenericInto, MerkleRootSol},
};
Expand Down Expand Up @@ -64,7 +65,8 @@ mod tests {
.add_root(root.generic_into::<MerkleRootSol>().0)
.send()
.await?
.await?;
.await?
.ensure_mined();

// Adapted from seahorse
// https://github.com/EspressoSystems/seahorse/blob/ace20bc5f1bcf5b88ca0562799b8e80e6c52e933/src/persistence.rs#L574
Expand Down Expand Up @@ -96,15 +98,19 @@ mod tests {
&connection.contract,
block_with_memos.clone(),
BlockNumber::Latest,
GAS_LIMIT_OVERRIDE, // gas limit
1_000_000, // extra gas. This transaction sometimes runs out of gas, reason unclear.
)
.await?
.await?;
.await?
.ensure_mined();

// A connection with a random wallet (for queries only)
let query_connection = EthConnection::from_config_for_query(
&format!("{:?}", connection.contract.address()), // 0x123...cdf
"http://localhost:8545",
&match std::env::var("CAPE_WEB3_PROVIDER_URL") {
Ok(url) => url,
Err(_) => "http://localhost:8545".to_string(),
},
);

let events = query_connection
Expand Down
12 changes: 8 additions & 4 deletions contracts/rust/src/cape/faucet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,27 @@ mod test {
use crate::{
assertion::Matcher,
deploy::deploy_test_cape_with_deployer,
ethereum::get_funded_client,
ethereum::{get_funded_client, get_provider},
model::CAPE_MERKLE_HEIGHT,
types::{self as sol, field_to_u256, GenericInto, TestCAPE},
};
use anyhow::Result;
use ethers::abi::AbiDecode;
use ethers::{abi::AbiDecode, prelude::SignerMiddleware, signers::LocalWallet};
use jf_cap::{
keys::UserKeyPair,
structs::{AssetDefinition, BlindFactor, FreezeFlag, RecordCommitment, RecordOpening},
BaseField, MerkleTree,
};
use std::sync::Arc;

#[tokio::test]
async fn test_faucet() -> Result<()> {
let rng = &mut ark_std::test_rng();
let deployer = get_funded_client().await?;
let non_deployer = get_funded_client().await?;
let non_deployer = Arc::new(SignerMiddleware::new(
get_provider(),
LocalWallet::new(&mut rand::thread_rng()),
));
let contract = deploy_test_cape_with_deployer(deployer.clone()).await;
let faucet_manager = UserKeyPair::generate(rng);

Expand All @@ -43,7 +47,7 @@ mod test {
faucet_manager.address().into(),
faucet_manager.pub_key().enc_key().into(),
)
.send()
.call()
.await
.should_revert_with_message("Only invocable by deployer");

Expand Down
22 changes: 19 additions & 3 deletions contracts/rust/src/cape/submit_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ethers::prelude::signer::SignerMiddlewareError;
use ethers::prelude::{BlockNumber, Provider, Wallet};
use ethers::prelude::{Bytes, Http, Middleware, PendingTransaction, TxHash};
use ethers::providers::ProviderError;
use ethers_core::k256::ecdsa::SigningKey;

use super::{BlockMemos, BlockWithMemos};
Expand Down Expand Up @@ -46,7 +47,7 @@ pub async fn submit_cape_block_with_memos(
contract: &CAPE<EthMiddleware>,
block: BlockWithMemos,
block_number: BlockNumber,
gas_limit: u64,
extra_gas: u64,
) -> Result<PendingTransaction<'_, Http>, SignerMiddlewareError<Provider<Http>, Wallet<SigningKey>>>
{
let mut memos_bytes: Vec<u8> = vec![];
Expand Down Expand Up @@ -95,7 +96,23 @@ pub async fn submit_cape_block_with_memos(
// gas usage of processing a burn note is potentially unbounded. Using
// tokens whose transfer function far exceeds normal gas consumption is
// currently not supported.
tx.set_gas(gas_limit);
//
// TODO: mathis: it's a bit wasteful to download the entire block for this
// but I don't know of another way to obtain the current block gas limit.
let block = contract
.client()
.get_block(BlockNumber::Latest)
.await?
.ok_or_else(|| {
SignerMiddlewareError::MiddlewareError(ProviderError::CustomError(
"Did not receive a block".to_string(),
))
})?;

tx.set_gas(std::cmp::min(
tx.gas().ok_or(SignerMiddlewareError::GasMissing)? + extra_gas,
block.gas_limit,
));

contract.client().send_transaction(tx, None).await
}
Expand Down Expand Up @@ -236,7 +253,6 @@ mod tests {
.await?
.ensure_mined();

// Check that now the nullifier has been inserted
assert!(
contract
.nullifiers(nf.generic_into::<NullifierSol>().0)
Expand Down
28 changes: 20 additions & 8 deletions contracts/rust/src/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use crate::types::{
TestTranscript, TestVerifyingKeys, CAPE,
};
use ethers::prelude::{k256::ecdsa::SigningKey, Http, Provider, SignerMiddleware, Wallet};
use ethers::types::Address;
use std::env;
use std::sync::Arc;

// Middleware used for locally signing transactions
Expand All @@ -35,13 +37,23 @@ pub async fn deploy_test_cape_with_deployer(
deployer: Arc<EthMiddleware>,
) -> TestCAPE<EthMiddleware> {
// deploy the PlonkVerifier
let verifier = deploy(
deployer.clone(),
&contract_abi_path("verifier/PlonkVerifier.sol/PlonkVerifier"),
(),
)
.await
.unwrap();

// If VERIFIER_ADDRESS is set, use that address instead of deploying a new
// contract.
let verifier_address = match env::var("VERIFIER_ADDRESS") {
Ok(val) => {
println!("Using Verifier at {val}");
val.parse::<Address>().unwrap()
}
Err(_) => deploy(
deployer.clone(),
&contract_abi_path("verifier/PlonkVerifier.sol/PlonkVerifier"),
(),
)
.await
.unwrap()
.address(),
};

let records_merkle_tree = deploy(
deployer.clone(),
Expand All @@ -57,7 +69,7 @@ pub async fn deploy_test_cape_with_deployer(
&contract_abi_path("mocks/TestCAPE.sol/TestCAPE"),
CAPEConstructorArgs::new(
CAPE_NUM_ROOTS as u64,
verifier.address(),
verifier_address,
records_merkle_tree.address(),
)
.to_tuple(),
Expand Down
15 changes: 11 additions & 4 deletions contracts/rust/src/ethereum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ use ethers::{
use std::{convert::TryFrom, env, fs, path::Path, sync::Arc, time::Duration};

/// Supply this gas limit when the automatically filled estimated gas value is
/// too low and the transaction runs out of gas.
pub const GAS_LIMIT_OVERRIDE: u64 = 10_000_000;
/// too low and the transaction runs out of gas. This limit is large enough for
/// arbitrum and small enough for L1 (block gas limit 30_000_000 @ 2022-11-01).
pub const GAS_LIMIT_OVERRIDE: u64 = 25_000_000;

/// Utility to interact with the CAPE contract on some Ethereum blockchain
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -157,7 +158,10 @@ async fn link_unlinked_libraries<M: 'static + Middleware>(
// Connect to linked library if env var with address is set
// otherwise, deploy the library.
let rescue_lib_address = match env::var("RESCUE_LIB_ADDRESS") {
Ok(val) => val.parse::<Address>()?,
Ok(val) => {
println!("Using RescueLib library at {val}");
val.parse::<Address>()?
}
Err(_) => deploy(
client.clone(),
&contract_abi_path("libraries/RescueLib.sol/RescueLib"),
Expand All @@ -181,7 +185,10 @@ async fn link_unlinked_libraries<M: 'static + Middleware>(
// Connect to linked library if env var with address is set
// otherwise, deploy the library.
let verifying_keys_lib_address = match env::var("VERIFYING_KEYS_LIB_ADDRESS") {
Ok(val) => val.parse::<Address>()?,
Ok(val) => {
println!("Using VerifyingKeys library at {val}");
val.parse::<Address>()?
}
Err(_) => deploy(
client.clone(),
&contract_abi_path("libraries/VerifyingKeys.sol/VerifyingKeys"),
Expand Down
8 changes: 4 additions & 4 deletions relayer/src/bin/minimal-relayer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use ethers::prelude::{
coins_bip39::English, Address, Middleware, MnemonicBuilder, Signer, SignerMiddleware,
};
use relayer::{
init_web_server, submit_empty_block_loop, NonceCountRule, WebState, DEFAULT_RELAYER_GAS_LIMIT,
init_web_server, submit_empty_block_loop, NonceCountRule, WebState, DEFAULT_RELAYER_EXTRA_GAS,
DEFAULT_RELAYER_MAX_RETRIES, DEFAULT_RELAYER_PORT, DEFAULT_RELAYER_RETRY_INTERVAL_MS,
};
use std::{num::NonZeroU64, sync::Arc, time::Duration};
Expand Down Expand Up @@ -73,8 +73,8 @@ struct MinimalRelayerOptions {
///
/// The default of 10M is enough to cover the gas cost of submitting one note
/// and crediting up to 10 pending deposits in the smart contract.
#[structopt(long, env = "CAPE_RELAYER_GAS_LIMIT", default_value = DEFAULT_RELAYER_GAS_LIMIT)]
gas_limit: NonZeroU64,
#[structopt(long, env = "CAPE_RELAYER_EXTRA_GAS", default_value = DEFAULT_RELAYER_EXTRA_GAS)]
extra_gas: NonZeroU64,

/// Maximum number of times to retry transaction submission.
///
Expand Down Expand Up @@ -121,7 +121,7 @@ async fn main() -> std::io::Result<()> {
let web_state = WebState::new(
contract,
opt.nonce_count_rule,
opt.gas_limit.into(),
opt.extra_gas.into(),
opt.max_retries,
Duration::from_millis(opt.retry_interval),
);
Expand Down
Loading