diff --git a/README.md b/README.md index 70d06fab..07b883a8 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ To our knowledge, this design is unique to LEZ. Other privacy-focused programmab - Execution is handled fully on-chain without ZKPs. - Alice’s and Charlie’s public balances are updated. - + ### Key points: - The same token program is used in every execution. - The only difference is execution mode: public execution updates visible state on-chain, while private execution relies on ZKPs. @@ -127,6 +127,9 @@ RUST_LOG=info RISC0_DEV_MODE=1 cargo run $(pwd)/configs/debug all # Run the sequencer and node + +## Running Manually + The sequencer and node can be run locally: 1. On one terminal go to the `logos-blockchain/logos-blockchain` repo and run a local logos blockchain node: @@ -138,10 +141,22 @@ The sequencer and node can be run locally: - `./target/debug/logos-blockchain-node nodes/node/config-one-node.yaml` 2. On another terminal go to the `logos-blockchain/lssa` repo and run indexer service: - - `git checkout schouhy/full-bedrock-integration` - - `RUST_LOG=info cargo run --release -p indexer_service $(pwd)/integration_tests/configs/indexer/indexer_config.json` + - `RUST_LOG=info cargo run --release -p indexer_service indexer/service/configs/indexer_config.json` 3. On another terminal go to the `logos-blockchain/lssa` repo and run the sequencer: - - `git checkout schouhy/full-bedrock-integration` - `RUST_LOG=info RISC0_DEV_MODE=1 cargo run --release -p sequencer_runner sequencer_runner/configs/debug` +## Running with Docker + +You can run the whole setup with Docker: + +```bash +docker compose up +``` + +With that you can send transactions from local wallet to the Sequencer running inside Docker using `wallet/configs/debug` as well as exploring blocks by opening `http://localhost:8080`. + +## Caution for local image builds + +If you're going to build sequencer image locally you should better adjust default docker settings and set `defaultKeepStorage` at least `25GB` so that it can keep layers properly cached. + diff --git a/integration_tests/bedrock/README.md b/bedrock/README.md similarity index 95% rename from integration_tests/bedrock/README.md rename to bedrock/README.md index 2c6f47b2..13de0faf 100644 --- a/integration_tests/bedrock/README.md +++ b/bedrock/README.md @@ -1,4 +1,4 @@ -# Bedrock Configuration Files for Integration Tests +# Bedrock Configuration Files for All-in-One run and Integration Tests ## How to update diff --git a/integration_tests/bedrock/cfgsync.yaml b/bedrock/cfgsync.yaml similarity index 54% rename from integration_tests/bedrock/cfgsync.yaml rename to bedrock/cfgsync.yaml index 097fa801..e09fe586 100644 --- a/integration_tests/bedrock/cfgsync.yaml +++ b/bedrock/cfgsync.yaml @@ -4,11 +4,9 @@ timeout: 10 # Tracing tracing_settings: - logger: None + logger: Stdout tracing: None - filter: !EnvFilter - filters: - logos-blockchain: debug + filter: None metrics: None console: None - level: INFO + level: DEBUG diff --git a/integration_tests/bedrock/docker-compose.yml b/bedrock/docker-compose.yml similarity index 100% rename from integration_tests/bedrock/docker-compose.yml rename to bedrock/docker-compose.yml diff --git a/integration_tests/bedrock/kzgrs_test_params b/bedrock/kzgrs_test_params similarity index 100% rename from integration_tests/bedrock/kzgrs_test_params rename to bedrock/kzgrs_test_params diff --git a/integration_tests/bedrock/scripts/run_cfgsync.sh b/bedrock/scripts/run_cfgsync.sh similarity index 100% rename from integration_tests/bedrock/scripts/run_cfgsync.sh rename to bedrock/scripts/run_cfgsync.sh diff --git a/integration_tests/bedrock/scripts/run_logos_blockchain_node.sh b/bedrock/scripts/run_logos_blockchain_node.sh similarity index 100% rename from integration_tests/bedrock/scripts/run_logos_blockchain_node.sh rename to bedrock/scripts/run_logos_blockchain_node.sh diff --git a/bedrock_client/src/lib.rs b/bedrock_client/src/lib.rs index 975c24d1..91687545 100644 --- a/bedrock_client/src/lib.rs +++ b/bedrock_client/src/lib.rs @@ -3,7 +3,7 @@ use std::time::Duration; use anyhow::{Context as _, Result}; use common::config::BasicAuth; use futures::{Stream, TryFutureExt}; -use log::warn; +use log::{info, warn}; pub use logos_blockchain_chain_broadcast_service::BlockInfo; pub use logos_blockchain_common_http_client::{CommonHttpClient, Error}; pub use logos_blockchain_core::{block::Block, header::HeaderId, mantle::SignedMantleTx}; @@ -39,6 +39,7 @@ pub struct BedrockClient { impl BedrockClient { pub fn new(backoff: BackoffConfig, node_url: Url, auth: Option) -> Result { + info!("Creating Bedrock client with node URL {node_url}"); let client = Client::builder() //Add more fields if needed .timeout(std::time::Duration::from_secs(60)) @@ -61,7 +62,7 @@ impl BedrockClient { Retry::spawn(self.backoff_strategy(), || { self.http_client .post_transaction(self.node_url.clone(), tx.clone()) - .inspect_err(|err| warn!("Transaction posting failed with err: {err:#?}")) + .inspect_err(|err| warn!("Transaction posting failed with error: {err:#}")) }) .await } @@ -77,7 +78,7 @@ impl BedrockClient { Retry::spawn(self.backoff_strategy(), || { self.http_client .get_block_by_id(self.node_url.clone(), header_id) - .inspect_err(|err| warn!("Block fetching failed with err: {err:#?}")) + .inspect_err(|err| warn!("Block fetching failed with error: {err:#}")) }) .await } diff --git a/configs/docker-all-in-one/indexer/indexer_config.json b/configs/docker-all-in-one/indexer/indexer_config.json new file mode 100644 index 00000000..ae106b46 --- /dev/null +++ b/configs/docker-all-in-one/indexer/indexer_config.json @@ -0,0 +1,11 @@ +{ + "resubscribe_interval_millis": 1000, + "bedrock_client_config": { + "addr": "http://logos-blockchain-node-0:18080", + "backoff": { + "start_delay_millis": 100, + "max_retries": 5 + } + }, + "channel_id": "0101010101010101010101010101010101010101010101010101010101010101" +} diff --git a/configs/docker-all-in-one/sequencer/sequencer_config.json b/configs/docker-all-in-one/sequencer/sequencer_config.json new file mode 100644 index 00000000..4acabb95 --- /dev/null +++ b/configs/docker-all-in-one/sequencer/sequencer_config.json @@ -0,0 +1,168 @@ +{ + "home": "/var/lib/sequencer_runner", + "override_rust_log": null, + "genesis_id": 1, + "is_genesis_random": true, + "max_num_tx_in_block": 20, + "mempool_max_size": 10000, + "block_create_timeout_millis": 10000, + "retry_pending_blocks_timeout_millis": 7000, + "port": 3040, + "bedrock_config": { + "backoff": { + "start_delay_millis": 100, + "max_retries": 5 + }, + "channel_id": "0101010101010101010101010101010101010101010101010101010101010101", + "node_url": "http://logos-blockchain-node-0:18080" + }, + "indexer_rpc_url": "ws://indexer_service:8779", + "initial_accounts": [ + { + "account_id": "BLgCRDXYdQPMMWVHYRFGQZbgeHx9frkipa8GtpG2Syqy", + "balance": 10000 + }, + { + "account_id": "Gj1mJy5W7J5pfmLRujmQaLfLMWidNxQ6uwnhb666ZwHw", + "balance": 20000 + } + ], + "initial_commitments": [ + { + "npk": [ + 63, + 202, + 178, + 231, + 183, + 82, + 237, + 212, + 216, + 221, + 215, + 255, + 153, + 101, + 177, + 161, + 254, + 210, + 128, + 122, + 54, + 190, + 230, + 151, + 183, + 64, + 225, + 229, + 113, + 1, + 228, + 97 + ], + "account": { + "program_owner": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "balance": 10000, + "data": [], + "nonce": 0 + } + }, + { + "npk": [ + 192, + 251, + 166, + 243, + 167, + 236, + 84, + 249, + 35, + 136, + 130, + 172, + 219, + 225, + 161, + 139, + 229, + 89, + 243, + 125, + 194, + 213, + 209, + 30, + 23, + 174, + 100, + 244, + 124, + 74, + 140, + 47 + ], + "account": { + "program_owner": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "balance": 20000, + "data": [], + "nonce": 0 + } + } + ], + "signing_key": [ + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37, + 37 + ] +} \ No newline at end of file diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 00000000..fe0d18f9 --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,27 @@ +# This file is automatically applied on top of docker-compose.yml when running `docker compose` commands. + +services: + logos-blockchain-node-0: + ports: !override + - "18080:18080/tcp" + environment: + - RUST_LOG=error + + sequencer_runner: + depends_on: + - logos-blockchain-node-0 + - indexer_service + volumes: !override + - ./configs/docker-all-in-one/sequencer:/etc/sequencer_runner + + indexer_service: + depends_on: + - logos-blockchain-node-0 + volumes: + - ./configs/docker-all-in-one/indexer/indexer_config.json:/etc/indexer_service/indexer_config.json + + explorer_service: + depends_on: + - indexer_service + environment: + - INDEXER_RPC_URL=http://indexer_service:8779 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..93b5896b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +# All-in-one docker compose configuration. +# It runs all services from this repo and the bedrock nodes in a single docker network. +# This is useful for development and testing purposes. + +include: + - path: + bedrock/docker-compose.yml + - path: + sequencer_runner/docker-compose.yml + - path: + indexer/service/docker-compose.yml + - path: + explorer_service/docker-compose.yml diff --git a/indexer/core/src/config.rs b/indexer/core/src/config.rs index e6d1c136..f823f9ab 100644 --- a/indexer/core/src/config.rs +++ b/indexer/core/src/config.rs @@ -12,6 +12,7 @@ pub struct BedrockClientConfig { /// For individual RPC requests we use Fibonacci backoff retry strategy. pub backoff: BackoffConfig, pub addr: Url, + #[serde(default, skip_serializing_if = "Option::is_none")] pub auth: Option, } diff --git a/indexer/service/Dockerfile b/indexer/service/Dockerfile index b283e2ec..b6a896b2 100644 --- a/indexer/service/Dockerfile +++ b/indexer/service/Dockerfile @@ -36,7 +36,9 @@ RUN strip /indexer_service/target/release/indexer_service FROM debian:trixie-slim # Create non-root user for security -RUN useradd -m -u 1000 -s /bin/bash indexer_service_user +RUN useradd -m -u 1000 -s /bin/bash indexer_service_user && \ + mkdir -p /indexer_service /etc/indexer_service && \ + chown -R indexer_service_user:indexer_service_user /indexer_service /etc/indexer_service # Copy binary from builder COPY --from=builder --chown=indexer_service_user:indexer_service_user /indexer_service/target/release/indexer_service /usr/local/bin/indexer_service @@ -61,4 +63,4 @@ ENV RUST_LOG=info USER indexer_service_user WORKDIR /indexer_service -CMD ["indexer_service"] +CMD ["indexer_service", "/etc/indexer_service/indexer_config.json"] diff --git a/indexer/service/configs/indexer_config.json b/indexer/service/configs/indexer_config.json new file mode 100644 index 00000000..93d424c5 --- /dev/null +++ b/indexer/service/configs/indexer_config.json @@ -0,0 +1,11 @@ +{ + "resubscribe_interval_millis": 1000, + "bedrock_client_config": { + "addr": "http://localhost:18080", + "backoff": { + "start_delay_millis": 100, + "max_retries": 5 + } + }, + "channel_id": "0101010101010101010101010101010101010101010101010101010101010101" +} diff --git a/indexer/service/docker-compose.yml b/indexer/service/docker-compose.yml index 81e68cfa..fe650a2a 100644 --- a/indexer/service/docker-compose.yml +++ b/indexer/service/docker-compose.yml @@ -2,8 +2,11 @@ services: indexer_service: image: lssa/indexer_service build: - context: .. - dockerfile: indexer_service/Dockerfile + context: ../.. + dockerfile: indexer/service/Dockerfile container_name: indexer_service ports: - "8779:8779" + volumes: + # Mount configuration + - ./configs/indexer_config.json:/etc/indexer_service/indexer_config.json diff --git a/indexer/service/src/service.rs b/indexer/service/src/service.rs index 6c4870b1..a0356b2a 100644 --- a/indexer/service/src/service.rs +++ b/indexer/service/src/service.rs @@ -8,7 +8,7 @@ use indexer_service_protocol::{Account, AccountId, Block, BlockId, HashType, Tra use jsonrpsee::{ SubscriptionSink, core::{Serialize, SubscriptionResult}, - types::ErrorObjectOwned, + types::{ErrorCode, ErrorObject, ErrorObjectOwned}, }; use log::{debug, error, info, warn}; use tokio::sync::mpsc::UnboundedSender; @@ -54,23 +54,23 @@ impl indexer_service_rpc::RpcServer for IndexerService { } async fn get_block_by_id(&self, _block_id: BlockId) -> Result { - todo!() + Err(not_yet_implemented_error()) } async fn get_block_by_hash(&self, _block_hash: HashType) -> Result { - todo!() + Err(not_yet_implemented_error()) } async fn get_account(&self, _account_id: AccountId) -> Result { - todo!() + Err(not_yet_implemented_error()) } async fn get_transaction(&self, _tx_hash: HashType) -> Result { - todo!() + Err(not_yet_implemented_error()) } async fn get_blocks(&self, _offset: u32, _limit: u32) -> Result, ErrorObjectOwned> { - todo!() + Err(not_yet_implemented_error()) } async fn get_transactions_by_account( @@ -79,7 +79,7 @@ impl indexer_service_rpc::RpcServer for IndexerService { _limit: u32, _offset: u32, ) -> Result, ErrorObjectOwned> { - todo!() + Err(not_yet_implemented_error()) } } @@ -105,6 +105,7 @@ impl SubscriptionService { // Respawn the subscription service loop if it has finished (either with error or panic) if guard.handle.is_finished() { + drop(guard); let new_parts = Self::spawn_respond_subscribers_loop(self.indexer.clone()); let old_handle_and_sender = self.parts.swap(Arc::new(new_parts)); let old_parts = Arc::into_inner(old_handle_and_sender) @@ -113,7 +114,7 @@ impl SubscriptionService { match old_parts.handle.await { Ok(Err(err)) => { error!( - "Subscription service loop has unexpectedly finished with err: {err:#}" + "Subscription service loop has unexpectedly finished with error: {err:#}" ); } Err(err) => { @@ -217,3 +218,11 @@ impl Drop for Subscription { ); } } + +fn not_yet_implemented_error() -> ErrorObjectOwned { + ErrorObject::owned( + ErrorCode::InternalError.code(), + "Not yet implemented", + Option::::None, + ) +} diff --git a/integration_tests/src/lib.rs b/integration_tests/src/lib.rs index 9adda331..c193b2d7 100644 --- a/integration_tests/src/lib.rs +++ b/integration_tests/src/lib.rs @@ -100,7 +100,8 @@ impl TestContext { async fn setup_bedrock_node() -> Result<(DockerCompose, SocketAddr)> { let manifest_dir = env!("CARGO_MANIFEST_DIR"); - let bedrock_compose_path = PathBuf::from(manifest_dir).join("bedrock/docker-compose.yml"); + let bedrock_compose_path = + PathBuf::from(manifest_dir).join("../bedrock/docker-compose.yml"); let mut compose = DockerCompose::with_auto_client(&[bedrock_compose_path]) .await diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 3ec291c4..bf951337 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,5 @@ +# Should be kept in sync with Dockerfiles + [toolchain] channel = "1.91.1" profile = "default" diff --git a/sequencer_core/src/indexer_client.rs b/sequencer_core/src/indexer_client.rs index 50b33ed8..960b77a4 100644 --- a/sequencer_core/src/indexer_client.rs +++ b/sequencer_core/src/indexer_client.rs @@ -1,6 +1,7 @@ use std::{ops::Deref, sync::Arc}; use anyhow::{Context as _, Result}; +use log::info; pub use url::Url; #[expect(async_fn_in_trait, reason = "We don't care about Send/Sync here")] @@ -13,6 +14,8 @@ pub struct IndexerClient(Arc); impl IndexerClientTrait for IndexerClient { async fn new(indexer_url: &Url) -> Result { + info!("Connecting to Indexer at {indexer_url}"); + let client = jsonrpsee::ws_client::WsClientBuilder::default() .build(indexer_url) .await diff --git a/sequencer_runner/Dockerfile b/sequencer_runner/Dockerfile index 0ad7b132..679ff361 100644 --- a/sequencer_runner/Dockerfile +++ b/sequencer_runner/Dockerfile @@ -1,15 +1,34 @@ # Chef stage - uses pre-built cargo-chef image FROM lukemathwalker/cargo-chef:latest-rust-1.91.1-slim-trixie AS chef -# Install build dependencies +# Install dependencies RUN apt-get update && apt-get install -y \ + build-essential \ pkg-config \ libssl-dev \ libclang-dev \ clang \ + cmake \ + ninja-build \ curl \ + git \ && rm -rf /var/lib/apt/lists/* +# Install r0vm (manual build as it's portable across different host platforms) +RUN git clone --depth 1 --branch release-3.0 https://github.com/risc0/risc0.git +RUN git clone --depth 1 --branch r0.1.91.1 https://github.com/risc0/rust.git +WORKDIR /risc0 +RUN cargo install --path rzup +RUN rzup build --path /rust rust --verbose +RUN cargo install --path risc0/cargo-risczero +ENV PATH="/root/.cargo/bin:/root/.risc0/bin:${PATH}" +RUN cp "$(which r0vm)" /usr/local/bin/r0vm +RUN test -x /usr/local/bin/r0vm +RUN r0vm --version + +# Install logos blockchain circuits +RUN curl -sSL https://raw.githubusercontent.com/logos-blockchain/logos-blockchain/main/scripts/setup-logos-blockchain-circuits.sh | bash + WORKDIR /sequencer_runner # Planner stage - generates dependency recipe @@ -32,14 +51,6 @@ RUN cargo build --release --bin sequencer_runner # Strip debug symbols to reduce binary size RUN strip /sequencer_runner/target/release/sequencer_runner -# Install r0vm -RUN curl -L https://risczero.com/install | bash -ENV PATH="/root/.cargo/bin:/root/.risc0/bin:${PATH}" -RUN rzup install -RUN cp "$(which r0vm)" /usr/local/bin/r0vm -RUN test -x /usr/local/bin/r0vm -RUN r0vm --version - # Runtime stage - minimal image FROM debian:trixie-slim @@ -59,6 +70,9 @@ COPY --from=builder --chown=sequencer_user:sequencer_user /sequencer_runner/targ # Copy r0vm binary from builder COPY --from=builder --chown=sequencer_user:sequencer_user /usr/local/bin/r0vm /usr/local/bin/r0vm +# Copy logos blockchain circuits from builder +COPY --from=builder --chown=sequencer_user:sequencer_user /root/.logos-blockchain-circuits /home/sequencer_user/.logos-blockchain-circuits + # Copy entrypoint script COPY sequencer_runner/docker-entrypoint.sh /docker-entrypoint.sh RUN chmod +x /docker-entrypoint.sh diff --git a/sequencer_runner/configs/debug/sequencer_config.json b/sequencer_runner/configs/debug/sequencer_config.json index 9ab5d98d..cd6840e6 100644 --- a/sequencer_runner/configs/debug/sequencer_config.json +++ b/sequencer_runner/configs/debug/sequencer_config.json @@ -8,6 +8,15 @@ "block_create_timeout_millis": 5000, "retry_pending_blocks_timeout_millis": 7000, "port": 3040, + "bedrock_config": { + "backoff": { + "start_delay_millis": 100, + "max_retries": 5 + }, + "channel_id": "0101010101010101010101010101010101010101010101010101010101010101", + "node_url": "http://localhost:18080" + }, + "indexer_rpc_url": "ws://localhost:8779", "initial_accounts": [ { "account_id": "BLgCRDXYdQPMMWVHYRFGQZbgeHx9frkipa8GtpG2Syqy", @@ -155,13 +164,5 @@ 37, 37, 37 - ], - "bedrock_config": { - "channel_id": "0101010101010101010101010101010101010101010101010101010101010101", - "node_url": "http://localhost:8080", - "auth": { - "username": "user" - } - }, - "indexer_rpc_url": "ws://localhost:8779" + ] } diff --git a/sequencer_runner/configs/docker/sequencer_config.json b/sequencer_runner/configs/docker/sequencer_config.json index 8ac66d48..4dd817c9 100644 --- a/sequencer_runner/configs/docker/sequencer_config.json +++ b/sequencer_runner/configs/docker/sequencer_config.json @@ -7,6 +7,16 @@ "mempool_max_size": 10000, "block_create_timeout_millis": 10000, "port": 3040, + "retry_pending_blocks_timeout_millis": 7000, + "bedrock_config": { + "backoff": { + "start_delay_millis": 100, + "max_retries": 5 + }, + "channel_id": "0101010101010101010101010101010101010101010101010101010101010101", + "node_url": "http://localhost:18080" + }, + "indexer_rpc_url": "ws://localhost:8779", "initial_accounts": [ { "account_id": "6iArKUXxhUJqS7kCaPNhwMWt3ro71PDyBj7jwAyE2VQV", diff --git a/sequencer_runner/src/lib.rs b/sequencer_runner/src/lib.rs index 3cd84ee5..1dab37d5 100644 --- a/sequencer_runner/src/lib.rs +++ b/sequencer_runner/src/lib.rs @@ -244,7 +244,7 @@ pub async fn main_runner() -> Result<()> { info!("Sequencer running. Monitoring concurrent tasks..."); let Err(err) = sequencer_handle.run_forever().await; - error!("Sequencer failed: {err:?}"); + error!("Sequencer failed: {err:#}"); info!("Shutting down sequencer...");