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 .github/actions/install_rust/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ runs:
- name: Install Anvil
uses: foundry-rs/foundry-toolchain@v1
with:
version: v0.3.0
version: v1.5.1
2 changes: 1 addition & 1 deletion .github/workflows/hybrid_system_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ jobs:
- name: Install Anvil
uses: foundry-rs/foundry-toolchain@v1
with:
version: v0.3.0
version: v1.5.1

- name: Restore executable permissions
run: chmod +x ./target/debug/sequencer_node_setup ./target/debug/sequencer_simulator
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/apollo_base_layer_tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ colored.workspace = true
papyrus_base_layer = { workspace = true, features = ["testing"] }
starknet_api.workspace = true
tokio.workspace = true
tracing.workspace = true
url.workspace = true

[dev-dependencies]
apollo_infra_utils.workspace = true
24 changes: 20 additions & 4 deletions crates/apollo_base_layer_tests/src/anvil_base_layer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::ops::RangeInclusive;
use std::process::Command;
use std::time::Duration;

use alloy::node_bindings::NodeError as AnvilError;
use alloy::primitives::{I256, U256};
Expand Down Expand Up @@ -28,6 +29,7 @@ use papyrus_base_layer::{
use starknet_api::block::BlockHashAndNumber;
use starknet_api::hash::StarkHash;
use starknet_api::transaction::L1HandlerTransaction;
use tracing::info;
use url::Url;

/// Initialize an anvil instance under the default port and deploy the Starknet contract.
Expand All @@ -47,7 +49,7 @@ pub struct AnvilBaseLayer {
impl AnvilBaseLayer {
pub const DEFAULT_ANVIL_L1_ACCOUNT_ADDRESS: StarkHash =
StarkHash::from_hex_unchecked("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266");
pub const DEFAULT_ANVIL_PORT: u16 = 8545;
const DEFAULT_ANVIL_PORT: u16 = 8545;
const DEFAULT_ANVIL_L1_DEPLOYED_ADDRESS: &str = "0x5fbdb2315678afecb367f032d93f642f64180aa3";

/// Note: if you have port conflicts, you might have a zombie anvil instance
Expand All @@ -69,7 +71,7 @@ impl AnvilBaseLayer {
"Install instructions (for local development):\n
Execute from within a directory that's included in PATH, like ~/.local/bin:\n
curl -L \
https://github.com/foundry-rs/foundry/releases/download/v0.3.0/foundry_v0.3.0_linux_amd64.tar.gz \
https://github.com/foundry-rs/foundry/releases/download/v1.5.1/foundry_v1.5.1_linux_amd64.tar.gz \
| tar -xz --wildcards 'anvil'".yellow()
);

Expand All @@ -96,8 +98,22 @@ curl -L \
_ => panic!("Failed to spawn Anvil: {}", error.to_string().red()),
});

Starknet::deploy(anvil_client.clone()).await.unwrap();

info!("Deploying Starknet contract to Anvil with port: {}", port);
let mut retries = 0;
for _ in 0..100 {
let result = Starknet::deploy(anvil_client.clone()).await;
if result.is_ok() {
break;
}
retries += 1;
tokio::time::sleep(Duration::from_millis(10)).await;
}
Starknet::deploy(anvil_client.clone()).await.unwrap_or_else(|error| {
panic!(
"Failed to deploy Starknet contract to Anvil on port {port} after {retries} \
retries: {error:?}"
);
});
let config = Self::config(Self::url_static(port));
let url_iterator = CircularUrlIterator::new(config.ordered_l1_endpoint_urls.clone());
let root_client = anvil_client.root().clone();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use alloy::node_bindings::Anvil;
use apollo_infra_utils::test_utils::{AvailablePortsGenerator, TestIdentifier};
use papyrus_base_layer::ethereum_base_layer_contract::{
EthereumBaseLayerConfig,
EthereumBaseLayerContract,
Expand All @@ -10,14 +11,20 @@ use papyrus_base_layer::test_utils::{
OTHER_ARBITRARY_ANVIL_L1_ACCOUNT_ADDRESS,
};
use papyrus_base_layer::BaseLayerContract;
use tracing::info;

#[tokio::test]
async fn anvil_starts_with_no_contract() {
const NUM_L1_TRANSACTIONS: usize = 10;
// TODO(GuyNir/Shahak): avoid this hard-coded port number, and align port usages throughout the
// anvil instances.
let mut ports_gen =
AvailablePortsGenerator::new(TestIdentifier::AnvilStartsWithNoContractTest.into());
let mut available_ports = ports_gen
.next()
.expect("Failed to get an AvailablePorts instance for anvil_starts_with_no_contract");
let port = available_ports.get_next_port();
info!("Starting Anvil with port: {}", port);
let anvil = Anvil::new()
.port(9999_u16)
.port(port)
.try_spawn()
.expect("Anvil not installed, see anvil base layer for installation instructions.");
let base_layer_config = EthereumBaseLayerConfig {
Expand Down
6 changes: 6 additions & 0 deletions crates/apollo_infra_utils/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ pub enum TestIdentifier {
SyncFlowIntegrationTest,
StorageReaderServerUnitTests,
StorageReaderTypesUnitTests,
L1EventsScraperEndToEndTest,
MockedStarknetStateUpdateTest,
LatestProvedBlockEthereumTest,
EventsFromOtherContractsTest,
L1ProviderUnitTests,
AnvilStartsWithNoContractTest,
}

#[derive(Debug)]
Expand Down
40 changes: 33 additions & 7 deletions crates/apollo_integration_tests/src/integration_test_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use mempool_test_utils::starknet_api_test_utils::{
AccountId,
MultiAccountTransactionGenerator,
};
use papyrus_base_layer::ethereum_base_layer_contract::EthereumBaseLayerConfig;
use papyrus_base_layer::test_utils::anvil_mine_blocks;
use starknet_api::block::BlockNumber;
use starknet_api::core::{ChainId, Nonce};
Expand Down Expand Up @@ -260,6 +261,18 @@ impl NodeSetup {
.clone()
.expect("No executable with a set l1 gas price scraper config.")
}

pub fn get_base_layer_config(&self) -> EthereumBaseLayerConfig {
get_executable_by_component(
self.node_type,
&self.executables,
ComponentConfigInService::BaseLayer,
)
.get_config()
.base_layer_config
.clone()
.expect("No executable with a set base layer config.")
}
}

pub struct RunningNode {
Expand Down Expand Up @@ -345,8 +358,26 @@ impl IntegrationTestManager {

let l1_gas_price_scraper_config =
sequencers_setup.first().unwrap().get_l1_gas_price_scraper_config();
let anvil_base_layer_config = sequencers_setup.first().unwrap().get_base_layer_config();

// TODO(guyn): consider saving the port as a part of the base layer config, not just (or
// instead of) in the url.
let mut anvil_base_layer = AnvilBaseLayer::new(
Some(1),
Some(
anvil_base_layer_config
.ordered_l1_endpoint_urls
.first()
.unwrap()
.peek_secret()
.port()
.unwrap(),
),
)
.await;
// Make sure to update the rest of the config to match what comes from the sequencer setup.
anvil_base_layer.ethereum_base_layer.config = anvil_base_layer_config;

let anvil_base_layer = AnvilBaseLayer::new(Some(1), None).await;
// Send some transactions to L1 so it has a history of blocks to scrape gas prices from.
let num_blocks_needed_on_l1 = l1_gas_price_scraper_config.number_of_blocks_for_mean
+ l1_gas_price_scraper_config.finality;
Expand Down Expand Up @@ -1101,12 +1132,7 @@ async fn get_sequencer_setup_configs(
.next()
.expect("Failed to get an AvailablePorts instance for base layer config");
let base_layer_config =
// TODO(guyn): Need to start using the ports generator for anvil, but we need to make sure
// we pass it from "setup configs" into IntegrationTestManager::new() where we setup an actual Anvil instance.
// Use this commented line:
// AnvilBaseLayer::config(AnvilBaseLayer::url_static(base_layer_ports.get_next_port()));
// TODO(guyn): Also check if DEFAULT_ANVIL_PORT should be pub in AnvilBaseLayer.
AnvilBaseLayer::config(AnvilBaseLayer::url_static(AnvilBaseLayer::DEFAULT_ANVIL_PORT));
AnvilBaseLayer::config(AnvilBaseLayer::url_static(base_layer_ports.get_next_port()));

let mut nodes = Vec::new();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use apollo_base_layer_tests::anvil_base_layer::{send_message_to_l2, AnvilBaseLayer};
use apollo_infra_utils::test_utils::{AvailablePortsGenerator, TestIdentifier};
use assert_matches::assert_matches;
use papyrus_base_layer::constants::{EventIdentifier, LOG_MESSAGE_TO_L2_EVENT_IDENTIFIER};
use papyrus_base_layer::ethereum_base_layer_contract::Starknet;
Expand All @@ -14,7 +15,13 @@ use starknet_api::{calldata, contract_address, felt};
async fn events_from_other_contract() {
const EVENT_IDENTIFIERS: &[EventIdentifier] = &[LOG_MESSAGE_TO_L2_EVENT_IDENTIFIER];

let mut anvil_base_layer = AnvilBaseLayer::new(None, Some(8888)).await;
let mut ports_gen =
AvailablePortsGenerator::new(TestIdentifier::EventsFromOtherContractsTest.into());
let mut available_ports = ports_gen
.next()
.expect("Failed to get an AvailablePorts instance for events_from_other_contract");
let mut anvil_base_layer =
AnvilBaseLayer::new(None, Some(available_ports.get_next_port())).await;
// Anvil base layer already auto-deployed a starknet contract.
let this_contract = &anvil_base_layer.ethereum_base_layer.contract;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::time::Duration;

use alloy::primitives::U256;
use apollo_base_layer_tests::anvil_base_layer::AnvilBaseLayer;
use apollo_infra_utils::test_utils::{AvailablePortsGenerator, TestIdentifier};
use apollo_l1_provider::event_identifiers_to_track;
use apollo_l1_provider::l1_scraper::L1Scraper;
use apollo_l1_provider_types::{Event, MockL1ProviderClient};
Expand All @@ -22,7 +23,12 @@ use starknet_api::transaction::{L1HandlerTransaction, TransactionHasher, Transac
#[tokio::test]
async fn scraper_end_to_end() {
// Setup.
let mut base_layer = AnvilBaseLayer::new(None, None).await;
let mut ports_gen =
AvailablePortsGenerator::new(TestIdentifier::L1EventsScraperEndToEndTest.into());
let mut available_ports = ports_gen
.next()
.expect("Failed to get an AvailablePorts instance for l1_events_scraper_end_to_end");
let mut base_layer = AnvilBaseLayer::new(None, Some(available_ports.get_next_port())).await;
let contract = &base_layer.ethereum_base_layer.contract;
let mut l1_provider_client = MockL1ProviderClient::default();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use alloy::providers::Provider;
use apollo_base_layer_tests::anvil_base_layer::{AnvilBaseLayer, MockedStateUpdate};
use apollo_infra_utils::test_utils::{AvailablePortsGenerator, TestIdentifier};
use papyrus_base_layer::BaseLayerContract;
use pretty_assertions::assert_eq;
use starknet_api::block::{BlockHash, BlockHashAndNumber, BlockNumber};
Expand Down Expand Up @@ -49,7 +50,12 @@ async fn latest_proved_block_ethereum() {
))),
};

let mut base_layer = AnvilBaseLayer::new(None, None).await;
let mut ports_gen =
AvailablePortsGenerator::new(TestIdentifier::LatestProvedBlockEthereumTest.into());
let mut available_ports = ports_gen
.next()
.expect("Failed to get an AvailablePorts instance for latest_proved_block_ethereum");
let mut base_layer = AnvilBaseLayer::new(None, Some(available_ports.get_next_port())).await;
let provider = &base_layer.anvil_provider;

let mut current_block = provider.get_block_number().await.expect("Failed to get block number");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ use alloy::providers::Provider;
use alloy::rpc::types::eth::Filter as EthEventFilter;
use alloy::sol_types::SolEventInterface;
use apollo_base_layer_tests::anvil_base_layer::{AnvilBaseLayer, MockedStateUpdate};
use apollo_infra_utils::test_utils::{AvailablePortsGenerator, TestIdentifier};
use papyrus_base_layer::ethereum_base_layer_contract::Starknet;
use papyrus_base_layer::BaseLayerContract;
use pretty_assertions::assert_eq;
use starknet_api::block::{BlockHash, BlockHashAndNumber, BlockNumber};

#[tokio::test]
async fn test_mocked_starknet_state_update() {
let mut base_layer = AnvilBaseLayer::new(None, None).await;
let mut ports_gen =
AvailablePortsGenerator::new(TestIdentifier::MockedStarknetStateUpdateTest.into());
let mut available_ports = ports_gen
.next()
.expect("Failed to get an AvailablePorts instance for mocked_starknet_state_update_test");
let mut base_layer = AnvilBaseLayer::new(None, Some(available_ports.get_next_port())).await;

// Check that the contract was initialized (during the construction above).
let genesis_block_number = 1;
Expand Down
7 changes: 6 additions & 1 deletion crates/apollo_l1_provider/tests/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use apollo_infra::component_server::{
LocalComponentServer,
LocalServerConfig,
};
use apollo_infra_utils::test_utils::{AvailablePortsGenerator, TestIdentifier};
use apollo_l1_provider::l1_provider::L1Provider;
use apollo_l1_provider::l1_scraper::L1Scraper;
use apollo_l1_provider::metrics::L1_PROVIDER_INFRA_METRICS;
Expand Down Expand Up @@ -67,7 +68,11 @@ fn convert_call_data_to_u256(call_data: &[u8]) -> Vec<Uint<256, 4>> {
// Need to allow dead code as this is only used in some of the test crates.
#[allow(dead_code)]
pub(crate) async fn setup_anvil_base_layer() -> AnvilBaseLayer {
let mut base_layer = AnvilBaseLayer::new(None, None).await;
let mut ports_gen = AvailablePortsGenerator::new(TestIdentifier::L1ProviderUnitTests.into());
let mut available_ports = ports_gen
.next()
.expect("Failed to get an AvailablePorts instance for L1 provider unit tests");
let mut base_layer = AnvilBaseLayer::new(None, Some(available_ports.get_next_port())).await;
anvil_mine_blocks(base_layer.ethereum_base_layer.config.clone(), NUMBER_OF_BLOCKS_TO_MINE)
.await;
// We use a really long timeout because in the tests we sometimes advance the fake time by large
Expand Down
2 changes: 1 addition & 1 deletion deployments/anvil/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from imports import k8s

SERVICE_PORT = 8545
IMAGE = "ghcr.io/foundry-rs/foundry:v0.3.0"
IMAGE = "ghcr.io/foundry-rs/foundry:v1.5.1"


def argument_parser():
Expand Down
2 changes: 1 addition & 1 deletion deployments/images/sequencer/node_setup.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ RUN cargo chef prepare --recipe-path recipe.json

FROM base AS builder
WORKDIR /app
RUN curl -L https://github.com/foundry-rs/foundry/releases/download/v0.3.0/foundry_v0.3.0_linux_amd64.tar.gz | tar -xz --wildcards 'anvil'
RUN curl -L https://github.com/foundry-rs/foundry/releases/download/v1.5.1/foundry_v1.5.1_linux_amd64.tar.gz | tar -xz --wildcards 'anvil'
COPY --from=planner /app/recipe.json recipe.json
RUN cargo chef cook --recipe-path recipe.json --bin sequencer_node_setup
COPY . .
Expand Down
Loading