From 9b17acce762d3f19ca15c067775f5466a6444d80 Mon Sep 17 00:00:00 2001 From: Daniyar Itegulov Date: Wed, 15 Nov 2023 14:00:01 +1100 Subject: [PATCH] feat: use local Lake Indexer in integration tests (#358) --- .github/workflows/multichain-integration.yml | 2 +- Cargo.lock | 147 ++++++++++------- integration-tests/src/env/containers.rs | 150 ++++++++++++++++++ integration-tests/src/lib.rs | 83 ++++++++-- .../src/multichain/containers.rs | 7 +- integration-tests/src/multichain/local.rs | 7 +- integration-tests/src/multichain/mod.rs | 14 +- integration-tests/tests/lib.rs | 2 +- node/src/cli.rs | 13 +- node/src/indexer.rs | 53 +++++-- 10 files changed, 382 insertions(+), 96 deletions(-) diff --git a/.github/workflows/multichain-integration.yml b/.github/workflows/multichain-integration.yml index 86815bbad..b5b3703ad 100644 --- a/.github/workflows/multichain-integration.yml +++ b/.github/workflows/multichain-integration.yml @@ -39,7 +39,7 @@ jobs: - name: Pull Relayer & Sandbox Docker Images run: | docker pull ghcr.io/near/os-relayer:12ba6e35690df3979fce0b36a41d0ca0db9c0ab4 - docker pull ghcr.io/near/sandbox + docker pull ghcr.io/near/near-lake-indexer:e6519c922435f3d18b5f2ddac5d1ec171ef4dd6b - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 diff --git a/Cargo.lock b/Cargo.lock index 89e4bc829..58a12e8ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -263,6 +263,19 @@ dependencies = [ "futures-core", ] +[[package]] +name = "async-channel" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d37875bd9915b7d67c2f117ea2c30a0989874d0b2cb694fe25403c85763c0c9e" +dependencies = [ + "concurrent-queue", + "event-listener 3.1.0", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-compression" version = "0.4.4" @@ -328,14 +341,14 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41ed9d5715c2d329bf1b4da8d60455b99b187f27ba726df2883799af9af60997" dependencies = [ - "async-lock 3.0.0", + "async-lock 3.1.0", "cfg-if 1.0.0", "concurrent-queue", "futures-io", "futures-lite 2.0.1", "parking", "polling 3.3.0", - "rustix 0.38.21", + "rustix 0.38.23", "slab", "tracing", "waker-fn", @@ -353,11 +366,11 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e900cdcd39bb94a14487d3f7ef92ca222162e6c7c3fe7cb3550ea75fb486ed" +checksum = "deb2ab2aa8a746e221ab826c73f48bc6ba41be6763f0855cb249eb6d154cf1d7" dependencies = [ - "event-listener 3.0.1", + "event-listener 3.1.0", "event-listener-strategy", "pin-project-lite", ] @@ -384,9 +397,9 @@ dependencies = [ "async-signal", "blocking", "cfg-if 1.0.0", - "event-listener 3.0.1", + "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.21", + "rustix 0.38.23", "windows-sys 0.48.0", ] @@ -402,7 +415,7 @@ dependencies = [ "cfg-if 1.0.0", "futures-core", "futures-io", - "rustix 0.38.21", + "rustix 0.38.23", "signal-hook-registry", "slab", "windows-sys 0.48.0", @@ -1113,16 +1126,16 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blocking" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a" +checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ - "async-channel", - "async-lock 2.8.0", + "async-channel 2.1.0", + "async-lock 3.1.0", "async-task", "fastrand 2.0.1", "futures-io", - "futures-lite 1.13.0", + "futures-lite 2.0.1", "piper", "tracing", ] @@ -1187,11 +1200,11 @@ dependencies = [ [[package]] name = "borsh" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a744ac76a433734df0902926ed12edd997391a8da3add87f6d706afc2dcbea" +checksum = "bf617fabf5cdbdc92f774bfe5062d870f228b80056d41180797abf48bed4056e" dependencies = [ - "borsh-derive 1.1.2", + "borsh-derive 1.2.0", "cfg_aliases", ] @@ -1223,9 +1236,9 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b22bf794b9f8c87b51ea4d9e2710907ce13aa81dd2b8ac18a78fcca68ac738ef" +checksum = "f404657a7ea7b5249e36808dff544bc88a28f26e0ac40009f674b7a009d14be3" dependencies = [ "once_cell", "proc-macro-crate 2.0.0", @@ -1551,9 +1564,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.7" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ "clap_builder", "clap_derive 4.4.7", @@ -1561,9 +1574,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.7" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" dependencies = [ "anstream", "anstyle", @@ -1780,9 +1793,9 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" +checksum = "28f85c3514d2a6e64160359b45a3918c3b4178bcbf4ae5d03ab2d02e521c479a" dependencies = [ "generic-array 0.14.7", "rand_core 0.6.4", @@ -2274,7 +2287,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d97ca172ae9dc9f9b779a6e3a65d308f2af74e5b8c921299075bdb4a0370e914" dependencies = [ "base16ct", - "crypto-bigint 0.5.3", + "crypto-bigint 0.5.4", "digest 0.10.7", "ff 0.13.0", "generic-array 0.14.7", @@ -2331,9 +2344,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" dependencies = [ "humantime", "is-terminal", @@ -2366,9 +2379,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "3.0.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cec0252c2afff729ee6f00e903d479fba81784c8e2bd77447673471fdfaea1" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" dependencies = [ "concurrent-queue", "parking", @@ -2381,7 +2394,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" dependencies = [ - "event-listener 3.0.1", + "event-listener 3.1.0", "pin-project-lite", ] @@ -3041,9 +3054,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -3339,7 +3352,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi 0.3.3", - "rustix 0.38.21", + "rustix 0.38.23", "windows-sys 0.48.0", ] @@ -3697,7 +3710,7 @@ dependencies = [ "base64 0.21.5", "borsh 0.10.3", "chrono", - "clap 4.4.7", + "clap 4.4.8", "curv-kzen", "ed25519-dalek", "futures", @@ -3745,10 +3758,10 @@ dependencies = [ "async-process", "backon", "bollard", - "clap 4.4.7", + "clap 4.4.8", "curv-kzen", "ed25519-dalek", - "env_logger 0.10.0", + "env_logger 0.10.1", "futures", "hex 0.4.3", "hyper", @@ -3775,7 +3788,7 @@ dependencies = [ "tokio-util 0.7.10", "toml 0.8.8", "tracing", - "tracing-log", + "tracing-log 0.1.4", "tracing-subscriber", ] @@ -3788,7 +3801,7 @@ dependencies = [ "axum", "axum-extra", "cait-sith", - "clap 4.4.7", + "clap 4.4.8", "hex 0.4.3", "k256", "local-ip-address", @@ -4010,7 +4023,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14e75c875026229902d065e4435804497337b631ec69ba746b102954273e9ad1" dependencies = [ - "borsh 1.1.2", + "borsh 1.2.0", "schemars", "serde", ] @@ -4120,7 +4133,7 @@ checksum = "af7d35397b02b131c188c72f3885e97daeccab134ec2fc8cc0073a94cf1cfe19" dependencies = [ "actix", "atty", - "clap 4.4.7", + "clap 4.4.8", "near-crypto 0.17.0", "near-primitives-core 0.17.0", "once_cell", @@ -5217,7 +5230,7 @@ dependencies = [ "cfg-if 1.0.0", "concurrent-queue", "pin-project-lite", - "rustix 0.38.21", + "rustix 0.38.23", "tracing", "windows-sys 0.48.0", ] @@ -5962,9 +5975,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "ffb93593068e9babdad10e4fce47dc9b3ac25315a72a59766ffd9e9a71996a04" dependencies = [ "bitflags 2.4.1", "errno", @@ -6051,9 +6064,9 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" dependencies = [ "dyn-clone", "schemars_derive", @@ -6063,9 +6076,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" dependencies = [ "proc-macro2", "quote", @@ -6579,7 +6592,7 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13f2b548cd8447f8de0fdf1c592929f70f4fc7039a05e47404b0d096ec6987a1" dependencies = [ - "async-channel", + "async-channel 1.9.0", "async-executor", "async-fs", "async-io 1.13.0", @@ -6852,7 +6865,7 @@ dependencies = [ "cfg-if 1.0.0", "fastrand 2.0.1", "redox_syscall 0.4.1", - "rustix 0.38.21", + "rustix 0.38.23", "windows-sys 0.48.0", ] @@ -7325,11 +7338,12 @@ dependencies = [ [[package]] name = "tracing-appender" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e" +checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", + "thiserror", "time", "tracing-subscriber", ] @@ -7376,6 +7390,17 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + [[package]] name = "tracing-opentelemetry" version = "0.17.4" @@ -7386,7 +7411,7 @@ dependencies = [ "opentelemetry 0.17.0", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.1.4", "tracing-subscriber", ] @@ -7402,7 +7427,7 @@ dependencies = [ "smallvec", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.1.4", "tracing-subscriber", ] @@ -7421,9 +7446,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -7434,7 +7459,7 @@ dependencies = [ "thread_local", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.2.0", ] [[package]] @@ -7771,7 +7796,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.21", + "rustix 0.38.23", ] [[package]] @@ -8030,18 +8055,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.25" +version = "0.7.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557" +checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.25" +version = "0.7.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b" +checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" dependencies = [ "proc-macro2", "quote", diff --git a/integration-tests/src/env/containers.rs b/integration-tests/src/env/containers.rs index 561f161b1..17cbda85e 100644 --- a/integration-tests/src/env/containers.rs +++ b/integration-tests/src/env/containers.rs @@ -46,6 +46,7 @@ use crate::env::{Context, LeaderNodeApi, SignerNodeApi}; use crate::util::{ self, create_key_file, create_key_file_with_filepath, create_relayer_cofig_file, }; +use bollard::exec::CreateExecOptions; static NETWORK_MUTEX: Lazy> = Lazy::new(|| Mutex::new(0)); @@ -497,6 +498,155 @@ impl<'a> Datastore<'a> { } } +pub struct LocalStack<'a> { + pub container: Container<'a, GenericImage>, + pub address: String, + pub s3_address: String, + pub s3_host_address: String, + pub s3_bucket: String, + pub s3_region: String, +} + +impl<'a> LocalStack<'a> { + const S3_CONTAINER_PORT: u16 = 4566; + + pub async fn run( + docker_client: &'a DockerClient, + network: &str, + s3_bucket: String, + s3_region: String, + ) -> anyhow::Result> { + tracing::info!("running LocalStack container..."); + let image = GenericImage::new("localstack/localstack", "latest") + .with_exposed_port(Self::S3_CONTAINER_PORT) + .with_wait_for(WaitFor::message_on_stdout("Running on")); + let image: RunnableImage = image.into(); + let image = image.with_network(network); + let container = docker_client.cli.run(image); + let address = docker_client + .get_network_ip_address(&container, network) + .await?; + + // Create the bucket + let create_result = docker_client + .docker + .create_exec( + container.id(), + CreateExecOptions::<&str> { + attach_stdout: Some(true), + attach_stderr: Some(true), + cmd: Some(vec![ + "awslocal", + "s3api", + "create-bucket", + "--bucket", + &s3_bucket, + "--region", + &s3_region, + ]), + ..Default::default() + }, + ) + .await?; + docker_client + .docker + .start_exec(&create_result.id, None) + .await?; + + let s3_address = format!("http://{}:{}", address, Self::S3_CONTAINER_PORT); + let s3_host_port = container.get_host_port_ipv4(Self::S3_CONTAINER_PORT); + let s3_host_address = format!("http://127.0.0.1:{s3_host_port}"); + + tracing::info!( + s3_address, + s3_host_address, + "LocalStack container is running" + ); + Ok(LocalStack { + container, + address, + s3_address, + s3_host_address, + s3_bucket, + s3_region, + }) + } +} + +pub struct LakeIndexer<'a> { + pub container: Container<'a, GenericImage>, + pub bucket_name: String, + pub region: String, + pub rpc_address: String, + pub rpc_host_address: String, +} + +impl<'a> LakeIndexer<'a> { + pub const CONTAINER_RPC_PORT: u16 = 3030; + + pub async fn run( + docker_client: &'a DockerClient, + network: &str, + s3_address: &str, + bucket_name: String, + region: String, + ) -> anyhow::Result> { + tracing::info!( + network, + s3_address, + bucket_name, + region, + "running NEAR Lake Indexer container..." + ); + + let image = GenericImage::new( + "ghcr.io/near/near-lake-indexer", + "e6519c922435f3d18b5f2ddac5d1ec171ef4dd6b", + ) + .with_env_var("AWS_ACCESS_KEY_ID", "FAKE_LOCALSTACK_KEY_ID") + .with_env_var("AWS_SECRET_ACCESS_KEY", "FAKE_LOCALSTACK_ACCESS_KEY") + .with_wait_for(WaitFor::message_on_stderr("Starting Streamer")) + .with_exposed_port(Self::CONTAINER_RPC_PORT); + let image: RunnableImage = ( + image, + vec![ + "--endpoint".to_string(), + s3_address.to_string(), + "--bucket".to_string(), + bucket_name.clone(), + "--region".to_string(), + region.clone(), + "--stream-while-syncing".to_string(), + "sync-from-latest".to_string(), + ], + ) + .into(); + let image = image.with_network(network); + let container = docker_client.cli.run(image); + let address = docker_client + .get_network_ip_address(&container, network) + .await?; + let rpc_address = format!("http://{}:{}", address, Self::CONTAINER_RPC_PORT); + let rpc_host_port = container.get_host_port_ipv4(Self::CONTAINER_RPC_PORT); + let rpc_host_address = format!("http://127.0.0.1:{rpc_host_port}"); + + tracing::info!( + bucket_name, + region, + rpc_address, + rpc_host_address, + "NEAR Lake Indexer container is running" + ); + Ok(LakeIndexer { + container, + bucket_name, + region, + rpc_address, + rpc_host_address, + }) + } +} + pub struct SignerNode<'a> { pub container: Container<'a, GenericImage>, pub address: String, diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index 3e4861d82..dcd12bc4f 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -8,7 +8,8 @@ use near_workspaces::{ Account, Worker, }; -use crate::env::containers; +use crate::env::containers::{self, LocalStack}; +use testcontainers::{Container, GenericImage}; pub mod env; pub mod mpc; @@ -16,22 +17,20 @@ pub mod multichain; pub mod sandbox; pub mod util; -async fn fetch_validator_keys( +async fn fetch_from_validator( docker_client: &containers::DockerClient, - sandbox: &containers::Sandbox<'_>, -) -> anyhow::Result { - tracing::info!("Fetching validator keys..."); + container: &Container<'_, GenericImage>, + path: &str, +) -> anyhow::Result> { + tracing::info!(path, "fetching data from validator"); let create_result = docker_client .docker .create_exec( - sandbox.container.id(), - CreateExecOptions:: { + container.id(), + CreateExecOptions::<&str> { attach_stdout: Some(true), attach_stderr: Some(true), - cmd: Some(vec![ - "cat".to_string(), - "/root/.near/validator_key.json".to_string(), - ]), + cmd: Some(vec!["cat", path]), ..Default::default() }, ) @@ -49,13 +48,23 @@ async fn fetch_validator_keys( stream_contents.extend_from_slice(&chunk?.into_bytes()); } - tracing::info!("Validator keys fetched"); - Ok(serde_json::from_slice(&stream_contents)?) + tracing::info!("data fetched"); + Ok(stream_contents) } StartExecResults::Detached => unreachable!("unexpected detached output"), } } +async fn fetch_validator_keys( + docker_client: &containers::DockerClient, + container: &Container<'_, GenericImage>, +) -> anyhow::Result { + let _span = tracing::info_span!("fetch_validator_keys"); + let key_data = + fetch_from_validator(docker_client, container, "/root/.near/validator_key.json").await?; + Ok(serde_json::from_slice(&key_data)?) +} + pub struct SandboxCtx<'a> { pub sandbox: containers::Sandbox<'a>, pub worker: Worker, @@ -68,7 +77,7 @@ pub async fn initialize_sandbox<'a>( tracing::info!("initializing sandbox"); let sandbox = containers::Sandbox::run(docker_client, network).await?; - let validator_key = fetch_validator_keys(docker_client, &sandbox).await?; + let validator_key = fetch_validator_keys(docker_client, &sandbox.container).await?; tracing::info!("initializing sandbox worker"); let worker = near_workspaces::sandbox() @@ -82,6 +91,48 @@ pub async fn initialize_sandbox<'a>( Ok(SandboxCtx { sandbox, worker }) } +pub struct LakeIndexerCtx<'a> { + pub localstack: containers::LocalStack<'a>, + pub lake_indexer: containers::LakeIndexer<'a>, + pub worker: Worker, +} + +pub async fn initialize_lake_indexer<'a>( + docker_client: &'a containers::DockerClient, + network: &str, +) -> anyhow::Result> { + let s3_bucket = "near-lake-custom".to_string(); + let s3_region = "us-east-1".to_string(); + let localstack = + LocalStack::run(docker_client, network, s3_bucket.clone(), s3_region.clone()).await?; + + let lake_indexer = containers::LakeIndexer::run( + docker_client, + network, + &localstack.s3_address, + s3_bucket, + s3_region, + ) + .await?; + + let validator_key = fetch_validator_keys(docker_client, &lake_indexer.container).await?; + + tracing::info!("initializing sandbox worker"); + let worker = near_workspaces::sandbox() + .rpc_addr(&lake_indexer.rpc_host_address) + .validator_key(ValidatorKey::Known( + validator_key.account_id.to_string().parse()?, + validator_key.secret_key.to_string().parse()?, + )) + .await?; + + Ok(LakeIndexerCtx { + localstack, + lake_indexer, + worker, + }) +} + pub struct RelayerCtx<'a> { pub sandbox: containers::Sandbox<'a>, pub redis: containers::Redis<'a>, @@ -96,7 +147,9 @@ pub async fn initialize_relayer<'a>( network: &str, relayer_id: &str, ) -> anyhow::Result> { - let SandboxCtx { sandbox, worker } = initialize_sandbox(docker_client, network).await?; + let SandboxCtx { + sandbox, worker, .. + } = initialize_sandbox(docker_client, network).await?; let social_db = sandbox::initialize_social_db(&worker).await?; sandbox::initialize_linkdrop(&worker).await?; diff --git a/integration-tests/src/multichain/containers.rs b/integration-tests/src/multichain/containers.rs index fbc9ebba2..f579533a0 100644 --- a/integration-tests/src/multichain/containers.rs +++ b/integration-tests/src/multichain/containers.rs @@ -35,11 +35,16 @@ impl<'a> Node<'a> { tracing::info!(node_id, "running node container"); let args = mpc_recovery_node::cli::Cli::Start { node_id: node_id.into(), - near_rpc: ctx.sandbox.local_address.clone(), + near_rpc: ctx.lake_indexer.rpc_host_address.clone(), mpc_contract_id: ctx.mpc_contract.id().clone(), account: account.clone(), account_sk: account_sk.to_string().parse()?, web_port: Self::CONTAINER_PORT, + indexer_options: mpc_recovery_node::indexer::Options { + s3_bucket: ctx.localstack.s3_host_address.clone(), + s3_region: ctx.localstack.s3_region.clone(), + start_block_height: 0, + }, } .into_str_args(); let image: GenericImage = GenericImage::new("near/mpc-recovery-node", "latest") diff --git a/integration-tests/src/multichain/local.rs b/integration-tests/src/multichain/local.rs index d1fe3a733..da32abd3f 100644 --- a/integration-tests/src/multichain/local.rs +++ b/integration-tests/src/multichain/local.rs @@ -24,11 +24,16 @@ impl Node { let web_port = util::pick_unused_port().await?; let cli = mpc_recovery_node::cli::Cli::Start { node_id: node_id.into(), - near_rpc: ctx.sandbox.local_address.clone(), + near_rpc: ctx.lake_indexer.rpc_host_address.clone(), mpc_contract_id: ctx.mpc_contract.id().clone(), account: account.clone(), account_sk: account_sk.to_string().parse()?, web_port, + indexer_options: mpc_recovery_node::indexer::Options { + s3_bucket: ctx.localstack.s3_host_address.clone(), + s3_region: ctx.localstack.s3_region.clone(), + start_block_height: 0, + }, }; let mpc_node_id = format!("multichain/{node_id}"); diff --git a/integration-tests/src/multichain/mod.rs b/integration-tests/src/multichain/mod.rs index d63ce483f..fa0b7020f 100644 --- a/integration-tests/src/multichain/mod.rs +++ b/integration-tests/src/multichain/mod.rs @@ -2,7 +2,7 @@ pub mod containers; pub mod local; use crate::env::containers::DockerClient; -use crate::{initialize_sandbox, SandboxCtx}; +use crate::{initialize_lake_indexer, LakeIndexerCtx}; use mpc_contract::ParticipantInfo; use near_workspaces::network::Sandbox; use near_workspaces::{AccountId, Contract, Worker}; @@ -62,7 +62,8 @@ pub struct Context<'a> { pub docker_network: String, pub release: bool, - pub sandbox: crate::env::containers::Sandbox<'a>, + pub localstack: crate::env::containers::LocalStack<'a>, + pub lake_indexer: crate::env::containers::LakeIndexer<'a>, pub worker: Worker, pub mpc_contract: Contract, } @@ -80,7 +81,11 @@ pub async fn setup(docker_client: &DockerClient) -> anyhow::Result> let docker_network = NETWORK; docker_client.create_network(docker_network).await?; - let SandboxCtx { sandbox, worker } = initialize_sandbox(docker_client, NETWORK).await?; + let LakeIndexerCtx { + localstack, + lake_indexer, + worker, + } = initialize_lake_indexer(docker_client, docker_network).await?; let mpc_contract = worker .dev_deploy(&std::fs::read( @@ -93,7 +98,8 @@ pub async fn setup(docker_client: &DockerClient) -> anyhow::Result> docker_client, docker_network: docker_network.to_string(), release, - sandbox, + localstack, + lake_indexer, worker, mpc_contract, }) diff --git a/integration-tests/tests/lib.rs b/integration-tests/tests/lib.rs index 0fafa27ad..501465554 100644 --- a/integration-tests/tests/lib.rs +++ b/integration-tests/tests/lib.rs @@ -72,7 +72,7 @@ where let docker_client = DockerClient::default(); let nodes = mpc_recovery_integration_tests::multichain::run(nodes, &docker_client).await?; - let rpc_client = near_fetch::Client::new(&nodes.ctx().sandbox.local_address); + let rpc_client = near_fetch::Client::new(&nodes.ctx().lake_indexer.rpc_host_address); f(MultichainTestContext { nodes, rpc_client, diff --git a/node/src/cli.rs b/node/src/cli.rs index 7863417c0..005ac4d63 100644 --- a/node/src/cli.rs +++ b/node/src/cli.rs @@ -34,6 +34,9 @@ pub enum Cli { /// The web port for this server #[arg(long, env("MPC_RECOVERY_WEB_PORT"))] web_port: u16, + /// NEAR Lake Indexer options + #[clap(flatten)] + indexer_options: indexer::Options, }, } @@ -52,8 +55,9 @@ impl Cli { account, account_sk, web_port, + indexer_options, } => { - vec![ + let mut args = vec![ "start".to_string(), "--node-id".to_string(), u32::from(node_id).to_string(), @@ -67,7 +71,9 @@ impl Cli { account_sk.to_string(), "--web-port".to_string(), web_port.to_string(), - ] + ]; + args.extend(indexer_options.into_str_args()); + args } } } @@ -94,6 +100,7 @@ pub fn run(cmd: Cli) -> anyhow::Result<()> { mpc_contract_id, account, account_sk, + indexer_options, } => { tokio::runtime::Builder::new_multi_thread() .enable_all() @@ -142,7 +149,7 @@ pub fn run(cmd: Cli) -> anyhow::Result<()> { anyhow::Ok(()) })?; - indexer::run(&near_rpc, mpc_contract_id)?; + indexer::run(&indexer_options, mpc_contract_id)?; } } diff --git a/node/src/indexer.rs b/node/src/indexer.rs index 4c7aba23c..8e7f498f8 100644 --- a/node/src/indexer.rs +++ b/node/src/indexer.rs @@ -2,6 +2,44 @@ use near_lake_framework::{LakeBuilder, LakeContext}; use near_lake_primitives::{receipts::ExecutionStatus, AccountId}; use serde::{Deserialize, Serialize}; +/// Configures exporter of span and trace data. +#[derive(Debug, clap::Parser)] +pub struct Options { + /// AWS S3 bucket name for NEAR Lake Indexer + #[clap( + long, + env("MPC_RECOVERY_INDEXER_S3_BUCKET"), + default_value = "near-lake-data-testnet" + )] + pub s3_bucket: String, + + /// AWS S3 region name for NEAR Lake Indexer + #[clap( + long, + env("MPC_RECOVERY_INDEXER_S3_REGION"), + default_value = "eu-central-1" + )] + pub s3_region: String, + + /// The block height to start indexing from. + // Defaults to the latest block on 2023-11-14 07:40:22 AM UTC + #[clap(long, default_value = "145964826")] + pub start_block_height: u64, +} + +impl Options { + pub fn into_str_args(self) -> Vec { + vec![ + "--s3-bucket".to_string(), + self.s3_bucket, + "--s3-region".to_string(), + self.s3_region, + "--start-block-height".to_string(), + self.start_block_height.to_string(), + ] + } +} + #[derive(Serialize, Deserialize)] struct SignPayload { payload: Vec, @@ -43,16 +81,13 @@ async fn handle_block( Ok(()) } -pub fn run(_near_rpc: &str, signer_account: AccountId) -> anyhow::Result<()> { - let mut config_builder = LakeBuilder::default(); - // config_builder = match near_network { - // "mainnet" => config_builder.mainnet().start_block_height(98924566), - // "testnet" => config_builder.testnet().start_block_height(134986320), - // other => anyhow::bail!("unrecognized NEAR network: {other}"), - // }; - config_builder = config_builder.testnet().start_block_height(134986320); +pub fn run(options: &Options, signer_account: AccountId) -> anyhow::Result<()> { + let lake = LakeBuilder::default() + .s3_bucket_name(&options.s3_bucket) + .s3_region_name(&options.s3_region) + .start_block_height(options.start_block_height) + .build()?; let context = Context { signer_account }; - let lake = config_builder.build()?; lake.run_with_context(handle_block, &context)?; Ok(()) }