From f0dd94bb12620a8517c3bbe9965987ab5f353b20 Mon Sep 17 00:00:00 2001 From: mohiiit Date: Tue, 17 Dec 2024 17:41:08 +0530 Subject: [PATCH 01/17] chore: readme udpated: --- README.md | 464 ++++++++++++++++++++++---------------------- madara-bootstrapper | 2 +- 2 files changed, 233 insertions(+), 233 deletions(-) diff --git a/README.md b/README.md index f05e12ef..a93890e2 100644 --- a/README.md +++ b/README.md @@ -1,61 +1,43 @@ # Madara Orchestrator ๐ŸŽญ -The Madara orchestrator is designed to be an additional service which runs in -parallel to Madara and handles various critical jobs that ensure proper block -processing, proof generation, data submission and state transitions. +Madara Orchestrator is a service that runs parallel to Madara, managing critical jobs for block processing, proof generation, data submission, and state transitions. -## ๐Ÿ“‹ Overview +> ๐Ÿ“ **Note**: These instructions are verified for Ubuntu systems. While most steps remain similar for macOS, some package names and installation commands may differ. -The Madara Orchestrator coordinates and triggers five primary jobs in sequence, -managing their execution through a centralized queue system, alowing -for multiple orchestrator to run together! +## Table of Contents -1. **SNOS (Starknet OS) Job** ๐Ÿ”„ +- [Overview](#overview) +- [Architecture](#architecture) +- [Build Requirements](#build-requirements) +- [Building from Source](#building-from-source) +- [Deployment](#deployment) + - [Local Development](#local-development) + - [Production](#production) +- [Configuration](#configuration) +- [Testing](#testing) +- [Monitoring](#monitoring) +- [Error Handling](#error-handling) - - Identifies blocks that need processing. - - Triggers SNOS run on identified blocks. - - Tracks SNOS execution status and PIE (Program Independent Execution) generation +## Overview -2. **Proving Job** โœ… +The Madara Orchestrator coordinates five primary jobs through a centralized queue system: - - Coordinates proof generation by submitting PIE to proving services - - Tracks proof generation progress and completion +1. **SNOS (Starknet OS) Job**: Processes blocks and generates Program Independent Execution (PIE) +2. **Proving Job**: Manages proof generation using PIE +3. **Data Submission Job**: Handles state updates for availability layers (Currently supports Ethereum EIP-4844) +4. **State Transition Job**: Manages state transitions with settlement layers (Ethereum and Starknet) -3. **Data Submission Job** ๐Ÿ“ค - - - Manages state update data preparation for availability layers - - If needed, coordinates blob submission to data availability layers - - Currently integrates with Ethereum (EIP-4844 blob transactions) - - Additional DA layer integrations in development (e.g., Celestia) - -4. **State Transition Job** ๐Ÿ”„ - - Coordinates state transitions with settlement layers - - Manages proof and state update submissions - - Handles integration with Ethereum and Starknet settlement layers - -Each job is managed through a queue-based system where the orchestrator: - -- Determines when and which blocks need processing -- Triggers the appropriate services -- Monitors job progress -- Manages job dependencies and sequencing -- Handles retries and failure cases - -## ๐Ÿ›๏ธ Architecture +## Architecture ### Job Processing Model -The orchestrator implements a queue-based architecture where each job type -follows a three-phase execution model: - -1. **Creation**: Jobs are spawned based on block availability -2. **Processing**: Core job logic execution -3. **Verification**: Result validation and confirmation +The orchestrator uses a queue-based architecture with three execution phases: +1. Creation: Jobs are spawned based on block availability +2. Processing: Core job logic execution +3. Verification: Result validation and confirmation ### Queue Structure -The system uses dedicated queues for managing different job phases: - - Worker Trigger Queue - SNOS Processing/Verification Queues - Proving Processing/Verification Queues @@ -65,218 +47,236 @@ The system uses dedicated queues for managing different job phases: ### Workflow -1. Cron jobs trigger worker tasks via the worker-trigger queue -2. Workers determine block-level job requirements +1. Cron jobs trigger worker tasks +2. Workers determine block-level requirements 3. Jobs are created and added to processing queues 4. Processed jobs move to verification queues -5. Verified jobs are marked as complete in the database - -## ๐Ÿ› ๏ธ Technical Requirements - -### Prerequisites - -1. **Madara Node** - - - Required for block processing - - Follow setup instructions at [Madara Documentation](https://github.com/madara-alliance/madara) - -2. **Prover Service** - - - ATLANTIC must be running - -3. **Infrastructure Dependencies** - - MongoDB for job management - - AWS services (or Localstack for local development): - - SQS for queues - - S3 for data storage - - SNS for alerts - - EventBridge for scheduling - -## ๐Ÿš€ Installation & Setup - -### Setup Mode - -Setup mode configures the required AWS services and dependencies. -Use the following command: - -```bash -cargo run --release --bin orchestrator setup --aws --aws-s3 --aws-sqs --aws-sns --aws-event-bridge -``` - -Note: Setup mode is currently in development. A fresh setup is required -if the process fails mid-way. - -### Run Mode - -Run mode executes the orchestrator's job processing workflow. Example command: - -```bash -RUST_LOG=info cargo run --release --bin orchestrator run --atlantic --aws --settle-on-ethereum --aws-s3 --aws-sqs --aws-sns --da-on-ethereum --mongodb -``` - -### Command Line Options - -1. **Prover Services** (choose one): - - - `--atlantic`: Use Atlantic prover - - `--sharp`: Use SHARP prover - -2. **Settlement Layer** (choose one): - - - `--settle-on-ethereum`: Use Ethereum - - `--settle-on-starknet`: Use Starknet - -3. **Data Availability**: - - - `--da-on-ethereum`: Use Ethereum - -4. **Infrastructure**: - - - `--aws`: Use AWS services (or Localstack) - -5. **Data Storage**: - - - `--aws-s3`: Store state updates and program outputs - -6. **Database**: - - - `--mongodb`: Store job information - -7. **Queue System**: - - - `--aws-sqs`: Message queue service - -8. **Alerting**: - - - `--aws-sns`: Notification service - -9. **Scheduling**: - - - `--aws-event-bridge`: Cron job scheduling - -10. **Monitoring**: - - `--otel-service-name`: OpenTelemetry service name - - `--otel-collector-endpoint`: OpenTelemetry collector endpoint - -## โš™๏ธ Configuration - -The orchestrator uses environment variables for configuration. -Create a `.env` file with the following sections: - -### AWS Configuration - +5. Verified jobs are marked complete in the database + +## Build Requirements + +### System Dependencies +> For macOS users, use `brew install` instead of `apt install` for these dependencies. + +- Build essentials (`build-essential`) +- OpenSSL (`libssl-dev`) +- Package config (`pkg-config`) +- Python 3.9 with development files +- GMP library (`libgmp-dev`) + +### Core Dependencies +- [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +- [Rust](https://www.rust-lang.org/tools/install) +- [Madara Node](https://github.com/madara-alliance/madara) +- Prover Service (ATLANTIC) + +## Building from Source + +1. **Install System Dependencies** + ```bash + # Ubuntu/Debian + sudo apt-get update + sudo apt install build-essential openssl pkg-config libssl-dev + sudo apt install python3.9 python3.9-venv python3.9-distutils libgmp-dev python3.9-dev + + # For macOS + brew install openssl pkg-config gmp python@3.9 + ``` + +2. **Install Rust** (Cross-platform) + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + source ~/.bashrc # Or source ~/.zshrc for macOS + ``` + +3. **Clone Repository** + ```bash + git clone https://github.com/madara-alliance/madara-orchestrator.git + cd madara-orchestrator + git submodule update --init + ``` + +4. **Build SNOS** + ```bash + make snos + ``` + +5. **Build Project** + ```bash + cargo build --release + ``` + +## Deployment + +### Local Development + +#### Additional Requirements +1. **Docker** - For running local services +2. **MongoDB** - For job management +3. **Localstack** - For simulating AWS services +4. **Anvil** - For local Ethereum node +5. **Foundry** - For Ethereum development tools + +#### Setup Steps + +1. **Install Docker** (Cross-platform) + Follow the official installation guides: + - [Ubuntu Installation Guide](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository) + - [macOS Installation Guide](https://docs.docker.com/desktop/install/mac-install/) + +2. **Install Foundry** (Cross-platform) + ```bash + curl -L https://foundry.paradigm.xyz | bash + foundryup + ``` + +3. **Start Local Services** + ```bash + # Start MongoDB + docker run -d -p 27017:27017 mongo + + # Start Localstack + docker run -d -p 4566:4566 localstack/localstack@sha256:763947722c6c8d33d5fbf7e8d52b4bddec5be35274a0998fdc6176d733375314 + + # Start Anvil in a separate terminal + anvil --block-time 1 + ``` + +4. **Initialize Local Infrastructure** + ```bash + cargo run --release --bin orchestrator setup --aws --aws-s3 --aws-sqs --aws-sns --aws-event-bridge + ``` + +5. **Run Orchestrator Locally** + ```bash + RUST_LOG=info cargo run --release --bin orchestrator run \ + --atlantic \ + --aws \ + --settle-on-ethereum \ + --aws-s3 \ + --aws-sqs \ + --aws-sns \ + --da-on-ethereum \ + --mongodb + ``` + +### Production + +#### Requirements +- AWS Account with access to: + - S3 + - SQS + - SNS + - EventBridge +- MongoDB instance +- Ethereum RPC endpoint +- ATLANTIC prover service access + +#### Deployment Steps + +1. **Configure AWS Services** + See [Configuration](#configuration) section for required environment variables. + ```bash + cargo run --release --bin orchestrator setup \ + --aws \ + --aws-s3 \ + --aws-sqs \ + --aws-sns \ + --aws-event-bridge + ``` + +2. **Run Orchestrator** + ```bash + RUST_LOG=info cargo run --release --bin orchestrator run \ + --atlantic \ + --aws \ + --settle-on-ethereum \ + --aws-s3 \ + --aws-sqs \ + --aws-sns \ + --da-on-ethereum \ + --mongodb + ``` + +## Configuration + +Create a `.env` file with appropriate values for your environment: + +### Production Environment ```env +# AWS Configuration AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_REGION= -``` - -Note: These configurations are also picked up from - -### Prover Configuration -```env -# SHARP Configuration -MADARA_ORCHESTRATOR_SHARP_CUSTOMER_ID= -MADARA_ORCHESTRATOR_SHARP_URL= -# or -# ATLANTIC Configuration +# Prover Configuration MADARA_ORCHESTRATOR_ATLANTIC_API_KEY= MADARA_ORCHESTRATOR_ATLANTIC_SERVICE_URL= -``` -### Database Configuration +# Database Configuration +MADARA_ORCHESTRATOR_MONGODB_CONNECTION_URL= +MADARA_ORCHESTRATOR_DATABASE_NAME=orchestrator + +# RPC Configuration +MADARA_ORCHESTRATOR_ETHEREUM_SETTLEMENT_RPC_URL= +MADARA_ORCHESTRATOR_RPC_FOR_SNOS= +``` +### Local Development ```env +# AWS Configuration (Localstack) +AWS_ACCESS_KEY_ID=test +AWS_SECRET_ACCESS_KEY=test +AWS_REGION=us-east-1 + +# Database Configuration MADARA_ORCHESTRATOR_MONGODB_CONNECTION_URL=mongodb://localhost:27017 MADARA_ORCHESTRATOR_DATABASE_NAME=orchestrator + +# RPC Configuration +MADARA_ORCHESTRATOR_ETHEREUM_SETTLEMENT_RPC_URL=http://localhost:8545 +MADARA_ORCHESTRATOR_RPC_FOR_SNOS= ``` -For a complete list of configuration options, refer to the `.env.example` file -in the repository. +## Testing + +### Local Environment Tests +Requires [local services](#local-development) to be running (MongoDB, Localstack, Anvil) -## ๐Ÿ” Monitoring +1. **E2E Tests** + ```bash + RUST_LOG=info cargo test --features testing test_orchestrator_workflow -- --nocapture + ``` -The orchestrator includes a telemetry system that tracks: +2. **Integration and Unit Tests** + ```bash + RUST_LOG=debug RUST_BACKTRACE=1 cargo llvm-cov nextest \ + --release \ + --features testing \ + --lcov \ + --output-path lcov.info \ + --test-threads=1 \ + --workspace \ + --exclude=e2e-tests \ + --no-fail-fast + ``` +## Monitoring + +The orchestrator includes [OpenTelemetry](https://opentelemetry.io/) integration for monitoring: - Job execution metrics -- Processing time statistics +- Processing time statistics - RPC performance metrics -OpenTelemetry integration is available for detailed monitoring. -It requires a `Otel-collector` url to be able to send metrics/logs/traces. +Configure monitoring using: +- `--otel-service-name`: OpenTelemetry service name +- `--otel-collector-endpoint`: OpenTelemetry collector endpoint -## ๐Ÿ› Error Handling +## Error Handling -- Failed jobs are moved to a dedicated failure handling queue +- Failed jobs move to a dedicated failure queue (see [Queue Structure](#queue-structure)) - Automatic retry mechanism with configurable intervals -- Failed jobs are tracked in the database for manual inspection after maximum retries -- Integrated telemetry system for monitoring job failures - -## ๐Ÿงช Testing - -The Madara Orchestrator supports three types of tests: - -### Types of Tests - -1. **E2E Tests** ๐Ÿ”„ - - - End-to-end workflow testing - - Tests orchestrator functionality on block 66645 of Starknet - - Uses mocked proving endpoints - -2. **Integration & Unit Tests** ๐Ÿ”Œ - -### Running Tests - -#### Required Services - -- MongoDB running on port 27017 -- Localstack running on port 4566 -- Anvil (local Ethereum node) - -#### Environment Configuration - -```bash -export MADARA_ORCHESTRATOR_ETHEREUM_SETTLEMENT_RPC_URL= -export MADARA_ORCHESTRATOR_RPC_FOR_SNOS= -export AWS_REGION=us-east-1 -``` - -#### Running E2E Tests - -```bash -RUST_LOG=info cargo test --features testing test_orchestrator_workflow -- --nocapture -``` - -#### Running Integration and Unit Tests - -The orchestrator uses LLVM coverage testing to ensure comprehensive test coverage -of the codebase. - -```bash -RUST_LOG=debug RUST_BACKTRACE=1 cargo llvm-cov nextest \ - --release \ - --features testing \ - --lcov \ - --output-path lcov.info \ - --test-threads=1 \ - --workspace \ - --exclude=e2e-tests \ - --no-fail-fast -``` - -This command: - -- Generates detailed coverage reports in LCOV format -- Excludes E2E tests from coverage analysis -- Runs tests sequentially (single thread) -- Continues testing even if failures occur -- Enables debug logging and full backtraces for better error diagnosis - -The coverage report (`lcov.info`) can be used with various code coverage -visualization tools. - -## ๐Ÿ““ More Information +- Failed jobs tracked in database after maximum retries +- Integrated telemetry for failure monitoring (see [Monitoring](#monitoring)) -- Read the architecture present at `./docs/orchestrator_da_sequencer_diagram.png` +For additional architectural details, refer to `./docs/orchestrator_da_sequencer_diagram.png` \ No newline at end of file diff --git a/madara-bootstrapper b/madara-bootstrapper index b0b64750..f717bf17 160000 --- a/madara-bootstrapper +++ b/madara-bootstrapper @@ -1 +1 @@ -Subproject commit b0b647500c2ae3e3b0d99e345fa652989bca4726 +Subproject commit f717bf179581da53d68fee03b50ef78e0628ee20 From dcc161df97f98897cae5a5b1bf25fa5f797a5ddb Mon Sep 17 00:00:00 2001 From: mohiiit Date: Wed, 18 Dec 2024 10:57:58 +0530 Subject: [PATCH 02/17] chore: readme updated --- README.md | 320 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 182 insertions(+), 138 deletions(-) diff --git a/README.md b/README.md index a93890e2..bca7c6c0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Madara Orchestrator ๐ŸŽญ -Madara Orchestrator is a service that runs parallel to Madara, managing critical jobs for block processing, proof generation, data submission, and state transitions. +The Madara orchestrator is designed to be an additional service which runs in +parallel to Madara and handles various critical jobs that ensure proper block +processing, proof generation, data submission and state transitions. > ๐Ÿ“ **Note**: These instructions are verified for Ubuntu systems. While most steps remain similar for macOS, some package names and installation commands may differ. @@ -8,36 +10,68 @@ Madara Orchestrator is a service that runs parallel to Madara, managing critical - [Overview](#overview) - [Architecture](#architecture) -- [Build Requirements](#build-requirements) -- [Building from Source](#building-from-source) -- [Deployment](#deployment) - - [Local Development](#local-development) - - [Production](#production) +- [Technical Requirements](#technical-requirements) +- [Installation & Setup](#installation--setup) + - [System Dependencies](#system-dependencies) + - [Core Dependencies](#core-dependencies) + - [Building from Source](#building-from-source) + - [Setup Mode](#setup-mode) + - [Run Mode](#run-mode) - [Configuration](#configuration) - [Testing](#testing) + - [Local Environment Setup](#local-environment-setup) + - [Running Tests](#running-tests) - [Monitoring](#monitoring) - [Error Handling](#error-handling) -## Overview +## ๐Ÿ“‹ Overview -The Madara Orchestrator coordinates five primary jobs through a centralized queue system: +The Madara Orchestrator coordinates and triggers five primary jobs in sequence, +managing their execution through a centralized queue system, allowing +for multiple orchestrators to run together! -1. **SNOS (Starknet OS) Job**: Processes blocks and generates Program Independent Execution (PIE) -2. **Proving Job**: Manages proof generation using PIE -3. **Data Submission Job**: Handles state updates for availability layers (Currently supports Ethereum EIP-4844) -4. **State Transition Job**: Manages state transitions with settlement layers (Ethereum and Starknet) +1. **SNOS (Starknet OS) Job** ๐Ÿ”„ + - Identifies blocks that need processing. + - Triggers SNOS run on identified blocks. + - Tracks SNOS execution status and PIE (Program Independent Execution) generation -## Architecture +2. **Proving Job** โœ… + - Coordinates proof generation by submitting PIE to proving services + - Tracks proof generation progress and completion + +3. **Data Submission Job** ๐Ÿ“ค + - Manages state update data preparation for availability layers + - If needed, coordinates blob submission to data availability layers + - Currently integrates with Ethereum (EIP-4844 blob transactions) + - Additional DA layer integrations in development (e.g., Celestia) + +4. **State Transition Job** ๐Ÿ”„ + - Coordinates state transitions with settlement layers + - Manages proof and state update submissions + - Handles integration with Ethereum and Starknet settlement layers + +Each job is managed through a queue-based system where the orchestrator: +- Determines when and which blocks need processing +- Triggers the appropriate services +- Monitors job progress +- Manages job dependencies and sequencing +- Handles retries and failure cases + +## ๐Ÿ›๏ธ Architecture ### Job Processing Model -The orchestrator uses a queue-based architecture with three execution phases: -1. Creation: Jobs are spawned based on block availability -2. Processing: Core job logic execution -3. Verification: Result validation and confirmation +The orchestrator implements a queue-based architecture where each job type +follows a three-phase execution model: + +1. **Creation**: Jobs are spawned based on block availability +2. **Processing**: Core job logic execution +3. **Verification**: Result validation and confirmation ### Queue Structure +The system uses dedicated queues for managing different job phases: + - Worker Trigger Queue - SNOS Processing/Verification Queues - Proving Processing/Verification Queues @@ -47,13 +81,13 @@ The orchestrator uses a queue-based architecture with three execution phases: ### Workflow -1. Cron jobs trigger worker tasks -2. Workers determine block-level requirements +1. Cron jobs trigger worker tasks via the worker-trigger queue +2. Workers determine block-level job requirements 3. Jobs are created and added to processing queues 4. Processed jobs move to verification queues -5. Verified jobs are marked complete in the database +5. Verified jobs are marked as complete in the database -## Build Requirements +## ๐Ÿ› ๏ธ Technical Requirements ### System Dependencies > For macOS users, use `brew install` instead of `apt install` for these dependencies. @@ -69,8 +103,16 @@ The orchestrator uses a queue-based architecture with three execution phases: - [Rust](https://www.rust-lang.org/tools/install) - [Madara Node](https://github.com/madara-alliance/madara) - Prover Service (ATLANTIC) +- MongoDB for job management +- AWS services (or Localstack for local development): + - SQS for queues + - S3 for data storage + - SNS for alerts + - EventBridge for scheduling + +## ๐Ÿš€ Installation & Setup -## Building from Source +### Building from Source 1. **Install System Dependencies** ```bash @@ -106,18 +148,7 @@ The orchestrator uses a queue-based architecture with three execution phases: cargo build --release ``` -## Deployment - -### Local Development - -#### Additional Requirements -1. **Docker** - For running local services -2. **MongoDB** - For job management -3. **Localstack** - For simulating AWS services -4. **Anvil** - For local Ethereum node -5. **Foundry** - For Ethereum development tools - -#### Setup Steps +### Local Development Setup 1. **Install Docker** (Cross-platform) Follow the official installation guides: @@ -142,141 +173,154 @@ The orchestrator uses a queue-based architecture with three execution phases: anvil --block-time 1 ``` -4. **Initialize Local Infrastructure** +4. **Setup Mock Proving Service** ```bash - cargo run --release --bin orchestrator setup --aws --aws-s3 --aws-sqs --aws-sns --aws-event-bridge + # Create a simple HTTP server that always returns 200 + # Example using Python + python3 -m http.server 8888 & + + # Set the mock prover URL in your .env + MADARA_ORCHESTRATOR_ATLANTIC_SERVICE_URL=http://localhost:8888 ``` -5. **Run Orchestrator Locally** +5. **Deploy Mock Verifier Contract** + + You can deploy the mock verifier contract in two ways: + + a. **Using Test Implementation** + - Reference the implementation in `e2e-tests/tests.rs` which contains `AnvilSetup` + - This handles the deployment of both the StarkNet core contract and verifier contract + ```rust + // From e2e-tests/tests.rs + let anvil_setup = AnvilSetup::new(); + let (starknet_core_contract_address, verifier_contract_address) = anvil_setup.deploy_contracts().await; + ``` + + b. **Manual Deployment** + - Alternatively, you can deploy the mock verifier directly using Foundry + - The contract should implement the same interface as used in the tests + - Set the deployed address in your environment: ```bash - RUST_LOG=info cargo run --release --bin orchestrator run \ - --atlantic \ - --aws \ - --settle-on-ethereum \ - --aws-s3 \ - --aws-sqs \ - --aws-sns \ - --da-on-ethereum \ - --mongodb + MADARA_ORCHESTRATOR_VERIFIER_ADDRESS= ``` -### Production +Note: The mock services are intended for development and testing purposes only. In production, you'll need to use actual proving services and verifier contracts. -#### Requirements -- AWS Account with access to: - - S3 - - SQS - - SNS - - EventBridge -- MongoDB instance -- Ethereum RPC endpoint -- ATLANTIC prover service access +### Setup Mode -#### Deployment Steps +Setup mode configures the required AWS services and dependencies. +Use the following command: -1. **Configure AWS Services** - See [Configuration](#configuration) section for required environment variables. - ```bash - cargo run --release --bin orchestrator setup \ - --aws \ - --aws-s3 \ - --aws-sqs \ - --aws-sns \ - --aws-event-bridge - ``` +```bash +cargo run --release --bin orchestrator setup --aws --aws-s3 --aws-sqs --aws-sns --aws-event-bridge +``` -2. **Run Orchestrator** - ```bash - RUST_LOG=info cargo run --release --bin orchestrator run \ - --atlantic \ - --aws \ - --settle-on-ethereum \ - --aws-s3 \ - --aws-sqs \ - --aws-sns \ - --da-on-ethereum \ - --mongodb - ``` +Note: Setup mode is currently in development. A fresh setup is required +if the process fails mid-way. -## Configuration +### Run Mode -Create a `.env` file with appropriate values for your environment: +Run mode executes the orchestrator's job processing workflow. Example command: -### Production Environment -```env -# AWS Configuration -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_REGION= +```bash +RUST_LOG=info cargo run --release --bin orchestrator run \ + --atlantic \ + --aws \ + --settle-on-ethereum \ + --aws-s3 \ + --aws-sqs \ + --aws-sns \ + --da-on-ethereum \ + --mongodb +``` -# Prover Configuration -MADARA_ORCHESTRATOR_ATLANTIC_API_KEY= -MADARA_ORCHESTRATOR_ATLANTIC_SERVICE_URL= +### Command Line Options -# Database Configuration -MADARA_ORCHESTRATOR_MONGODB_CONNECTION_URL= -MADARA_ORCHESTRATOR_DATABASE_NAME=orchestrator +[Previous command line options section remains exactly the same] -# RPC Configuration -MADARA_ORCHESTRATOR_ETHEREUM_SETTLEMENT_RPC_URL= -MADARA_ORCHESTRATOR_RPC_FOR_SNOS= -``` +## โš™๏ธ Configuration -### Local Development -```env -# AWS Configuration (Localstack) -AWS_ACCESS_KEY_ID=test -AWS_SECRET_ACCESS_KEY=test -AWS_REGION=us-east-1 +[Previous configuration section remains exactly the same] -# Database Configuration -MADARA_ORCHESTRATOR_MONGODB_CONNECTION_URL=mongodb://localhost:27017 -MADARA_ORCHESTRATOR_DATABASE_NAME=orchestrator +## ๐Ÿงช Testing -# RPC Configuration -MADARA_ORCHESTRATOR_ETHEREUM_SETTLEMENT_RPC_URL=http://localhost:8545 -MADARA_ORCHESTRATOR_RPC_FOR_SNOS= -``` +### Local Environment Setup -## Testing +Before running tests, ensure you have: -### Local Environment Tests -Requires [local services](#local-development) to be running (MongoDB, Localstack, Anvil) +1. **Required Services Running**: + - MongoDB on port 27017 + - Localstack on port 4566 + - Anvil (local Ethereum node) -1. **E2E Tests** +2. **Environment Configuration**: ```bash - RUST_LOG=info cargo test --features testing test_orchestrator_workflow -- --nocapture + export MADARA_ORCHESTRATOR_ETHEREUM_SETTLEMENT_RPC_URL= + export MADARA_ORCHESTRATOR_RPC_FOR_SNOS= + export AWS_REGION=us-east-1 ``` -2. **Integration and Unit Tests** - ```bash - RUST_LOG=debug RUST_BACKTRACE=1 cargo llvm-cov nextest \ - --release \ - --features testing \ - --lcov \ - --output-path lcov.info \ - --test-threads=1 \ - --workspace \ - --exclude=e2e-tests \ - --no-fail-fast - ``` +### Types of Tests -## Monitoring +1. **E2E Tests** ๐Ÿ”„ + - End-to-end workflow testing + - Tests orchestrator functionality on block 66645 of Starknet + - Uses mocked proving endpoints + +2. **Integration & Unit Tests** ๐Ÿ”Œ + - Tests component interactions + - Verifies individual functionalities + +### Running Tests + +#### Running E2E Tests + +```bash +RUST_LOG=info cargo test --features testing test_orchestrator_workflow -- --nocapture +``` + +#### Running Integration and Unit Tests + +```bash +RUST_LOG=debug RUST_BACKTRACE=1 cargo llvm-cov nextest \ + --release \ + --features testing \ + --lcov \ + --output-path lcov.info \ + --test-threads=1 \ + --workspace \ + --exclude=e2e-tests \ + --no-fail-fast +``` + +This command: +- Generates detailed coverage reports in LCOV format +- Excludes E2E tests from coverage analysis +- Runs tests sequentially (single thread) +- Continues testing even if failures occur +- Enables debug logging and full backtraces for better error diagnosis + +The coverage report (`lcov.info`) can be used with various code coverage +visualization tools. + +## ๐Ÿ” Monitoring + +The orchestrator includes a telemetry system that tracks: -The orchestrator includes [OpenTelemetry](https://opentelemetry.io/) integration for monitoring: - Job execution metrics -- Processing time statistics +- Processing time statistics - RPC performance metrics -Configure monitoring using: -- `--otel-service-name`: OpenTelemetry service name -- `--otel-collector-endpoint`: OpenTelemetry collector endpoint +OpenTelemetry integration is available for detailed monitoring. +It requires a `Otel-collector` url to be able to send metrics/logs/traces. -## Error Handling +## ๐Ÿ› Error Handling -- Failed jobs move to a dedicated failure queue (see [Queue Structure](#queue-structure)) +- Failed jobs are moved to a dedicated failure handling queue - Automatic retry mechanism with configurable intervals -- Failed jobs tracked in database after maximum retries -- Integrated telemetry for failure monitoring (see [Monitoring](#monitoring)) +- Failed jobs are tracked in the database for manual inspection after maximum retries +- Integrated telemetry system for monitoring job failures + +## ๐Ÿ““ More Information -For additional architectural details, refer to `./docs/orchestrator_da_sequencer_diagram.png` \ No newline at end of file +- Read the architecture present at `./docs/orchestrator_da_sequencer_diagram.png` \ No newline at end of file From e927a0785795c32dba3f3b9de24afdb8fb35de33 Mon Sep 17 00:00:00 2001 From: mohiiit Date: Wed, 18 Dec 2024 11:27:35 +0530 Subject: [PATCH 03/17] chore(readme): re-added a few sections that were missed earlier --- CHANGELOG.md | 1 + README.md | 181 +++++++++++++++++++++++++++++++++++------- scripts/init_state.js | 110 ++++++++++++------------- 3 files changed, 208 insertions(+), 84 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b89ef854..f320fb89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## Added +- readme: setup instructions added - tests: http_client tests added - Added Atlantic proving service integration - setup functions added for cloud and db diff --git a/README.md b/README.md index bca7c6c0..b02be3cc 100644 --- a/README.md +++ b/README.md @@ -8,21 +8,31 @@ processing, proof generation, data submission and state transitions. ## Table of Contents -- [Overview](#overview) -- [Architecture](#architecture) -- [Technical Requirements](#technical-requirements) -- [Installation & Setup](#installation--setup) +- [Overview](#-overview) +- [Architecture](#๏ธ-architecture) + - [Job Processing Model](#job-processing-model) + - [Queue Structure](#queue-structure) + - [Workflow](#workflow) +- [Technical Requirements](#๏ธ-technical-requirements) - [System Dependencies](#system-dependencies) - [Core Dependencies](#core-dependencies) +- [Installation & Setup](#-installation--setup) - [Building from Source](#building-from-source) + - [Local Development Setup](#local-development-setup) - [Setup Mode](#setup-mode) - [Run Mode](#run-mode) -- [Configuration](#configuration) -- [Testing](#testing) + - [Command Line Options](#command-line-options) +- [Configuration](#๏ธ-configuration) + - [AWS Configuration](#aws-configuration) + - [Prover Configuration](#prover-configuration) + - [Database Configuration](#database-configuration) +- [Testing](#-testing) - [Local Environment Setup](#local-environment-setup) + - [Types of Tests](#types-of-tests) - [Running Tests](#running-tests) -- [Monitoring](#monitoring) -- [Error Handling](#error-handling) +- [Monitoring](#-monitoring) +- [Error Handling](#-error-handling) +- [Additional Resources](#additional-resources) ## ๐Ÿ“‹ Overview @@ -31,15 +41,18 @@ managing their execution through a centralized queue system, allowing for multiple orchestrators to run together! 1. **SNOS (Starknet OS) Job** ๐Ÿ”„ + - Identifies blocks that need processing. - Triggers SNOS run on identified blocks. - Tracks SNOS execution status and PIE (Program Independent Execution) generation 2. **Proving Job** โœ… + - Coordinates proof generation by submitting PIE to proving services - Tracks proof generation progress and completion 3. **Data Submission Job** ๐Ÿ“ค + - Manages state update data preparation for availability layers - If needed, coordinates blob submission to data availability layers - Currently integrates with Ethereum (EIP-4844 blob transactions) @@ -51,6 +64,7 @@ for multiple orchestrators to run together! - Handles integration with Ethereum and Starknet settlement layers Each job is managed through a queue-based system where the orchestrator: + - Determines when and which blocks need processing - Triggers the appropriate services - Monitors job progress @@ -90,6 +104,7 @@ The system uses dedicated queues for managing different job phases: ## ๐Ÿ› ๏ธ Technical Requirements ### System Dependencies + > For macOS users, use `brew install` instead of `apt install` for these dependencies. - Build essentials (`build-essential`) @@ -99,9 +114,12 @@ The system uses dedicated queues for managing different job phases: - GMP library (`libgmp-dev`) ### Core Dependencies + - [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) - [Rust](https://www.rust-lang.org/tools/install) - [Madara Node](https://github.com/madara-alliance/madara) + - Required for block processing + - Follow setup instructions at [Madara Documentation](https://github.com/madara-alliance/madara) - Prover Service (ATLANTIC) - MongoDB for job management - AWS services (or Localstack for local development): @@ -110,11 +128,20 @@ The system uses dedicated queues for managing different job phases: - SNS for alerts - EventBridge for scheduling +> ๐Ÿšจ **Important Note**: Currently, Madara doesn't support the `get_storage_proof` endpoint. Therefore, you need to run Pathfinder alongside Madara: +> +> - Madara will run in sequencer mode +> - Pathfinder will sync with Madara +> - The orchestrator will use Pathfinder's RPC URL for SNOS and state update fetching +> +> This setup ensures proper functionality until the `get_storage_proof` endpoint is implemented in Madara. + ## ๐Ÿš€ Installation & Setup ### Building from Source 1. **Install System Dependencies** + ```bash # Ubuntu/Debian sudo apt-get update @@ -126,12 +153,14 @@ The system uses dedicated queues for managing different job phases: ``` 2. **Install Rust** (Cross-platform) + ```bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh source ~/.bashrc # Or source ~/.zshrc for macOS ``` 3. **Clone Repository** + ```bash git clone https://github.com/madara-alliance/madara-orchestrator.git cd madara-orchestrator @@ -139,6 +168,7 @@ The system uses dedicated queues for managing different job phases: ``` 4. **Build SNOS** + ```bash make snos ``` @@ -152,16 +182,19 @@ The system uses dedicated queues for managing different job phases: 1. **Install Docker** (Cross-platform) Follow the official installation guides: + - [Ubuntu Installation Guide](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository) - [macOS Installation Guide](https://docs.docker.com/desktop/install/mac-install/) 2. **Install Foundry** (Cross-platform) + ```bash curl -L https://foundry.paradigm.xyz | bash foundryup ``` 3. **Start Local Services** + ```bash # Start MongoDB docker run -d -p 27017:27017 mongo @@ -174,6 +207,7 @@ The system uses dedicated queues for managing different job phases: ``` 4. **Setup Mock Proving Service** + ```bash # Create a simple HTTP server that always returns 200 # Example using Python @@ -184,12 +218,14 @@ The system uses dedicated queues for managing different job phases: ``` 5. **Deploy Mock Verifier Contract** - + You can deploy the mock verifier contract in two ways: a. **Using Test Implementation** + - Reference the implementation in `e2e-tests/tests.rs` which contains `AnvilSetup` - This handles the deployment of both the StarkNet core contract and verifier contract + ```rust // From e2e-tests/tests.rs let anvil_setup = AnvilSetup::new(); @@ -197,9 +233,11 @@ The system uses dedicated queues for managing different job phases: ``` b. **Manual Deployment** + - Alternatively, you can deploy the mock verifier directly using Foundry - The contract should implement the same interface as used in the tests - Set the deployed address in your environment: + ```bash MADARA_ORCHESTRATOR_VERIFIER_ADDRESS= ``` @@ -236,19 +274,111 @@ RUST_LOG=info cargo run --release --bin orchestrator run \ ### Command Line Options -[Previous command line options section remains exactly the same] +1. **Prover Services** (choose one): + + - `--atlantic`: Use Atlantic prover + - `--sharp`: Use SHARP prover + +2. **Settlement Layer** (choose one): + + - `--settle-on-ethereum`: Use Ethereum + - `--settle-on-starknet`: Use Starknet + +3. **Data Availability**: + + - `--da-on-ethereum`: Use Ethereum + +4. **Infrastructure**: + + - `--aws`: Use AWS services (or Localstack) + +5. **Data Storage**: + + - `--aws-s3`: Store state updates and program outputs + +6. **Database**: + + - `--mongodb`: Store job information + +7. **Queue System**: + + - `--aws-sqs`: Message queue service + +8. **Alerting**: + + - `--aws-sns`: Notification service + +9. **Scheduling**: + + - `--aws-event-bridge`: Cron job scheduling + +10. **Monitoring**: + - `--otel-service-name`: OpenTelemetry service name + - `--otel-collector-endpoint`: OpenTelemetry collector endpoint ## โš™๏ธ Configuration -[Previous configuration section remains exactly the same] +The orchestrator uses environment variables for configuration. +Create a `.env` file with the following sections: + +### AWS Configuration + +```env +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_REGION= +``` + +Note: These configurations are also picked up from your AWS credentials file (~/.aws/credentials) or environment variables if not specified in the .env file. + +### Prover Configuration + +```env +# SHARP Configuration +MADARA_ORCHESTRATOR_SHARP_CUSTOMER_ID= +MADARA_ORCHESTRATOR_SHARP_URL= +# or +# ATLANTIC Configuration +MADARA_ORCHESTRATOR_ATLANTIC_API_KEY= +MADARA_ORCHESTRATOR_ATLANTIC_SERVICE_URL= +``` + +### Database Configuration + +```env +MADARA_ORCHESTRATOR_MONGODB_CONNECTION_URL=mongodb://localhost:27017 +MADARA_ORCHESTRATOR_DATABASE_NAME=orchestrator +``` + +For a complete list of configuration options, refer to the `.env.example` file +in the repository. + +## ๐Ÿ” Monitoring + +The orchestrator includes a telemetry system that tracks: + +- Job execution metrics +- Processing time statistics +- RPC performance metrics + +OpenTelemetry integration is available for detailed monitoring. +It requires a `Otel-collector` url to be able to send metrics/logs/traces. + +## ๐Ÿ› Error Handling + +- Failed jobs are moved to a dedicated failure handling queue +- Automatic retry mechanism with configurable intervals +- Failed jobs are tracked in the database for manual inspection after maximum retries +- Integrated telemetry system for monitoring job failures -## ๐Ÿงช Testing +## ๐Ÿ““ Testing ### Local Environment Setup Before running tests, ensure you have: 1. **Required Services Running**: + - MongoDB on port 27017 - Localstack on port 4566 - Anvil (local Ethereum node) @@ -263,6 +393,7 @@ Before running tests, ensure you have: ### Types of Tests 1. **E2E Tests** ๐Ÿ”„ + - End-to-end workflow testing - Tests orchestrator functionality on block 66645 of Starknet - Uses mocked proving endpoints @@ -294,6 +425,7 @@ RUST_LOG=debug RUST_BACKTRACE=1 cargo llvm-cov nextest \ ``` This command: + - Generates detailed coverage reports in LCOV format - Excludes E2E tests from coverage analysis - Runs tests sequentially (single thread) @@ -303,24 +435,13 @@ This command: The coverage report (`lcov.info`) can be used with various code coverage visualization tools. -## ๐Ÿ” Monitoring - -The orchestrator includes a telemetry system that tracks: - -- Job execution metrics -- Processing time statistics -- RPC performance metrics - -OpenTelemetry integration is available for detailed monitoring. -It requires a `Otel-collector` url to be able to send metrics/logs/traces. +## ๐Ÿ““ More Information -## ๐Ÿ› Error Handling +- Read the architecture present at `./docs/orchestrator_da_sequencer_diagram.png` -- Failed jobs are moved to a dedicated failure handling queue -- Automatic retry mechanism with configurable intervals -- Failed jobs are tracked in the database for manual inspection after maximum retries -- Integrated telemetry system for monitoring job failures - -## ๐Ÿ““ More Information +## Additional Resources -- Read the architecture present at `./docs/orchestrator_da_sequencer_diagram.png` \ No newline at end of file +- Architecture Diagram: See `./docs/orchestrator_da_sequencer_diagram.png` +- [Madara Documentation](https://github.com/madara-alliance/madara) +- [LocalStack Documentation](https://docs.localstack.cloud/) +- [Foundry Documentation](https://book.getfoundry.sh/) diff --git a/scripts/init_state.js b/scripts/init_state.js index 0c041972..474e39ab 100644 --- a/scripts/init_state.js +++ b/scripts/init_state.js @@ -18,7 +18,7 @@ const MADARA_ORCHESTRATOR_ETHEREUM_PRIVATE_KEY = const eth_provider = new ethers.JsonRpcProvider("http://localhost:8545"); const wallet = new ethers.Wallet( MADARA_ORCHESTRATOR_ETHEREUM_PRIVATE_KEY, - eth_provider, + eth_provider ); const starknet_provider = new starknet.RpcProvider({ @@ -56,7 +56,7 @@ async function getAppChainBalance(address) { const ethContract = new starknet.Contract( abi, ETHEREUM_APP_CHAIN_ADDRESS, - starknet_provider, + starknet_provider ); // Interaction with the contract with call @@ -69,16 +69,16 @@ async function bridgeToChain(bridge_address, starnet_expected_account_address) { const contract = new ethers.Contract( bridge_address, ["function deposit(uint256, uint256)"], - wallet, + wallet ); const initial_app_chain_balance = await getAppChainBalance( - starnet_expected_account_address, + starnet_expected_account_address ); const tx = await contract.deposit( ethers.parseEther("1"), starnet_expected_account_address, - { value: ethers.parseEther("1.01") }, + { value: ethers.parseEther("1.01") } ); tx.wait(); @@ -88,13 +88,13 @@ async function bridgeToChain(bridge_address, starnet_expected_account_address) { let counter = 10; while (counter--) { const final_app_chain_balance = await getAppChainBalance( - starnet_expected_account_address, + starnet_expected_account_address ); if (final_app_chain_balance > initial_app_chain_balance) { console.log( "๐Ÿ’ฐ App chain balance:", (final_app_chain_balance / 10n ** 18n).toString(), - "ETH", + "ETH" ); return; } @@ -121,7 +121,7 @@ function calculatePrefactualAccountAddress() { starkKeyPub, OZ_ACCOUNT_CLASS_HASH, OZaccountConstructorCallData, - 0, + 0 ); return { address: OZcontractAddress, @@ -172,14 +172,14 @@ async function validateBlockPassesSnosChecks(block_number) { async function deployStarknetAccount( starknet_private_key, starnet_expected_account_address, - starknet_account_public_key, + starknet_account_public_key ) { console.log("โณ Deploying Starknet account..."); const account = new starknet.Account( starknet_provider, starnet_expected_account_address, starknet_private_key, - "1", + "1" ); const { transaction_hash, contract_address } = await account.deployAccount({ classHash: OZ_ACCOUNT_CLASS_HASH, @@ -211,7 +211,7 @@ async function waitForTransactionSuccess(hash) { // can run SNOS async function overrideStateOnCoreContract( block_number, - core_contract_address, + core_contract_address ) { let state_update = await starknet_provider.getStateUpdate(block_number); let abi = [ @@ -244,7 +244,7 @@ async function overrideStateOnCoreContract( const tx = await contract.updateStateOverride( state_update.new_root, block_number, - state_update.block_hash, + state_update.block_hash ); const receipt = await tx.wait(); if (!receipt.status) { @@ -296,13 +296,13 @@ async function setupMongoDb(block_number) { async function transfer( starknet_account_private_key, - starnet_expected_account_address, + starnet_expected_account_address ) { const account = new starknet.Account( starknet_provider, starnet_expected_account_address, starknet_account_private_key, - "1", + "1" ); const abi = [ { @@ -346,7 +346,7 @@ async function transfer( const contract = new starknet.Contract( abi, ETHEREUM_APP_CHAIN_ADDRESS, - starknet_provider, + starknet_provider ); let calldata = contract.populate("transfer", { recipient: "0x1234", @@ -361,7 +361,7 @@ async function transfer( txn_hash.transaction_hash, { retryInterval: 100, - }, + } ); if (!receipt.isSuccess()) { console.log("โŒ Failed to do a transfer on Starknet account"); @@ -371,7 +371,7 @@ async function transfer( // if txn is pending, block_number won't be available while (!receipt.block_number) { receipt = await starknet_provider.getTransactionReceipt( - txn_hash.transaction_hash, + txn_hash.transaction_hash ); await new Promise((resolve) => setTimeout(resolve, 200)); } @@ -387,19 +387,19 @@ async function transfer( async function upgradeETHToken( l2_eth_token_address, starknet_account_private_key, - starnet_expected_account_address, + starnet_expected_account_address ) { const account = new starknet.Account( starknet_provider, starnet_expected_account_address, starknet_account_private_key, - "1", + "1" ); // declare and deploy the new ERC20 contract // https://sepolia.starkscan.co/tx/0x04b5fa2a2e738a8b7a6c7b15194fbcf4409411743ebbe48cc5b83e5fe0edffdf console.log( - "โ„น๏ธ Sending transaction to declare and deploy new ERC20 contract for ETH...", + "โ„น๏ธ Sending transaction to declare and deploy new ERC20 contract for ETH..." ); let new_erc20_declare_deploy = await account.declareAndDeploy({ contract: require("./artifacts/starknet/new_eth_token.sierra.json"), @@ -433,12 +433,12 @@ async function upgradeETHToken( // add_implementation to bridge contarct before we upgrade // https://sepolia.starkscan.co/tx/0x064ab87819a2f8ebf91176eeb901f842c23ef6c97c107fe31b14defa352ba045 console.log( - "โ„น๏ธ Sending transaction to add implementation to bridge contract...", + "โ„น๏ธ Sending transaction to add implementation to bridge contract..." ); let eth_bridge = new starknet.Contract( require("./artifacts/starknet/bridge_proxy_legacy.json").abi, l2_eth_token_address, - account, + account ); let add_implementation_calldata = eth_bridge.populate("add_implementation", [ new_erc20_declare_deploy.deploy.address, @@ -447,7 +447,7 @@ async function upgradeETHToken( 0, // final ]); let add_implementation_txn_hash = await eth_bridge.add_implementation( - add_implementation_calldata.calldata, + add_implementation_calldata.calldata ); await waitForTransactionSuccess(add_implementation_txn_hash.transaction_hash); console.log("โœ… Transaction successful."); @@ -457,7 +457,7 @@ async function upgradeETHToken( console.log("โ„น๏ธ Sending transaction to upgrade ETH token contract..."); let upgrade_txn_hash = await eth_bridge.upgrade_to( // the calldata is the same - add_implementation_calldata.calldata, + add_implementation_calldata.calldata ); await waitForTransactionSuccess(upgrade_txn_hash.transaction_hash); console.log("โœ… Transaction successful."); @@ -465,7 +465,7 @@ async function upgradeETHToken( // now add a new implementation to the bridge contract for the erc20 class hash // https://sepolia.starkscan.co/tx/0x051cc24816ec349c601bbd4e9afc8e0a8c7a93061aba372045bbf7e5d35aff7a console.log( - "โ„น๏ธ Sending transaction to add new implementation to bridge contract...", + "โ„น๏ธ Sending transaction to add new implementation to bridge contract..." ); let add_new_implementation_txn_hash = await account.execute([ { @@ -480,13 +480,13 @@ async function upgradeETHToken( }, ]); await waitForTransactionSuccess( - add_new_implementation_txn_hash.transaction_hash, + add_new_implementation_txn_hash.transaction_hash ); console.log("โœ… Transaction successful."); // finally replace the class hash on the ETH contract console.log( - "โ„น๏ธ Sending transaction to replace class hash on the ETH contract...", + "โ„น๏ธ Sending transaction to replace class hash on the ETH contract..." ); let replace_to_txn_hash = await account.execute([ { @@ -512,19 +512,19 @@ async function upgradeETHToken( async function upgradeETHBridge( l2_eth_bridge_address, starknet_account_private_key, - starnet_expected_account_address, + starnet_expected_account_address ) { const account = new starknet.Account( starknet_provider, starnet_expected_account_address, starknet_account_private_key, - "1", + "1" ); // declare and deploy the new ETH bridge contract // https://sepolia.starkscan.co/tx/0x05c266b9069c04f68752f5eb9652d7c0cd130c6d152d2267a8480273ec991de6 console.log( - "โ„น๏ธ Sending transaction to declare and deploy new ETH bridge contract for ETH...", + "โ„น๏ธ Sending transaction to declare and deploy new ETH bridge contract for ETH..." ); let new_bridge_declare_deploy = await account.declareAndDeploy({ contract: require("./artifacts/starknet/new_eth_bridge.sierra.json"), @@ -548,12 +548,12 @@ async function upgradeETHBridge( // add_implementation to bridge contarct before we upgrade // https://sepolia.starkscan.co/call/0x0721b02e1f4daa98ed8928966d66f345cb897f382274b22c89d86c00e755106d_1_1 console.log( - "โ„น๏ธ Sending transaction to add implementation to bridge contract...", + "โ„น๏ธ Sending transaction to add implementation to bridge contract..." ); let eth_bridge = new starknet.Contract( require("./artifacts/starknet/bridge_proxy_legacy.json").abi, l2_eth_bridge_address, - account, + account ); let add_implementation_calldata = eth_bridge.populate("add_implementation", [ new_bridge_declare_deploy.deploy.address, @@ -565,7 +565,7 @@ async function upgradeETHBridge( 0, // final ]); let add_implementation_txn_hash = await eth_bridge.add_implementation( - add_implementation_calldata.calldata, + add_implementation_calldata.calldata ); await waitForTransactionSuccess(add_implementation_txn_hash.transaction_hash); console.log("โœ… Transaction successful."); @@ -575,7 +575,7 @@ async function upgradeETHBridge( console.log("โ„น๏ธ Sending transaction to upgrade ETH bridge contract..."); let upgrade_txn_hash = await eth_bridge.upgrade_to( // the calldata is the same - add_implementation_calldata.calldata, + add_implementation_calldata.calldata ); await waitForTransactionSuccess(upgrade_txn_hash.transaction_hash); console.log("โœ… Transaction successful."); @@ -583,7 +583,7 @@ async function upgradeETHBridge( // now add a new implementation to the bridge contract for the bridge class hash // https://sepolia.starkscan.co/tx/0x051cc24816ec349c601bbd4e9afc8e0a8c7a93061aba372045bbf7e5d35aff7a console.log( - "โ„น๏ธ Sending transaction to add new implementation to bridge contract...", + "โ„น๏ธ Sending transaction to add new implementation to bridge contract..." ); let add_new_implementation_txn_hash = await account.execute([ { @@ -598,13 +598,13 @@ async function upgradeETHBridge( }, ]); await waitForTransactionSuccess( - add_new_implementation_txn_hash.transaction_hash, + add_new_implementation_txn_hash.transaction_hash ); console.log("โœ… Transaction successful."); // finally replace the class hash on the ETH contract console.log( - "โ„น๏ธ Sending transaction to replace class hash on the ETH contract...", + "โ„น๏ธ Sending transaction to replace class hash on the ETH contract..." ); let replace_to_txn_hash = await account.execute([ { @@ -623,7 +623,7 @@ async function upgradeL1EthBridge(l1_bridge_address) { const contract = new ethers.ContractFactory( newEthBridge.abi, newEthBridge.bytecode, - wallet, + wallet ); const ethBridgeReceipt = await contract.deploy(); await ethBridgeReceipt.waitForDeployment(); @@ -635,7 +635,7 @@ async function upgradeL1EthBridge(l1_bridge_address) { const eicContract = new ethers.ContractFactory( newEic.abi, newEic.bytecode, - wallet, + wallet ); const eicReceipt = await eicContract.deploy(); await eicReceipt.waitForDeployment(); @@ -693,14 +693,14 @@ async function upgradeL1EthBridge(l1_bridge_address) { stateMutability: "payable", }, ], - wallet, + wallet ); // add new implementation to the bridge let addImplementationTxn = await bridge.addImplementation( ethBridgeAddress, chainHexesToBytes([eicAddress, "0x0", "0x0"]), - false, + false ); await addImplementationTxn.wait(); console.log("โœ… New implementation added to the bridge"); @@ -709,7 +709,7 @@ async function upgradeL1EthBridge(l1_bridge_address) { let upgradeToTxn = await bridge.upgradeTo( ethBridgeAddress, chainHexesToBytes([eicAddress, "0x0", "0x0"]), - false, + false ); await upgradeToTxn.wait(); console.log("โœ… Bridge upgraded to the new implementation"); @@ -763,8 +763,9 @@ async function main() { const bootstrapper_private_key = "0xabcd" || process.argv[7]; // add funds to boostrapper account - let bootstrapper_address_balance = - await getAppChainBalance(bootstrapper_address); + let bootstrapper_address_balance = await getAppChainBalance( + bootstrapper_address + ); if (bootstrapper_address_balance < 10n ** 17n) { await bridgeToChain(l1_bridge_address, bootstrapper_address); } else { @@ -772,21 +773,22 @@ async function main() { } // upgrade ETH token to Cairo 1 as SNOS breaks otherwise - const eth_token_class = - await starknet_provider.getClassAt(l2_eth_token_address); + const eth_token_class = await starknet_provider.getClassAt( + l2_eth_token_address + ); if (eth_token_class.sierra_program) { console.log("โ„น๏ธ Eth token is already upgraded, proceeding"); } else { await upgradeETHToken( l2_eth_token_address, bootstrapper_private_key, - bootstrapper_address, + bootstrapper_address ); } // upgrade ETH bridge to Cairo 1 as well const l2_eth_bridge_class = await starknet_provider.getClassAt( - l2_eth_bridge_address, + l2_eth_bridge_address ); if (l2_eth_bridge_class.sierra_program) { console.log("โ„น๏ธ Eth bridge is already upgraded, proceeding"); @@ -794,7 +796,7 @@ async function main() { await upgradeETHBridge( l2_eth_bridge_address, bootstrapper_private_key, - bootstrapper_address, + bootstrapper_address ); } @@ -802,14 +804,14 @@ async function main() { const l1BridgeContract = new ethers.Contract( l1_bridge_address, ["function identify() external view returns (string)"], - eth_provider, + eth_provider ); const identify = await l1BridgeContract.identify(); console.log("โ„น๏ธ L1 ETH bridge identify:", identify); if ( identify.includes( // StarkWare_StarknetEthBridge_2023_1 - "StarkWare_StarknetEthBridge_2023_1", + "StarkWare_StarknetEthBridge_2023_1" ) ) { await upgradeL1EthBridge(l1_bridge_address); @@ -824,7 +826,7 @@ async function main() { } = calculatePrefactualAccountAddress(); console.log( "๐Ÿฆ Starknet expected account address:", - starnet_expected_account_address, + starnet_expected_account_address ); await bridgeToChain(l1_bridge_address, starnet_expected_account_address); @@ -832,7 +834,7 @@ async function main() { let block_number = await deployStarknetAccount( starknet_account_private_key, starnet_expected_account_address, - starknet_account_public_key, + starknet_account_public_key ); // SNOS doesn't seem to be able to run on deploy account block @@ -840,7 +842,7 @@ async function main() { block_number = await transfer( starknet_account_private_key, - starnet_expected_account_address, + starnet_expected_account_address ); await validateBlockPassesSnosChecks(block_number); From d4ea5107e37ca8bf50015412597775bfabe09625 Mon Sep 17 00:00:00 2001 From: mohiiit Date: Wed, 18 Dec 2024 11:31:00 +0530 Subject: [PATCH 04/17] chore(readme): linting --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b02be3cc..a3932f7b 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,7 @@ The system uses dedicated queues for managing different job phases: ``` 5. **Build Project** + ```bash cargo build --release ``` @@ -384,6 +385,7 @@ Before running tests, ensure you have: - Anvil (local Ethereum node) 2. **Environment Configuration**: + ```bash export MADARA_ORCHESTRATOR_ETHEREUM_SETTLEMENT_RPC_URL= export MADARA_ORCHESTRATOR_RPC_FOR_SNOS= From 11f98c706806885e66ad86515866fa969eda3ca3 Mon Sep 17 00:00:00 2001 From: mohiiit Date: Wed, 18 Dec 2024 11:38:53 +0530 Subject: [PATCH 05/17] chore: linting and formatting --- .markdownlint.json | 3 +- README.md | 9 ++-- scripts/init_state.js | 112 +++++++++++++++++++++--------------------- 3 files changed, 63 insertions(+), 61 deletions(-) diff --git a/.markdownlint.json b/.markdownlint.json index 68e7410c..500ea857 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -4,6 +4,7 @@ "MD045": false, "MD003": false, "MD013": { - "code_blocks": false + "code_blocks": false, + "line_length": 120 } } diff --git a/README.md b/README.md index a3932f7b..9c3a50b6 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@ The Madara orchestrator is designed to be an additional service which runs in parallel to Madara and handles various critical jobs that ensure proper block processing, proof generation, data submission and state transitions. -> ๐Ÿ“ **Note**: These instructions are verified for Ubuntu systems. While most steps remain similar for macOS, some package names and installation commands may differ. +> ๐Ÿ“ **Note**: These instructions are verified for Ubuntu systems. While most steps remain similar +> for macOS, some package names and installation commands may differ. ## Table of Contents @@ -330,7 +331,8 @@ AWS_SECRET_ACCESS_KEY= AWS_REGION= ``` -Note: These configurations are also picked up from your AWS credentials file (~/.aws/credentials) or environment variables if not specified in the .env file. +Note: These configurations are also picked up from your AWS credentials file (~/.aws/credentials) +or environment variables if not specified in the .env file. ### Prover Configuration @@ -432,7 +434,8 @@ This command: - Excludes E2E tests from coverage analysis - Runs tests sequentially (single thread) - Continues testing even if failures occur -- Enables debug logging and full backtraces for better error diagnosis +- Enables debug logging and full backtraces for better error + diagnosis The coverage report (`lcov.info`) can be used with various code coverage visualization tools. diff --git a/scripts/init_state.js b/scripts/init_state.js index 474e39ab..a5cb3a09 100644 --- a/scripts/init_state.js +++ b/scripts/init_state.js @@ -18,7 +18,7 @@ const MADARA_ORCHESTRATOR_ETHEREUM_PRIVATE_KEY = const eth_provider = new ethers.JsonRpcProvider("http://localhost:8545"); const wallet = new ethers.Wallet( MADARA_ORCHESTRATOR_ETHEREUM_PRIVATE_KEY, - eth_provider + eth_provider, ); const starknet_provider = new starknet.RpcProvider({ @@ -56,7 +56,7 @@ async function getAppChainBalance(address) { const ethContract = new starknet.Contract( abi, ETHEREUM_APP_CHAIN_ADDRESS, - starknet_provider + starknet_provider, ); // Interaction with the contract with call @@ -69,16 +69,16 @@ async function bridgeToChain(bridge_address, starnet_expected_account_address) { const contract = new ethers.Contract( bridge_address, ["function deposit(uint256, uint256)"], - wallet + wallet, ); const initial_app_chain_balance = await getAppChainBalance( - starnet_expected_account_address + starnet_expected_account_address, ); const tx = await contract.deposit( ethers.parseEther("1"), starnet_expected_account_address, - { value: ethers.parseEther("1.01") } + { value: ethers.parseEther("1.01") }, ); tx.wait(); @@ -88,13 +88,13 @@ async function bridgeToChain(bridge_address, starnet_expected_account_address) { let counter = 10; while (counter--) { const final_app_chain_balance = await getAppChainBalance( - starnet_expected_account_address + starnet_expected_account_address, ); if (final_app_chain_balance > initial_app_chain_balance) { console.log( "๐Ÿ’ฐ App chain balance:", (final_app_chain_balance / 10n ** 18n).toString(), - "ETH" + "ETH", ); return; } @@ -121,7 +121,7 @@ function calculatePrefactualAccountAddress() { starkKeyPub, OZ_ACCOUNT_CLASS_HASH, OZaccountConstructorCallData, - 0 + 0, ); return { address: OZcontractAddress, @@ -172,14 +172,14 @@ async function validateBlockPassesSnosChecks(block_number) { async function deployStarknetAccount( starknet_private_key, starnet_expected_account_address, - starknet_account_public_key + starknet_account_public_key, ) { console.log("โณ Deploying Starknet account..."); const account = new starknet.Account( starknet_provider, starnet_expected_account_address, starknet_private_key, - "1" + "1", ); const { transaction_hash, contract_address } = await account.deployAccount({ classHash: OZ_ACCOUNT_CLASS_HASH, @@ -211,7 +211,7 @@ async function waitForTransactionSuccess(hash) { // can run SNOS async function overrideStateOnCoreContract( block_number, - core_contract_address + core_contract_address, ) { let state_update = await starknet_provider.getStateUpdate(block_number); let abi = [ @@ -244,7 +244,7 @@ async function overrideStateOnCoreContract( const tx = await contract.updateStateOverride( state_update.new_root, block_number, - state_update.block_hash + state_update.block_hash, ); const receipt = await tx.wait(); if (!receipt.status) { @@ -296,13 +296,13 @@ async function setupMongoDb(block_number) { async function transfer( starknet_account_private_key, - starnet_expected_account_address + starnet_expected_account_address, ) { const account = new starknet.Account( starknet_provider, starnet_expected_account_address, starknet_account_private_key, - "1" + "1", ); const abi = [ { @@ -346,7 +346,7 @@ async function transfer( const contract = new starknet.Contract( abi, ETHEREUM_APP_CHAIN_ADDRESS, - starknet_provider + starknet_provider, ); let calldata = contract.populate("transfer", { recipient: "0x1234", @@ -361,7 +361,7 @@ async function transfer( txn_hash.transaction_hash, { retryInterval: 100, - } + }, ); if (!receipt.isSuccess()) { console.log("โŒ Failed to do a transfer on Starknet account"); @@ -371,7 +371,7 @@ async function transfer( // if txn is pending, block_number won't be available while (!receipt.block_number) { receipt = await starknet_provider.getTransactionReceipt( - txn_hash.transaction_hash + txn_hash.transaction_hash, ); await new Promise((resolve) => setTimeout(resolve, 200)); } @@ -387,19 +387,19 @@ async function transfer( async function upgradeETHToken( l2_eth_token_address, starknet_account_private_key, - starnet_expected_account_address + starnet_expected_account_address, ) { const account = new starknet.Account( starknet_provider, starnet_expected_account_address, starknet_account_private_key, - "1" + "1", ); // declare and deploy the new ERC20 contract // https://sepolia.starkscan.co/tx/0x04b5fa2a2e738a8b7a6c7b15194fbcf4409411743ebbe48cc5b83e5fe0edffdf console.log( - "โ„น๏ธ Sending transaction to declare and deploy new ERC20 contract for ETH..." + "โ„น๏ธ Sending transaction to declare and deploy new ERC20 contract for ETH...", ); let new_erc20_declare_deploy = await account.declareAndDeploy({ contract: require("./artifacts/starknet/new_eth_token.sierra.json"), @@ -433,12 +433,12 @@ async function upgradeETHToken( // add_implementation to bridge contarct before we upgrade // https://sepolia.starkscan.co/tx/0x064ab87819a2f8ebf91176eeb901f842c23ef6c97c107fe31b14defa352ba045 console.log( - "โ„น๏ธ Sending transaction to add implementation to bridge contract..." + "โ„น๏ธ Sending transaction to add implementation to bridge contract...", ); let eth_bridge = new starknet.Contract( require("./artifacts/starknet/bridge_proxy_legacy.json").abi, l2_eth_token_address, - account + account, ); let add_implementation_calldata = eth_bridge.populate("add_implementation", [ new_erc20_declare_deploy.deploy.address, @@ -447,7 +447,7 @@ async function upgradeETHToken( 0, // final ]); let add_implementation_txn_hash = await eth_bridge.add_implementation( - add_implementation_calldata.calldata + add_implementation_calldata.calldata, ); await waitForTransactionSuccess(add_implementation_txn_hash.transaction_hash); console.log("โœ… Transaction successful."); @@ -457,7 +457,7 @@ async function upgradeETHToken( console.log("โ„น๏ธ Sending transaction to upgrade ETH token contract..."); let upgrade_txn_hash = await eth_bridge.upgrade_to( // the calldata is the same - add_implementation_calldata.calldata + add_implementation_calldata.calldata, ); await waitForTransactionSuccess(upgrade_txn_hash.transaction_hash); console.log("โœ… Transaction successful."); @@ -465,7 +465,7 @@ async function upgradeETHToken( // now add a new implementation to the bridge contract for the erc20 class hash // https://sepolia.starkscan.co/tx/0x051cc24816ec349c601bbd4e9afc8e0a8c7a93061aba372045bbf7e5d35aff7a console.log( - "โ„น๏ธ Sending transaction to add new implementation to bridge contract..." + "โ„น๏ธ Sending transaction to add new implementation to bridge contract...", ); let add_new_implementation_txn_hash = await account.execute([ { @@ -480,13 +480,13 @@ async function upgradeETHToken( }, ]); await waitForTransactionSuccess( - add_new_implementation_txn_hash.transaction_hash + add_new_implementation_txn_hash.transaction_hash, ); console.log("โœ… Transaction successful."); // finally replace the class hash on the ETH contract console.log( - "โ„น๏ธ Sending transaction to replace class hash on the ETH contract..." + "โ„น๏ธ Sending transaction to replace class hash on the ETH contract...", ); let replace_to_txn_hash = await account.execute([ { @@ -512,19 +512,19 @@ async function upgradeETHToken( async function upgradeETHBridge( l2_eth_bridge_address, starknet_account_private_key, - starnet_expected_account_address + starnet_expected_account_address, ) { const account = new starknet.Account( starknet_provider, starnet_expected_account_address, starknet_account_private_key, - "1" + "1", ); // declare and deploy the new ETH bridge contract // https://sepolia.starkscan.co/tx/0x05c266b9069c04f68752f5eb9652d7c0cd130c6d152d2267a8480273ec991de6 console.log( - "โ„น๏ธ Sending transaction to declare and deploy new ETH bridge contract for ETH..." + "โ„น๏ธ Sending transaction to declare and deploy new ETH bridge contract for ETH...", ); let new_bridge_declare_deploy = await account.declareAndDeploy({ contract: require("./artifacts/starknet/new_eth_bridge.sierra.json"), @@ -548,12 +548,12 @@ async function upgradeETHBridge( // add_implementation to bridge contarct before we upgrade // https://sepolia.starkscan.co/call/0x0721b02e1f4daa98ed8928966d66f345cb897f382274b22c89d86c00e755106d_1_1 console.log( - "โ„น๏ธ Sending transaction to add implementation to bridge contract..." + "โ„น๏ธ Sending transaction to add implementation to bridge contract...", ); let eth_bridge = new starknet.Contract( require("./artifacts/starknet/bridge_proxy_legacy.json").abi, l2_eth_bridge_address, - account + account, ); let add_implementation_calldata = eth_bridge.populate("add_implementation", [ new_bridge_declare_deploy.deploy.address, @@ -565,7 +565,7 @@ async function upgradeETHBridge( 0, // final ]); let add_implementation_txn_hash = await eth_bridge.add_implementation( - add_implementation_calldata.calldata + add_implementation_calldata.calldata, ); await waitForTransactionSuccess(add_implementation_txn_hash.transaction_hash); console.log("โœ… Transaction successful."); @@ -575,7 +575,7 @@ async function upgradeETHBridge( console.log("โ„น๏ธ Sending transaction to upgrade ETH bridge contract..."); let upgrade_txn_hash = await eth_bridge.upgrade_to( // the calldata is the same - add_implementation_calldata.calldata + add_implementation_calldata.calldata, ); await waitForTransactionSuccess(upgrade_txn_hash.transaction_hash); console.log("โœ… Transaction successful."); @@ -583,7 +583,7 @@ async function upgradeETHBridge( // now add a new implementation to the bridge contract for the bridge class hash // https://sepolia.starkscan.co/tx/0x051cc24816ec349c601bbd4e9afc8e0a8c7a93061aba372045bbf7e5d35aff7a console.log( - "โ„น๏ธ Sending transaction to add new implementation to bridge contract..." + "โ„น๏ธ Sending transaction to add new implementation to bridge contract...", ); let add_new_implementation_txn_hash = await account.execute([ { @@ -598,13 +598,13 @@ async function upgradeETHBridge( }, ]); await waitForTransactionSuccess( - add_new_implementation_txn_hash.transaction_hash + add_new_implementation_txn_hash.transaction_hash, ); console.log("โœ… Transaction successful."); // finally replace the class hash on the ETH contract console.log( - "โ„น๏ธ Sending transaction to replace class hash on the ETH contract..." + "โ„น๏ธ Sending transaction to replace class hash on the ETH contract...", ); let replace_to_txn_hash = await account.execute([ { @@ -623,7 +623,7 @@ async function upgradeL1EthBridge(l1_bridge_address) { const contract = new ethers.ContractFactory( newEthBridge.abi, newEthBridge.bytecode, - wallet + wallet, ); const ethBridgeReceipt = await contract.deploy(); await ethBridgeReceipt.waitForDeployment(); @@ -635,7 +635,7 @@ async function upgradeL1EthBridge(l1_bridge_address) { const eicContract = new ethers.ContractFactory( newEic.abi, newEic.bytecode, - wallet + wallet, ); const eicReceipt = await eicContract.deploy(); await eicReceipt.waitForDeployment(); @@ -693,14 +693,14 @@ async function upgradeL1EthBridge(l1_bridge_address) { stateMutability: "payable", }, ], - wallet + wallet, ); // add new implementation to the bridge let addImplementationTxn = await bridge.addImplementation( ethBridgeAddress, chainHexesToBytes([eicAddress, "0x0", "0x0"]), - false + false, ); await addImplementationTxn.wait(); console.log("โœ… New implementation added to the bridge"); @@ -709,7 +709,7 @@ async function upgradeL1EthBridge(l1_bridge_address) { let upgradeToTxn = await bridge.upgradeTo( ethBridgeAddress, chainHexesToBytes([eicAddress, "0x0", "0x0"]), - false + false, ); await upgradeToTxn.wait(); console.log("โœ… Bridge upgraded to the new implementation"); @@ -763,9 +763,8 @@ async function main() { const bootstrapper_private_key = "0xabcd" || process.argv[7]; // add funds to boostrapper account - let bootstrapper_address_balance = await getAppChainBalance( - bootstrapper_address - ); + let bootstrapper_address_balance = + await getAppChainBalance(bootstrapper_address); if (bootstrapper_address_balance < 10n ** 17n) { await bridgeToChain(l1_bridge_address, bootstrapper_address); } else { @@ -773,22 +772,21 @@ async function main() { } // upgrade ETH token to Cairo 1 as SNOS breaks otherwise - const eth_token_class = await starknet_provider.getClassAt( - l2_eth_token_address - ); + const eth_token_class = + await starknet_provider.getClassAt(l2_eth_token_address); if (eth_token_class.sierra_program) { console.log("โ„น๏ธ Eth token is already upgraded, proceeding"); } else { await upgradeETHToken( l2_eth_token_address, bootstrapper_private_key, - bootstrapper_address + bootstrapper_address, ); } // upgrade ETH bridge to Cairo 1 as well const l2_eth_bridge_class = await starknet_provider.getClassAt( - l2_eth_bridge_address + l2_eth_bridge_address, ); if (l2_eth_bridge_class.sierra_program) { console.log("โ„น๏ธ Eth bridge is already upgraded, proceeding"); @@ -796,7 +794,7 @@ async function main() { await upgradeETHBridge( l2_eth_bridge_address, bootstrapper_private_key, - bootstrapper_address + bootstrapper_address, ); } @@ -804,14 +802,14 @@ async function main() { const l1BridgeContract = new ethers.Contract( l1_bridge_address, ["function identify() external view returns (string)"], - eth_provider + eth_provider, ); const identify = await l1BridgeContract.identify(); console.log("โ„น๏ธ L1 ETH bridge identify:", identify); if ( identify.includes( // StarkWare_StarknetEthBridge_2023_1 - "StarkWare_StarknetEthBridge_2023_1" + "StarkWare_StarknetEthBridge_2023_1", ) ) { await upgradeL1EthBridge(l1_bridge_address); @@ -826,7 +824,7 @@ async function main() { } = calculatePrefactualAccountAddress(); console.log( "๐Ÿฆ Starknet expected account address:", - starnet_expected_account_address + starnet_expected_account_address, ); await bridgeToChain(l1_bridge_address, starnet_expected_account_address); @@ -834,7 +832,7 @@ async function main() { let block_number = await deployStarknetAccount( starknet_account_private_key, starnet_expected_account_address, - starknet_account_public_key + starknet_account_public_key, ); // SNOS doesn't seem to be able to run on deploy account block @@ -842,7 +840,7 @@ async function main() { block_number = await transfer( starknet_account_private_key, - starnet_expected_account_address + starnet_expected_account_address, ); await validateBlockPassesSnosChecks(block_number); @@ -854,4 +852,4 @@ async function main() { await setupMongoDb(block_number - 1); } -main(); +main(); \ No newline at end of file From 4ebf3a33b6891b885a551b620c0ddd604a7dad06 Mon Sep 17 00:00:00 2001 From: mohiiit Date: Wed, 18 Dec 2024 11:41:25 +0530 Subject: [PATCH 06/17] chore: linting and formatting --- README.md | 7 ++- scripts/init_state.js | 112 +++++++++++++++++++++--------------------- 2 files changed, 62 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 9c3a50b6..ab0bb085 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,9 @@ The system uses dedicated queues for managing different job phases: - SNS for alerts - EventBridge for scheduling -> ๐Ÿšจ **Important Note**: Currently, Madara doesn't support the `get_storage_proof` endpoint. Therefore, you need to run Pathfinder alongside Madara: +> ๐Ÿšจ **Important Note**: Currently, Madara doesn't support the `get_storage_proof` endpoint. +> +> Therefore, you need to run Pathfinder alongside Madara: > > - Madara will run in sequencer mode > - Pathfinder will sync with Madara @@ -244,7 +246,8 @@ The system uses dedicated queues for managing different job phases: MADARA_ORCHESTRATOR_VERIFIER_ADDRESS= ``` -Note: The mock services are intended for development and testing purposes only. In production, you'll need to use actual proving services and verifier contracts. +Note: The mock services are intended for development and testing purposes only. +In production, you'll need to use actual proving services and verifier contracts. ### Setup Mode diff --git a/scripts/init_state.js b/scripts/init_state.js index a5cb3a09..474e39ab 100644 --- a/scripts/init_state.js +++ b/scripts/init_state.js @@ -18,7 +18,7 @@ const MADARA_ORCHESTRATOR_ETHEREUM_PRIVATE_KEY = const eth_provider = new ethers.JsonRpcProvider("http://localhost:8545"); const wallet = new ethers.Wallet( MADARA_ORCHESTRATOR_ETHEREUM_PRIVATE_KEY, - eth_provider, + eth_provider ); const starknet_provider = new starknet.RpcProvider({ @@ -56,7 +56,7 @@ async function getAppChainBalance(address) { const ethContract = new starknet.Contract( abi, ETHEREUM_APP_CHAIN_ADDRESS, - starknet_provider, + starknet_provider ); // Interaction with the contract with call @@ -69,16 +69,16 @@ async function bridgeToChain(bridge_address, starnet_expected_account_address) { const contract = new ethers.Contract( bridge_address, ["function deposit(uint256, uint256)"], - wallet, + wallet ); const initial_app_chain_balance = await getAppChainBalance( - starnet_expected_account_address, + starnet_expected_account_address ); const tx = await contract.deposit( ethers.parseEther("1"), starnet_expected_account_address, - { value: ethers.parseEther("1.01") }, + { value: ethers.parseEther("1.01") } ); tx.wait(); @@ -88,13 +88,13 @@ async function bridgeToChain(bridge_address, starnet_expected_account_address) { let counter = 10; while (counter--) { const final_app_chain_balance = await getAppChainBalance( - starnet_expected_account_address, + starnet_expected_account_address ); if (final_app_chain_balance > initial_app_chain_balance) { console.log( "๐Ÿ’ฐ App chain balance:", (final_app_chain_balance / 10n ** 18n).toString(), - "ETH", + "ETH" ); return; } @@ -121,7 +121,7 @@ function calculatePrefactualAccountAddress() { starkKeyPub, OZ_ACCOUNT_CLASS_HASH, OZaccountConstructorCallData, - 0, + 0 ); return { address: OZcontractAddress, @@ -172,14 +172,14 @@ async function validateBlockPassesSnosChecks(block_number) { async function deployStarknetAccount( starknet_private_key, starnet_expected_account_address, - starknet_account_public_key, + starknet_account_public_key ) { console.log("โณ Deploying Starknet account..."); const account = new starknet.Account( starknet_provider, starnet_expected_account_address, starknet_private_key, - "1", + "1" ); const { transaction_hash, contract_address } = await account.deployAccount({ classHash: OZ_ACCOUNT_CLASS_HASH, @@ -211,7 +211,7 @@ async function waitForTransactionSuccess(hash) { // can run SNOS async function overrideStateOnCoreContract( block_number, - core_contract_address, + core_contract_address ) { let state_update = await starknet_provider.getStateUpdate(block_number); let abi = [ @@ -244,7 +244,7 @@ async function overrideStateOnCoreContract( const tx = await contract.updateStateOverride( state_update.new_root, block_number, - state_update.block_hash, + state_update.block_hash ); const receipt = await tx.wait(); if (!receipt.status) { @@ -296,13 +296,13 @@ async function setupMongoDb(block_number) { async function transfer( starknet_account_private_key, - starnet_expected_account_address, + starnet_expected_account_address ) { const account = new starknet.Account( starknet_provider, starnet_expected_account_address, starknet_account_private_key, - "1", + "1" ); const abi = [ { @@ -346,7 +346,7 @@ async function transfer( const contract = new starknet.Contract( abi, ETHEREUM_APP_CHAIN_ADDRESS, - starknet_provider, + starknet_provider ); let calldata = contract.populate("transfer", { recipient: "0x1234", @@ -361,7 +361,7 @@ async function transfer( txn_hash.transaction_hash, { retryInterval: 100, - }, + } ); if (!receipt.isSuccess()) { console.log("โŒ Failed to do a transfer on Starknet account"); @@ -371,7 +371,7 @@ async function transfer( // if txn is pending, block_number won't be available while (!receipt.block_number) { receipt = await starknet_provider.getTransactionReceipt( - txn_hash.transaction_hash, + txn_hash.transaction_hash ); await new Promise((resolve) => setTimeout(resolve, 200)); } @@ -387,19 +387,19 @@ async function transfer( async function upgradeETHToken( l2_eth_token_address, starknet_account_private_key, - starnet_expected_account_address, + starnet_expected_account_address ) { const account = new starknet.Account( starknet_provider, starnet_expected_account_address, starknet_account_private_key, - "1", + "1" ); // declare and deploy the new ERC20 contract // https://sepolia.starkscan.co/tx/0x04b5fa2a2e738a8b7a6c7b15194fbcf4409411743ebbe48cc5b83e5fe0edffdf console.log( - "โ„น๏ธ Sending transaction to declare and deploy new ERC20 contract for ETH...", + "โ„น๏ธ Sending transaction to declare and deploy new ERC20 contract for ETH..." ); let new_erc20_declare_deploy = await account.declareAndDeploy({ contract: require("./artifacts/starknet/new_eth_token.sierra.json"), @@ -433,12 +433,12 @@ async function upgradeETHToken( // add_implementation to bridge contarct before we upgrade // https://sepolia.starkscan.co/tx/0x064ab87819a2f8ebf91176eeb901f842c23ef6c97c107fe31b14defa352ba045 console.log( - "โ„น๏ธ Sending transaction to add implementation to bridge contract...", + "โ„น๏ธ Sending transaction to add implementation to bridge contract..." ); let eth_bridge = new starknet.Contract( require("./artifacts/starknet/bridge_proxy_legacy.json").abi, l2_eth_token_address, - account, + account ); let add_implementation_calldata = eth_bridge.populate("add_implementation", [ new_erc20_declare_deploy.deploy.address, @@ -447,7 +447,7 @@ async function upgradeETHToken( 0, // final ]); let add_implementation_txn_hash = await eth_bridge.add_implementation( - add_implementation_calldata.calldata, + add_implementation_calldata.calldata ); await waitForTransactionSuccess(add_implementation_txn_hash.transaction_hash); console.log("โœ… Transaction successful."); @@ -457,7 +457,7 @@ async function upgradeETHToken( console.log("โ„น๏ธ Sending transaction to upgrade ETH token contract..."); let upgrade_txn_hash = await eth_bridge.upgrade_to( // the calldata is the same - add_implementation_calldata.calldata, + add_implementation_calldata.calldata ); await waitForTransactionSuccess(upgrade_txn_hash.transaction_hash); console.log("โœ… Transaction successful."); @@ -465,7 +465,7 @@ async function upgradeETHToken( // now add a new implementation to the bridge contract for the erc20 class hash // https://sepolia.starkscan.co/tx/0x051cc24816ec349c601bbd4e9afc8e0a8c7a93061aba372045bbf7e5d35aff7a console.log( - "โ„น๏ธ Sending transaction to add new implementation to bridge contract...", + "โ„น๏ธ Sending transaction to add new implementation to bridge contract..." ); let add_new_implementation_txn_hash = await account.execute([ { @@ -480,13 +480,13 @@ async function upgradeETHToken( }, ]); await waitForTransactionSuccess( - add_new_implementation_txn_hash.transaction_hash, + add_new_implementation_txn_hash.transaction_hash ); console.log("โœ… Transaction successful."); // finally replace the class hash on the ETH contract console.log( - "โ„น๏ธ Sending transaction to replace class hash on the ETH contract...", + "โ„น๏ธ Sending transaction to replace class hash on the ETH contract..." ); let replace_to_txn_hash = await account.execute([ { @@ -512,19 +512,19 @@ async function upgradeETHToken( async function upgradeETHBridge( l2_eth_bridge_address, starknet_account_private_key, - starnet_expected_account_address, + starnet_expected_account_address ) { const account = new starknet.Account( starknet_provider, starnet_expected_account_address, starknet_account_private_key, - "1", + "1" ); // declare and deploy the new ETH bridge contract // https://sepolia.starkscan.co/tx/0x05c266b9069c04f68752f5eb9652d7c0cd130c6d152d2267a8480273ec991de6 console.log( - "โ„น๏ธ Sending transaction to declare and deploy new ETH bridge contract for ETH...", + "โ„น๏ธ Sending transaction to declare and deploy new ETH bridge contract for ETH..." ); let new_bridge_declare_deploy = await account.declareAndDeploy({ contract: require("./artifacts/starknet/new_eth_bridge.sierra.json"), @@ -548,12 +548,12 @@ async function upgradeETHBridge( // add_implementation to bridge contarct before we upgrade // https://sepolia.starkscan.co/call/0x0721b02e1f4daa98ed8928966d66f345cb897f382274b22c89d86c00e755106d_1_1 console.log( - "โ„น๏ธ Sending transaction to add implementation to bridge contract...", + "โ„น๏ธ Sending transaction to add implementation to bridge contract..." ); let eth_bridge = new starknet.Contract( require("./artifacts/starknet/bridge_proxy_legacy.json").abi, l2_eth_bridge_address, - account, + account ); let add_implementation_calldata = eth_bridge.populate("add_implementation", [ new_bridge_declare_deploy.deploy.address, @@ -565,7 +565,7 @@ async function upgradeETHBridge( 0, // final ]); let add_implementation_txn_hash = await eth_bridge.add_implementation( - add_implementation_calldata.calldata, + add_implementation_calldata.calldata ); await waitForTransactionSuccess(add_implementation_txn_hash.transaction_hash); console.log("โœ… Transaction successful."); @@ -575,7 +575,7 @@ async function upgradeETHBridge( console.log("โ„น๏ธ Sending transaction to upgrade ETH bridge contract..."); let upgrade_txn_hash = await eth_bridge.upgrade_to( // the calldata is the same - add_implementation_calldata.calldata, + add_implementation_calldata.calldata ); await waitForTransactionSuccess(upgrade_txn_hash.transaction_hash); console.log("โœ… Transaction successful."); @@ -583,7 +583,7 @@ async function upgradeETHBridge( // now add a new implementation to the bridge contract for the bridge class hash // https://sepolia.starkscan.co/tx/0x051cc24816ec349c601bbd4e9afc8e0a8c7a93061aba372045bbf7e5d35aff7a console.log( - "โ„น๏ธ Sending transaction to add new implementation to bridge contract...", + "โ„น๏ธ Sending transaction to add new implementation to bridge contract..." ); let add_new_implementation_txn_hash = await account.execute([ { @@ -598,13 +598,13 @@ async function upgradeETHBridge( }, ]); await waitForTransactionSuccess( - add_new_implementation_txn_hash.transaction_hash, + add_new_implementation_txn_hash.transaction_hash ); console.log("โœ… Transaction successful."); // finally replace the class hash on the ETH contract console.log( - "โ„น๏ธ Sending transaction to replace class hash on the ETH contract...", + "โ„น๏ธ Sending transaction to replace class hash on the ETH contract..." ); let replace_to_txn_hash = await account.execute([ { @@ -623,7 +623,7 @@ async function upgradeL1EthBridge(l1_bridge_address) { const contract = new ethers.ContractFactory( newEthBridge.abi, newEthBridge.bytecode, - wallet, + wallet ); const ethBridgeReceipt = await contract.deploy(); await ethBridgeReceipt.waitForDeployment(); @@ -635,7 +635,7 @@ async function upgradeL1EthBridge(l1_bridge_address) { const eicContract = new ethers.ContractFactory( newEic.abi, newEic.bytecode, - wallet, + wallet ); const eicReceipt = await eicContract.deploy(); await eicReceipt.waitForDeployment(); @@ -693,14 +693,14 @@ async function upgradeL1EthBridge(l1_bridge_address) { stateMutability: "payable", }, ], - wallet, + wallet ); // add new implementation to the bridge let addImplementationTxn = await bridge.addImplementation( ethBridgeAddress, chainHexesToBytes([eicAddress, "0x0", "0x0"]), - false, + false ); await addImplementationTxn.wait(); console.log("โœ… New implementation added to the bridge"); @@ -709,7 +709,7 @@ async function upgradeL1EthBridge(l1_bridge_address) { let upgradeToTxn = await bridge.upgradeTo( ethBridgeAddress, chainHexesToBytes([eicAddress, "0x0", "0x0"]), - false, + false ); await upgradeToTxn.wait(); console.log("โœ… Bridge upgraded to the new implementation"); @@ -763,8 +763,9 @@ async function main() { const bootstrapper_private_key = "0xabcd" || process.argv[7]; // add funds to boostrapper account - let bootstrapper_address_balance = - await getAppChainBalance(bootstrapper_address); + let bootstrapper_address_balance = await getAppChainBalance( + bootstrapper_address + ); if (bootstrapper_address_balance < 10n ** 17n) { await bridgeToChain(l1_bridge_address, bootstrapper_address); } else { @@ -772,21 +773,22 @@ async function main() { } // upgrade ETH token to Cairo 1 as SNOS breaks otherwise - const eth_token_class = - await starknet_provider.getClassAt(l2_eth_token_address); + const eth_token_class = await starknet_provider.getClassAt( + l2_eth_token_address + ); if (eth_token_class.sierra_program) { console.log("โ„น๏ธ Eth token is already upgraded, proceeding"); } else { await upgradeETHToken( l2_eth_token_address, bootstrapper_private_key, - bootstrapper_address, + bootstrapper_address ); } // upgrade ETH bridge to Cairo 1 as well const l2_eth_bridge_class = await starknet_provider.getClassAt( - l2_eth_bridge_address, + l2_eth_bridge_address ); if (l2_eth_bridge_class.sierra_program) { console.log("โ„น๏ธ Eth bridge is already upgraded, proceeding"); @@ -794,7 +796,7 @@ async function main() { await upgradeETHBridge( l2_eth_bridge_address, bootstrapper_private_key, - bootstrapper_address, + bootstrapper_address ); } @@ -802,14 +804,14 @@ async function main() { const l1BridgeContract = new ethers.Contract( l1_bridge_address, ["function identify() external view returns (string)"], - eth_provider, + eth_provider ); const identify = await l1BridgeContract.identify(); console.log("โ„น๏ธ L1 ETH bridge identify:", identify); if ( identify.includes( // StarkWare_StarknetEthBridge_2023_1 - "StarkWare_StarknetEthBridge_2023_1", + "StarkWare_StarknetEthBridge_2023_1" ) ) { await upgradeL1EthBridge(l1_bridge_address); @@ -824,7 +826,7 @@ async function main() { } = calculatePrefactualAccountAddress(); console.log( "๐Ÿฆ Starknet expected account address:", - starnet_expected_account_address, + starnet_expected_account_address ); await bridgeToChain(l1_bridge_address, starnet_expected_account_address); @@ -832,7 +834,7 @@ async function main() { let block_number = await deployStarknetAccount( starknet_account_private_key, starnet_expected_account_address, - starknet_account_public_key, + starknet_account_public_key ); // SNOS doesn't seem to be able to run on deploy account block @@ -840,7 +842,7 @@ async function main() { block_number = await transfer( starknet_account_private_key, - starnet_expected_account_address, + starnet_expected_account_address ); await validateBlockPassesSnosChecks(block_number); @@ -852,4 +854,4 @@ async function main() { await setupMongoDb(block_number - 1); } -main(); \ No newline at end of file +main(); From f9216443dd7b835ade32fd853d1ef449eecf9872 Mon Sep 17 00:00:00 2001 From: mohiiit Date: Wed, 18 Dec 2024 11:44:09 +0530 Subject: [PATCH 07/17] chore: linting and formatting --- .prettierignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.prettierignore b/.prettierignore index 1243185b..2158a86d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,3 +7,4 @@ pathfinder/ orchestrator_venv/ build/ node_modules/ +scripts/ From 6e6b991f5a7993887981e13a3970b24d005491b6 Mon Sep 17 00:00:00 2001 From: mohiiit Date: Wed, 18 Dec 2024 21:55:20 +0530 Subject: [PATCH 08/17] chore: script added for dummy contract deployment, readme udpated to use dummy sharp service --- README.md | 104 +++++++++++---- scripts/artifacts/eth/MockGPSVerifier.sol | 9 ++ scripts/dummy_contract_deployment.sh | 150 ++++++++++++++++++++++ 3 files changed, 239 insertions(+), 24 deletions(-) create mode 100644 scripts/artifacts/eth/MockGPSVerifier.sol create mode 100755 scripts/dummy_contract_deployment.sh diff --git a/README.md b/README.md index ab0bb085..1043a782 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ The Madara orchestrator is designed to be an additional service which runs in parallel to Madara and handles various critical jobs that ensure proper block processing, proof generation, data submission and state transitions. -> ๐Ÿ“ **Note**: These instructions are verified for Ubuntu systems. While most steps remain similar +> ๐Ÿ“ **Note**: These instructions are verified for Ubuntu systems with AMD64 architecture. While most steps remain similar > for macOS, some package names and installation commands may differ. ## Table of Contents @@ -129,15 +129,19 @@ The system uses dedicated queues for managing different job phases: - SNS for alerts - EventBridge for scheduling -> ๐Ÿšจ **Important Note**: Currently, Madara doesn't support the `get_storage_proof` endpoint. +> ๐Ÿšจ **Important Note**: SNOS requires the `get_storage_proof` RPC endpoint to function. +> Currently, this endpoint is not implemented in Madara. > -> Therefore, you need to run Pathfinder alongside Madara: +> ๐Ÿšง Until madara implements the `get_storage_proof` endpoint, you need to run Pathfinder alongside Madara: > > - Madara will run in sequencer mode > - Pathfinder will sync with Madara > - The orchestrator will use Pathfinder's RPC URL for SNOS and state update fetching > -> This setup ensures proper functionality until the `get_storage_proof` endpoint is implemented in Madara. +> This setup is temporary until either: +> +> 1. SNOS is adapted to work without the `get_storage_proof` endpoint, or +> 2. The `get_storage_proof` endpoint is implemented in Madara ## ๐Ÿš€ Installation & Setup @@ -212,41 +216,89 @@ The system uses dedicated queues for managing different job phases: 4. **Setup Mock Proving Service** + ๐Ÿšง This setup is for development purposes only: + ```bash - # Create a simple HTTP server that always returns 200 - # Example using Python - python3 -m http.server 8888 & + # Start the mock prover service using Docker + docker run -d -p 6000:6000 ocdbytes/mock-prover:latest # Set the mock prover URL in your .env - MADARA_ORCHESTRATOR_ATLANTIC_SERVICE_URL=http://localhost:8888 + MADARA_ORCHESTRATOR_SHARP_URL=http://localhost:6000 ``` -5. **Deploy Mock Verifier Contract** +5. **Run Pathfinder** (Choose one method) - You can deploy the mock verifier contract in two ways: + > ๐Ÿšจ **Important Note**: + > + > - Pathfinder requires a WebSocket Ethereum endpoint (`ethereum.url`). Since Anvil doesn't support WebSocket yet, + > you'll need to provide a different Ethereum endpoint (e.g., Alchemy, Infura). This is okay for local development + > as Pathfinder only uses this for block header verification. + > - Make sure `chain-id` matches your Madara chain ID (default: `MADARA_DEVNET`) + > - The `gateway-url` and `feeder-gateway-url` should point to your local Madara node (default: `http://localhost:8080`) - a. **Using Test Implementation** + a. **From Source** (Recommended for development) - - Reference the implementation in `e2e-tests/tests.rs` which contains `AnvilSetup` - - This handles the deployment of both the StarkNet core contract and verifier contract + ```bash + # Clone the repository + git clone https://github.com/eqlabs/pathfinder.git + cd pathfinder + + # Run pathfinder + cargo run --bin pathfinder -- \ + --network custom \ + --chain-id MADARA_DEVNET \ + --ethereum.url wss://eth-sepolia.g.alchemy.com/v2/xxx \ # Replace with your Ethereum endpoint + --gateway-url http://localhost:8080/gateway \ + --feeder-gateway-url http://localhost:8080/feeder_gateway \ + --storage.state-tries archive \ + --data-directory ~/Desktop/pathfinder_db/ \ + --http-rpc 127.0.0.1:9545 + ``` - ```rust - // From e2e-tests/tests.rs - let anvil_setup = AnvilSetup::new(); - let (starknet_core_contract_address, verifier_contract_address) = anvil_setup.deploy_contracts().await; + b. **Using Docker** + + ```bash + # Create data directory + mkdir -p ~/pathfinder_data + + # Run pathfinder container + docker run \ + --name pathfinder \ + --restart unless-stopped \ + -p 9545:9545 \ + --user "$(id -u):$(id -g)" \ + -e RUST_LOG=info \ + -v ~/pathfinder_data:/usr/share/pathfinder/data \ + eqlabs/pathfinder \ + --network custom \ + --chain-id MADARA_DEVNET \ + --ethereum.url wss://eth-sepolia.g.alchemy.com/v2/xxx \ # Replace with your Ethereum endpoint + --gateway-url http://localhost:8080/gateway \ + --feeder-gateway-url http://localhost:8080/feeder_gateway \ + --storage.state-tries archive ``` - b. **Manual Deployment** +6. **Deploy Mock Verifier Contract** - - Alternatively, you can deploy the mock verifier directly using Foundry - - The contract should implement the same interface as used in the tests - - Set the deployed address in your environment: + ๐Ÿšง For development purposes, you can deploy the mock verifier contract using: ```bash - MADARA_ORCHESTRATOR_VERIFIER_ADDRESS= + ./scripts/dummy_contract_deployment.sh http://localhost:9944 0 ``` -Note: The mock services are intended for development and testing purposes only. + This script: + + - Takes the Madara endpoint and block number as parameters + - Automatically deploys both the verifier contract and core contract + - Sets up the necessary contract relationships + - The deployed contract addresses will be output to the console + + ```bash + MADARA_ORCHESTRATOR_L1_CORE_CONTRACT_ADDRESS= + MADARA_ORCHESTRATOR_VERIFIER_ADDRESS= + ``` + +๐Ÿšง Note: The mock services are intended for development and testing purposes only. In production, you'll need to use actual proving services and verifier contracts. ### Setup Mode @@ -267,7 +319,7 @@ Run mode executes the orchestrator's job processing workflow. Example command: ```bash RUST_LOG=info cargo run --release --bin orchestrator run \ - --atlantic \ + --sharp \ --aws \ --settle-on-ethereum \ --aws-s3 \ @@ -381,6 +433,8 @@ It requires a `Otel-collector` url to be able to send metrics/logs/traces. ### Local Environment Setup +๐Ÿšง This setup is for development purposes. For production deployment, please refer to our deployment documentation. + Before running tests, ensure you have: 1. **Required Services Running**: @@ -401,6 +455,8 @@ Before running tests, ensure you have: 1. **E2E Tests** ๐Ÿ”„ + ๐Ÿšง Development test environment: + - End-to-end workflow testing - Tests orchestrator functionality on block 66645 of Starknet - Uses mocked proving endpoints diff --git a/scripts/artifacts/eth/MockGPSVerifier.sol b/scripts/artifacts/eth/MockGPSVerifier.sol new file mode 100644 index 00000000..a5ddb007 --- /dev/null +++ b/scripts/artifacts/eth/MockGPSVerifier.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract MockGPSVerifier { + // Returns true for any input fact hash + function isValid(bytes32) public pure returns (bool) { + return true; + } +} \ No newline at end of file diff --git a/scripts/dummy_contract_deployment.sh b/scripts/dummy_contract_deployment.sh new file mode 100755 index 00000000..2e3162f6 --- /dev/null +++ b/scripts/dummy_contract_deployment.sh @@ -0,0 +1,150 @@ +#!/bin/bash + +# Check if jq is installed +if ! command -v jq &> /dev/null; then + echo "Error: jq is required but not installed. Please install jq first." + exit 1 +fi + +# Check if curl is installed +if ! command -v curl &> /dev/null; then + echo "Error: curl is required but not installed. Please install curl first." + exit 1 +fi + +# Check if required arguments are provided +if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: $0 " + echo "Example: $0 http://localhost:9944 66644" + exit 1 +fi + +# Read arguments +ABI_FILE='./e2e-tests/artifacts/contracts/Starknet.json' +RPC_URL=$1 +BLOCK_NUMBER=$2 + +# Default Anvil private key +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +ANVIL_URL="http://localhost:8545" + +echo -e "\n๐Ÿ” Fetching state update for block $BLOCK_NUMBER..." + +# Fetch state update from RPC with correct params structure +STATE_UPDATE=$(curl -s -X POST -H "Content-Type: application/json" --data "{ + \"jsonrpc\":\"2.0\", + \"method\":\"starknet_getStateUpdate\", + \"params\": { + \"block_id\": { + \"block_number\": $BLOCK_NUMBER + } + }, + \"id\":1 +}" "$RPC_URL") + +# Extract global root and block hash from the response +GLOBAL_ROOT=$(echo "$STATE_UPDATE" | jq -r '.result.new_root') +BLOCK_HASH=$(echo "$STATE_UPDATE" | jq -r '.result.block_hash') + +if [ "$GLOBAL_ROOT" == "null" ] || [ "$BLOCK_HASH" == "null" ]; then + echo "Error: Failed to fetch state update data" + echo "Response: $STATE_UPDATE" + exit 1 +fi + +echo -e "\n๐Ÿ“Š State Update Data:" +echo " Global Root: $GLOBAL_ROOT" +echo " Block Hash: $BLOCK_HASH" +echo "" + +# Deploy the verifier contract using forge create +echo -e "๐Ÿš€ Deploying verifier contract...\n" +VERIFIER_RESULT=$(forge create \ + --rpc-url "$ANVIL_URL" \ + --private-key "$PRIVATE_KEY" \ + "scripts/artifacts/eth/MockGPSVerifier.sol:MockGPSVerifier" \ + 2>&1) + +if [ $? -ne 0 ]; then + echo "Error deploying verifier contract:" + echo "$VERIFIER_RESULT" + exit 1 +fi + +# Extract contract address from forge create output +VERIFIER_ADDRESS=$(echo "$VERIFIER_RESULT" | grep "Deployed to" | awk '{print $3}') +echo -e "๐Ÿ“ฆ Verifier deployed at: $VERIFIER_ADDRESS\n" + +# Now deploy the main Starknet contract +echo -e "๐Ÿš€ Deploying Starknet contract...\n" + +# Extract bytecode from the JSON file +BYTECODE=$(jq -r '.bytecode.object' "$ABI_FILE" | sed 's/^0x//') + +if [ "$BYTECODE" == "null" ] || [ -z "$BYTECODE" ]; then + echo "Error: No bytecode found in the JSON file" + exit 1 +fi + +# Deploy the contract using cast +RESULT=$(cast send \ + --private-key "$PRIVATE_KEY" \ + --rpc-url "$ANVIL_URL" \ + --create "0x$BYTECODE" \ + 2>&1) + +# Check if deployment was successful +if [ $? -eq 0 ]; then + # Extract contract address from the result using grep and awk + CONTRACT_ADDRESS=$(echo "$RESULT" | grep "contractAddress" | awk '{print $2}') + + if [ -n "$CONTRACT_ADDRESS" ]; then + echo -e "๐Ÿ“ฆ Starknet contract deployed successfully at: $CONTRACT_ADDRESS\n" + + # sleep for 2 seconds + sleep 2 + + # Initialize the contract with the required data + echo -e "๐Ÿ”ง Initializing contract...\n" + + # Create the initialization data + PROGRAM_HASH="853638403225561750106379562222782223909906501242604214771127703946595519856" + AGGREGATOR_PROGRAM_HASH="0" + CONFIG_HASH="1773546093672122186726825451867439478968296982619761985456743675021283370179" + + # Encode the initialization data + INIT_DATA=$(cast abi-encode "f(uint256,uint256,address,uint256,uint256,int256,uint256)" \ + $PROGRAM_HASH \ + $AGGREGATOR_PROGRAM_HASH \ + $VERIFIER_ADDRESS \ + $CONFIG_HASH \ + $GLOBAL_ROOT \ + $BLOCK_NUMBER \ + $BLOCK_HASH) + + # Call initializeContractState + INIT_RESULT=$(cast send \ + --private-key "$PRIVATE_KEY" \ + --rpc-url "$ANVIL_URL" \ + $CONTRACT_ADDRESS \ + "initializeContractState(bytes)" \ + $INIT_DATA) + + if [ $? -eq 0 ]; then + TX_HASH=$(echo "$INIT_RESULT" | grep "transactionHash" | awk '{print $2}') + echo -e "โœ… Contract initialized successfully!" + echo -e " Transaction: $TX_HASH\n" + else + echo -e "โŒ Error initializing contract\n" + echo "$INIT_RESULT" + exit 1 + fi + else + echo "โŒ Error: Could not extract contract address from output" + exit 1 + fi +else + echo "โŒ Error deploying contract:" + echo "$RESULT" + exit 1 +fi \ No newline at end of file From 3d57f39eb0c9ad1206f182c2080a7103de093ac8 Mon Sep 17 00:00:00 2001 From: Heemank Verma Date: Thu, 19 Dec 2024 22:51:58 +0530 Subject: [PATCH 09/17] update: aws_event_bridge rework --- .../orchestrator/src/cli/cron/event_bridge.rs | 9 +- crates/orchestrator/src/cli/mod.rs | 20 +++- crates/orchestrator/src/cron/event_bridge.rs | 105 +++++++++++++----- madara-bootstrapper | 2 +- 4 files changed, 100 insertions(+), 36 deletions(-) diff --git a/crates/orchestrator/src/cli/cron/event_bridge.rs b/crates/orchestrator/src/cli/cron/event_bridge.rs index e9e83c25..88700ce3 100644 --- a/crates/orchestrator/src/cli/cron/event_bridge.rs +++ b/crates/orchestrator/src/cli/cron/event_bridge.rs @@ -2,11 +2,14 @@ use clap::Args; /// CLI arguments for the aws event bridge. #[derive(Debug, Clone, Args)] -#[group()] pub struct AWSEventBridgeCliArgs { - /// Use the AWS Event Bridge client + /// Use the AWS Event Bridge Rule client #[arg(long)] - pub aws_event_bridge: bool, + pub aws_event_bridge_rule: bool, + + /// Use the AWS Event Bridge Schedule client + #[arg(long)] + pub aws_event_bridge_schedule: bool, /// The name of the queue for the event bridge #[arg(env = "MADARA_ORCHESTRATOR_EVENT_BRIDGE_TARGET_QUEUE_NAME", long, default_value = Some("madara_orchestrator_worker_trigger_queue"), help = "The name of the SNS queue to send messages to from the event bridge.")] diff --git a/crates/orchestrator/src/cli/mod.rs b/crates/orchestrator/src/cli/mod.rs index b17d9369..59816d82 100644 --- a/crates/orchestrator/src/cli/mod.rs +++ b/crates/orchestrator/src/cli/mod.rs @@ -246,7 +246,7 @@ impl RunCmd { ), group( ArgGroup::new("cron") - .args(&["aws_event_bridge"]) + .args(&["aws_event_bridge_rule", "aws_event_bridge_schedule"]) .required(true) .multiple(false) .requires("provider") @@ -336,7 +336,7 @@ pub mod validate_params { use crate::alerts::aws_sns::AWSSNSValidatedArgs; use crate::cli::prover_layout::ProverLayoutCliArgs; use crate::config::ServiceParams; - use crate::cron::event_bridge::AWSEventBridgeValidatedArgs; + use crate::cron::event_bridge::{AWSEventBridgeValidatedArgs, EventBridgeType}; use crate::data_storage::aws_s3::AWSS3ValidatedArgs; use crate::database::mongodb::MongoDBValidatedArgs; use crate::queue::sqs::AWSSQSValidatedArgs; @@ -403,8 +403,19 @@ pub mod validate_params { aws_event_bridge_args: &AWSEventBridgeCliArgs, aws_config_args: &AWSConfigCliArgs, ) -> Result { - if aws_event_bridge_args.aws_event_bridge && aws_config_args.aws { + if (aws_event_bridge_args.aws_event_bridge_rule || aws_event_bridge_args.aws_event_bridge_schedule) + && aws_config_args.aws + { + let cron_type = if aws_event_bridge_args.aws_event_bridge_rule { + EventBridgeType::Rule + } else if aws_event_bridge_args.aws_event_bridge_schedule { + EventBridgeType::Schedule + } else { + panic!("No Cron service selected!") + }; + Ok(CronValidatedArgs::AWSEventBridge(AWSEventBridgeValidatedArgs { + cron_type, target_queue_name: aws_event_bridge_args .target_queue_name .clone() @@ -841,7 +852,8 @@ pub mod validate_params { #[case(false)] fn test_validate_cron_params(#[case] is_aws: bool) { let aws_event_bridge_args: AWSEventBridgeCliArgs = AWSEventBridgeCliArgs { - aws_event_bridge: is_aws, + aws_event_bridge_rule: is_aws, + aws_event_bridge_schedule: !is_aws, target_queue_name: Some(String::from("test")), cron_time: Some(String::from("12")), trigger_rule_name: Some(String::from("test")), diff --git a/crates/orchestrator/src/cron/event_bridge.rs b/crates/orchestrator/src/cron/event_bridge.rs index 112665f0..93811004 100644 --- a/crates/orchestrator/src/cron/event_bridge.rs +++ b/crates/orchestrator/src/cron/event_bridge.rs @@ -1,10 +1,9 @@ use std::time::Duration; -use async_std::task::sleep; use async_trait::async_trait; use aws_config::SdkConfig; +use aws_sdk_eventbridge::types::{InputTransformer, RuleState, Target as EventBridgeTarget}; use aws_sdk_scheduler::types::{FlexibleTimeWindow, FlexibleTimeWindowMode, Target}; -use aws_sdk_scheduler::Client as SchedulerClient; use aws_sdk_sqs::types::QueueAttributeName; use aws_sdk_sqs::Client as SqsClient; use color_eyre::eyre::Ok; @@ -13,8 +12,21 @@ use super::{get_worker_trigger_message, TriggerArns}; use crate::cron::Cron; use crate::queue::job_queue::WorkerTriggerType; +#[derive(Clone, Debug)] +pub enum EventBridgeType { + Rule, + Schedule, +} + +#[derive(Clone, Debug)] +enum EventBridgeClient { + Rule(aws_sdk_eventbridge::Client), + Schedule(aws_sdk_scheduler::Client), +} + #[derive(Clone, Debug)] pub struct AWSEventBridgeValidatedArgs { + pub cron_type: EventBridgeType, pub target_queue_name: String, pub cron_time: Duration, pub trigger_rule_name: String, @@ -26,7 +38,7 @@ pub struct AWSEventBridge { target_queue_name: String, cron_time: Duration, trigger_rule_name: String, - client: SchedulerClient, + client: EventBridgeClient, queue_client: SqsClient, iam_client: aws_sdk_iam::Client, trigger_role_name: String, @@ -35,11 +47,16 @@ pub struct AWSEventBridge { impl AWSEventBridge { pub fn new_with_args(params: &AWSEventBridgeValidatedArgs, aws_config: &SdkConfig) -> Self { + let client = match params.cron_type { + EventBridgeType::Rule => EventBridgeClient::Rule(aws_sdk_eventbridge::Client::new(aws_config)), + EventBridgeType::Schedule => EventBridgeClient::Schedule(aws_sdk_scheduler::Client::new(aws_config)), + }; + Self { target_queue_name: params.target_queue_name.clone(), cron_time: params.cron_time, trigger_rule_name: params.trigger_rule_name.clone(), - client: aws_sdk_scheduler::Client::new(aws_config), + client, queue_client: aws_sdk_sqs::Client::new(aws_config), iam_client: aws_sdk_iam::Client::new(aws_config), trigger_role_name: params.trigger_role_name.clone(), @@ -66,6 +83,7 @@ impl Cron for AWSEventBridge { // Create IAM role for EventBridge let role_name = format!("{}-{}", self.trigger_role_name, uuid::Uuid::new_v4()); + // TODO: might need to change this accordingly to support rule, skipping for now let assume_role_policy = r#"{ "Version": "2012-10-17", "Statement": [{ @@ -113,7 +131,7 @@ impl Cron for AWSEventBridge { // Attach the policy to the role self.iam_client.attach_role_policy().role_name(&role_name).policy_arn(&policy_arn).send().await?; - sleep(Duration::from_secs(60)).await; + // sleep(Duration::from_secs(60)).await; Ok(TriggerArns { queue_arn: queue_arn.to_string(), role_arn: role_arn.to_string() }) } @@ -123,30 +141,61 @@ impl Cron for AWSEventBridge { trigger_type: &WorkerTriggerType, trigger_arns: &TriggerArns, ) -> color_eyre::Result<()> { - let trigger_name = format!("{}-{}", self.trigger_rule_name, trigger_type); - - // Set flexible time window (you can adjust this as needed) - let flexible_time_window = FlexibleTimeWindow::builder().mode(FlexibleTimeWindowMode::Off).build()?; - let message = get_worker_trigger_message(trigger_type.clone())?; - - // Create target for SQS queue - let target = Target::builder() - .arn(trigger_arns.queue_arn.clone()) - .role_arn(trigger_arns.role_arn.clone()) - .input(message) - .build()?; - - // Create the schedule - self.client - .create_schedule() - .name(trigger_name) - .schedule_expression_timezone("UTC") - .flexible_time_window(flexible_time_window) - .schedule_expression(duration_to_rate_string(self.cron_time)) - .target(target) - .send() - .await?; + let trigger_name = format!("{}-{}", self.trigger_rule_name, trigger_type); + println!("trigger_nametrigger_nametrigger_name {}", trigger_name); + + match self.client.clone() { + EventBridgeClient::Rule(client) => { + let input_transformer = + InputTransformer::builder().input_paths_map("time", "$.time").input_template(message).build()?; + + client + .put_rule() + .name(trigger_name.clone()) + .schedule_expression("rate(1 minute)") + .state(RuleState::Enabled) + .send() + .await?; + + client + .put_targets() + .rule(trigger_name.clone()) + .targets( + EventBridgeTarget::builder() + .id(uuid::Uuid::new_v4().to_string()) + .arn(trigger_arns.queue_arn.clone()) + .input_transformer(input_transformer.clone()) + .build()?, + ) + .send() + .await?; + } + EventBridgeClient::Schedule(client) => { + // Set flexible time window (you can adjust this as needed) + let flexible_time_window = FlexibleTimeWindow::builder().mode(FlexibleTimeWindowMode::Off).build()?; + + let message = get_worker_trigger_message(trigger_type.clone())?; + + // Create target for SQS queue + let target = Target::builder() + .arn(trigger_arns.queue_arn.clone()) + .role_arn(trigger_arns.role_arn.clone()) + .input(message) + .build()?; + + // Create the schedule + client + .create_schedule() + .name(trigger_name) + .schedule_expression_timezone("UTC") + .flexible_time_window(flexible_time_window) + .schedule_expression(duration_to_rate_string(self.cron_time)) + .target(target) + .send() + .await?; + } + }; Ok(()) } diff --git a/madara-bootstrapper b/madara-bootstrapper index f717bf17..b0b64750 160000 --- a/madara-bootstrapper +++ b/madara-bootstrapper @@ -1 +1 @@ -Subproject commit f717bf179581da53d68fee03b50ef78e0628ee20 +Subproject commit b0b647500c2ae3e3b0d99e345fa652989bca4726 From afeda2e282d43a13baa49c56a66175d06c8b522e Mon Sep 17 00:00:00 2001 From: Heemank Verma Date: Thu, 19 Dec 2024 22:54:23 +0530 Subject: [PATCH 10/17] update: e2e --- e2e-tests/src/node.rs | 3 ++- e2e-tests/tests.rs | 61 ------------------------------------------- 2 files changed, 2 insertions(+), 62 deletions(-) diff --git a/e2e-tests/src/node.rs b/e2e-tests/src/node.rs index 0603cb40..b3d3151c 100644 --- a/e2e-tests/src/node.rs +++ b/e2e-tests/src/node.rs @@ -58,7 +58,8 @@ impl Orchestrator { .arg("--aws") .arg("--aws-s3") .arg("--aws-sqs") - .arg("--aws-sns"); + .arg("--aws-sns") + .arg("--aws-event-bridge-rule"); // Add event bridge arg only for setup mode if is_run_mode { diff --git a/e2e-tests/tests.rs b/e2e-tests/tests.rs index 9430109d..02dbd3b2 100644 --- a/e2e-tests/tests.rs +++ b/e2e-tests/tests.rs @@ -4,8 +4,6 @@ use std::io::Read; use std::time::{Duration, Instant}; use aws_config::meta::region::RegionProviderChain; -use aws_sdk_eventbridge::types::{InputTransformer, RuleState, Target}; -use aws_sdk_sqs::types::QueueAttributeName; use chrono::{SubsecRound, Utc}; use e2e_tests::anvil::AnvilSetup; use e2e_tests::mock_server::MockResponseBodyType; @@ -15,7 +13,6 @@ use e2e_tests::utils::{get_mongo_db_client, read_state_update_from_file, vec_u8_ use e2e_tests::{MongoDbServer, Orchestrator}; use mongodb::bson::doc; use orchestrator::cli::database::DatabaseValidatedArgs; -use orchestrator::cron::{get_worker_trigger_message, WORKER_TRIGGERS}; use orchestrator::data_storage::DataStorage; use orchestrator::database::mongodb::MongoDBValidatedArgs; use orchestrator::jobs::constants::{JOB_METADATA_SNOS_BLOCK, JOB_METADATA_STATE_UPDATE_BLOCKS_TO_SETTLE_KEY}; @@ -173,12 +170,6 @@ async fn test_orchestrator_workflow(#[case] l2_block_number: String) { let trigger_rule_name = &get_env_var_or_panic("MADARA_ORCHESTRATOR_EVENT_BRIDGE_TRIGGER_RULE_NAME"); let target_queue_name = &get_env_var_or_panic("MADARA_ORCHESTRATOR_EVENT_BRIDGE_TARGET_QUEUE_NAME"); - // Setup eventbridge rules - create_event_bridge_rule(trigger_rule_name, target_queue_name).await.expect( - "Unable to create - event bridge rule", - ); - // Run orchestrator let mut orchestrator = Orchestrator::new(OrchestratorMode::Run, setup_config.envs()).expect("Failed to start orchestrator"); @@ -237,58 +228,6 @@ async fn test_orchestrator_workflow(#[case] l2_block_number: String) { assert!(test_result.is_ok(), "After Update State Job state DB state assertion failed."); } -/// Function that adds rules to tests for localstack -/// This can be removed after https://github.com/localstack/localstack/issues/9861 is closed -async fn create_event_bridge_rule(trigger_rule_name: &String, target_queue_name: &String) -> color_eyre::Result<()> { - let aws_config = &aws_config::from_env().load().await; - - let queue_client = aws_sdk_sqs::Client::new(aws_config); - - let event_bridge_client = aws_sdk_eventbridge::Client::new(aws_config); - - let queue_url = queue_client.get_queue_url().queue_name(target_queue_name).send().await?; - - let queue_attributes = queue_client - .get_queue_attributes() - .queue_url(queue_url.queue_url.unwrap()) - .attribute_names(QueueAttributeName::QueueArn) - .send() - .await?; - let queue_arn = queue_attributes.attributes().unwrap().get(&QueueAttributeName::QueueArn).unwrap(); - - // Create the EventBridge target with the input transformer - - for trigger in WORKER_TRIGGERS.iter() { - let message = get_worker_trigger_message(trigger.clone())?; - let input_transformer = - InputTransformer::builder().input_paths_map("time", "$.time").input_template(message).build()?; - - let trigger_name = format!("{}-{}", trigger_rule_name, trigger); - event_bridge_client - .put_rule() - .name(trigger_name.clone()) - .schedule_expression("rate(1 minute)") - .state(RuleState::Enabled) - .send() - .await?; - - event_bridge_client - .put_targets() - .rule(trigger_name.clone()) - .targets( - Target::builder() - .id(uuid::Uuid::new_v4().to_string()) - .arn(queue_arn) - .input_transformer(input_transformer.clone()) - .build()?, - ) - .send() - .await?; - } - - Ok(()) -} - /// Function to check db for expected state continuously async fn wait_for_db_state( timeout: Duration, From a717ddf996b4661902106ad4084cd5d4fe8e5d74 Mon Sep 17 00:00:00 2001 From: mohiiit Date: Thu, 19 Dec 2024 23:48:30 +0530 Subject: [PATCH 11/17] chore: linting-formatting and readme updated --- README.md | 2 +- e2e-tests/src/node.rs | 5 ++--- e2e-tests/tests.rs | 3 --- madara-bootstrapper | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 1043a782..c807e346 100644 --- a/README.md +++ b/README.md @@ -307,7 +307,7 @@ Setup mode configures the required AWS services and dependencies. Use the following command: ```bash -cargo run --release --bin orchestrator setup --aws --aws-s3 --aws-sqs --aws-sns --aws-event-bridge +cargo run --release --bin orchestrator setup --aws --aws-s3 --aws-sqs --aws-sns --aws-event-bridge-rule ``` Note: Setup mode is currently in development. A fresh setup is required diff --git a/e2e-tests/src/node.rs b/e2e-tests/src/node.rs index b3d3151c..be7c569b 100644 --- a/e2e-tests/src/node.rs +++ b/e2e-tests/src/node.rs @@ -58,8 +58,7 @@ impl Orchestrator { .arg("--aws") .arg("--aws-s3") .arg("--aws-sqs") - .arg("--aws-sns") - .arg("--aws-event-bridge-rule"); + .arg("--aws-sns"); // Add event bridge arg only for setup mode if is_run_mode { @@ -75,7 +74,7 @@ impl Orchestrator { command.stdout(Stdio::piped()).stderr(Stdio::piped()); } else { - command.arg("--aws-event-bridge"); + command.arg("--aws-event-bridge-rule"); // For setup mode, inherit the stdio to show output directly command.stdout(Stdio::inherit()).stderr(Stdio::inherit()); diff --git a/e2e-tests/tests.rs b/e2e-tests/tests.rs index 02dbd3b2..ed72488b 100644 --- a/e2e-tests/tests.rs +++ b/e2e-tests/tests.rs @@ -167,9 +167,6 @@ async fn test_orchestrator_workflow(#[case] l2_block_number: String) { println!("โœ… Orchestrator setup completed."); - let trigger_rule_name = &get_env_var_or_panic("MADARA_ORCHESTRATOR_EVENT_BRIDGE_TRIGGER_RULE_NAME"); - let target_queue_name = &get_env_var_or_panic("MADARA_ORCHESTRATOR_EVENT_BRIDGE_TARGET_QUEUE_NAME"); - // Run orchestrator let mut orchestrator = Orchestrator::new(OrchestratorMode::Run, setup_config.envs()).expect("Failed to start orchestrator"); diff --git a/madara-bootstrapper b/madara-bootstrapper index b0b64750..f717bf17 160000 --- a/madara-bootstrapper +++ b/madara-bootstrapper @@ -1 +1 @@ -Subproject commit b0b647500c2ae3e3b0d99e345fa652989bca4726 +Subproject commit f717bf179581da53d68fee03b50ef78e0628ee20 From dd31f13f001075fd08361e077756db4e53a280d0 Mon Sep 17 00:00:00 2001 From: mohiiit Date: Thu, 19 Dec 2024 23:53:08 +0530 Subject: [PATCH 12/17] chore: readme misinformation fixed --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c807e346..64885a29 100644 --- a/README.md +++ b/README.md @@ -232,7 +232,7 @@ The system uses dedicated queues for managing different job phases: > > - Pathfinder requires a WebSocket Ethereum endpoint (`ethereum.url`). Since Anvil doesn't support WebSocket yet, > you'll need to provide a different Ethereum endpoint (e.g., Alchemy, Infura). This is okay for local development - > as Pathfinder only uses this for block header verification. + > as Pathfinder only uses this to get the state update from core contract. > - Make sure `chain-id` matches your Madara chain ID (default: `MADARA_DEVNET`) > - The `gateway-url` and `feeder-gateway-url` should point to your local Madara node (default: `http://localhost:8080`) From ae4a3db1f4cbca737f31f9f201677a76f601f47b Mon Sep 17 00:00:00 2001 From: mohiiit Date: Fri, 20 Dec 2024 10:40:53 +0530 Subject: [PATCH 13/17] update: verification job timeout and polling changed to work for 25 hours --- crates/orchestrator/src/jobs/proving_job/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/orchestrator/src/jobs/proving_job/mod.rs b/crates/orchestrator/src/jobs/proving_job/mod.rs index 138d2734..a034bb4e 100644 --- a/crates/orchestrator/src/jobs/proving_job/mod.rs +++ b/crates/orchestrator/src/jobs/proving_job/mod.rs @@ -149,10 +149,10 @@ impl Job for ProvingJob { } fn max_verification_attempts(&self) -> u64 { - 1200 + 300 } fn verification_polling_delay_seconds(&self) -> u64 { - 30 + 300 } } From 23429a2d2e24089122a713175e8275b36438dde1 Mon Sep 17 00:00:00 2001 From: mohiiit Date: Mon, 23 Dec 2024 14:27:20 +0530 Subject: [PATCH 14/17] chore: comment added for older python version needed --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 64885a29..a909adfb 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,8 @@ The system uses dedicated queues for managing different job phases: brew install openssl pkg-config gmp python@3.9 ``` + > ๐Ÿšจ **Note**: python 3.9 is required for the `SNOS` to create `os_latest.json` hence the `python3.9` in the above command. + 2. **Install Rust** (Cross-platform) ```bash @@ -180,6 +182,8 @@ The system uses dedicated queues for managing different job phases: make snos ``` + > ๐Ÿšจ **Note**: python 3.9 is required for the `SNOS` to create `os_latest.json` + 5. **Build Project** ```bash From 9376e6a757ba2d7b8bf760349a6ad1f7399528fe Mon Sep 17 00:00:00 2001 From: mohiiit Date: Mon, 23 Dec 2024 23:38:11 +0530 Subject: [PATCH 15/17] refactor: event bridge type added --- .env.example | 1 + .env.test | 2 +- README.md | 15 ++++++++---- .../orchestrator/src/cli/cron/event_bridge.rs | 14 +++++++---- crates/orchestrator/src/cli/mod.rs | 23 ++++++------------- crates/orchestrator/src/cron/event_bridge.rs | 2 +- .../atlantic-service/Cargo.toml | 2 +- e2e-tests/Cargo.toml | 2 +- e2e-tests/src/node.rs | 5 ++-- 9 files changed, 34 insertions(+), 32 deletions(-) diff --git a/.env.example b/.env.example index 43b3dc0f..2c7ed8e8 100644 --- a/.env.example +++ b/.env.example @@ -8,6 +8,7 @@ AWS_ENDPOINT_URL= # AWS endpoint URL AWS_DEFAULT_REGION= # AWS default region # For EventBridge +MADARA_ORCHESTRATOR_EVENT_BRIDGE_TYPE= # EventBridge type (rule/schedule) MADARA_ORCHESTRATOR_EVENT_BRIDGE_TRIGGER_RULE_NAME= # EventBridge rule name MADARA_ORCHESTRATOR_EVENT_BRIDGE_TRIGGER_ROLE_NAME= # EventBridge role name MADARA_ORCHESTRATOR_EVENT_BRIDGE_TRIGGER_POLICY_NAME= # EventBridge policy name diff --git a/.env.test b/.env.test index 73d1d6da..95804a57 100644 --- a/.env.test +++ b/.env.test @@ -10,7 +10,7 @@ AWS_ENDPOINT_URL=http://localhost.localstack.cloud:4566 AWS_DEFAULT_REGION=localhost # For EventBridge - +MADARA_ORCHESTRATOR_EVENT_BRIDGE_TYPE=rule MADARA_ORCHESTRATOR_EVENT_BRIDGE_TRIGGER_RULE_NAME=madara-orchestrator-worker-trigger MADARA_ORCHESTRATOR_EVENT_BRIDGE_TRIGGER_ROLE_NAME=madara-orchestrator-worker-trigger-role MADARA_ORCHESTRATOR_EVENT_BRIDGE_TRIGGER_POLICY_NAME=madara-orchestrator-worker-trigger-policy diff --git a/README.md b/README.md index a909adfb..ddc2e429 100644 --- a/README.md +++ b/README.md @@ -311,11 +311,15 @@ Setup mode configures the required AWS services and dependencies. Use the following command: ```bash -cargo run --release --bin orchestrator setup --aws --aws-s3 --aws-sqs --aws-sns --aws-event-bridge-rule +cargo run --release --bin orchestrator setup --aws --aws-s3 --aws-sqs --aws-sns --aws-event-bridge --event-bridge-type rule ``` -Note: Setup mode is currently in development. A fresh setup is required -if the process fails mid-way. +> ๐Ÿšจ **Note**: +> +> - Setup mode is currently in development. A fresh setup is required +> if the process fails mid-way. +> - The `event-bridge-type` needs to be `rule` in case of localstack. +> - The `event-bridge-type` should be `schedule` in case of AWS. ### Run Mode @@ -369,9 +373,10 @@ RUST_LOG=info cargo run --release --bin orchestrator run \ - `--aws-sns`: Notification service -9. **Scheduling**: +9. **Event Bridge Scheduling**: - - `--aws-event-bridge`: Cron job scheduling + - `--aws-event-bridge`: Enable AWS Event Bridge + - `--event-bridge-type`: Specify the type of Event Bridge (rule or schedule) 10. **Monitoring**: - `--otel-service-name`: OpenTelemetry service name diff --git a/crates/orchestrator/src/cli/cron/event_bridge.rs b/crates/orchestrator/src/cli/cron/event_bridge.rs index 88700ce3..0602d36e 100644 --- a/crates/orchestrator/src/cli/cron/event_bridge.rs +++ b/crates/orchestrator/src/cli/cron/event_bridge.rs @@ -1,19 +1,23 @@ use clap::Args; +use crate::cron::event_bridge::EventBridgeType; + /// CLI arguments for the aws event bridge. #[derive(Debug, Clone, Args)] +#[group(requires_all = ["aws_event_bridge"])] pub struct AWSEventBridgeCliArgs { - /// Use the AWS Event Bridge Rule client + /// Use the AWS Event Bridge client #[arg(long)] - pub aws_event_bridge_rule: bool, + pub aws_event_bridge: bool, - /// Use the AWS Event Bridge Schedule client - #[arg(long)] - pub aws_event_bridge_schedule: bool, + /// The type of Event Bridge to use (rule or schedule) + #[arg(env = "MADARA_ORCHESTRATOR_EVENT_BRIDGE_TYPE", long, value_enum)] + pub event_bridge_type: Option, /// The name of the queue for the event bridge #[arg(env = "MADARA_ORCHESTRATOR_EVENT_BRIDGE_TARGET_QUEUE_NAME", long, default_value = Some("madara_orchestrator_worker_trigger_queue"), help = "The name of the SNS queue to send messages to from the event bridge.")] pub target_queue_name: Option, + /// The cron time for the event bridge trigger rule. #[arg(env = "MADARA_ORCHESTRATOR_EVENT_BRIDGE_CRON_TIME", long, default_value = Some("60"), help = "The cron time for the event bridge trigger rule. Defaults to 10 seconds.")] pub cron_time: Option, diff --git a/crates/orchestrator/src/cli/mod.rs b/crates/orchestrator/src/cli/mod.rs index 59816d82..a4307d90 100644 --- a/crates/orchestrator/src/cli/mod.rs +++ b/crates/orchestrator/src/cli/mod.rs @@ -246,7 +246,7 @@ impl RunCmd { ), group( ArgGroup::new("cron") - .args(&["aws_event_bridge_rule", "aws_event_bridge_schedule"]) + .args(&["aws_event_bridge"]) .required(true) .multiple(false) .requires("provider") @@ -336,7 +336,7 @@ pub mod validate_params { use crate::alerts::aws_sns::AWSSNSValidatedArgs; use crate::cli::prover_layout::ProverLayoutCliArgs; use crate::config::ServiceParams; - use crate::cron::event_bridge::{AWSEventBridgeValidatedArgs, EventBridgeType}; + use crate::cron::event_bridge::AWSEventBridgeValidatedArgs; use crate::data_storage::aws_s3::AWSS3ValidatedArgs; use crate::database::mongodb::MongoDBValidatedArgs; use crate::queue::sqs::AWSSQSValidatedArgs; @@ -403,16 +403,8 @@ pub mod validate_params { aws_event_bridge_args: &AWSEventBridgeCliArgs, aws_config_args: &AWSConfigCliArgs, ) -> Result { - if (aws_event_bridge_args.aws_event_bridge_rule || aws_event_bridge_args.aws_event_bridge_schedule) - && aws_config_args.aws - { - let cron_type = if aws_event_bridge_args.aws_event_bridge_rule { - EventBridgeType::Rule - } else if aws_event_bridge_args.aws_event_bridge_schedule { - EventBridgeType::Schedule - } else { - panic!("No Cron service selected!") - }; + if aws_event_bridge_args.aws_event_bridge && aws_config_args.aws { + let cron_type = aws_event_bridge_args.event_bridge_type.clone().expect("Event Bridge type is required"); Ok(CronValidatedArgs::AWSEventBridge(AWSEventBridgeValidatedArgs { cron_type, @@ -432,12 +424,10 @@ pub mod validate_params { .trigger_rule_name .clone() .expect("Trigger rule name is required"), - trigger_role_name: aws_event_bridge_args .trigger_role_name .clone() .expect("Trigger role name is required"), - trigger_policy_name: aws_event_bridge_args .trigger_policy_name .clone() @@ -656,6 +646,7 @@ pub mod validate_params { validate_server_params, validate_service_params, validate_settlement_params, validate_snos_params, validate_storage_params, }; + use crate::cron::event_bridge::EventBridgeType; #[rstest] #[case(true)] @@ -852,8 +843,8 @@ pub mod validate_params { #[case(false)] fn test_validate_cron_params(#[case] is_aws: bool) { let aws_event_bridge_args: AWSEventBridgeCliArgs = AWSEventBridgeCliArgs { - aws_event_bridge_rule: is_aws, - aws_event_bridge_schedule: !is_aws, + aws_event_bridge: is_aws, + event_bridge_type: Some(EventBridgeType::Rule), target_queue_name: Some(String::from("test")), cron_time: Some(String::from("12")), trigger_rule_name: Some(String::from("test")), diff --git a/crates/orchestrator/src/cron/event_bridge.rs b/crates/orchestrator/src/cron/event_bridge.rs index 93811004..bd62f121 100644 --- a/crates/orchestrator/src/cron/event_bridge.rs +++ b/crates/orchestrator/src/cron/event_bridge.rs @@ -12,7 +12,7 @@ use super::{get_worker_trigger_message, TriggerArns}; use crate::cron::Cron; use crate::queue::job_queue::WorkerTriggerType; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, clap::ValueEnum)] pub enum EventBridgeType { Rule, Schedule, diff --git a/crates/prover-clients/atlantic-service/Cargo.toml b/crates/prover-clients/atlantic-service/Cargo.toml index 17881938..707a4380 100644 --- a/crates/prover-clients/atlantic-service/Cargo.toml +++ b/crates/prover-clients/atlantic-service/Cargo.toml @@ -27,8 +27,8 @@ strum = { workspace = true } strum_macros = { workspace = true } tempfile.workspace = true thiserror.workspace = true -tokio.workspace = true tokio-util = { version = "0.7.12", features = ["codec"] } +tokio.workspace = true url.workspace = true utils.workspace = true uuid.workspace = true diff --git a/e2e-tests/Cargo.toml b/e2e-tests/Cargo.toml index 806c572e..c522829b 100644 --- a/e2e-tests/Cargo.toml +++ b/e2e-tests/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -alloy.workspace = true alloy-sol-types.workspace = true +alloy.workspace = true async-trait.workspace = true aws-config.workspace = true aws-sdk-eventbridge.workspace = true diff --git a/e2e-tests/src/node.rs b/e2e-tests/src/node.rs index be7c569b..f1be9de2 100644 --- a/e2e-tests/src/node.rs +++ b/e2e-tests/src/node.rs @@ -74,8 +74,9 @@ impl Orchestrator { command.stdout(Stdio::piped()).stderr(Stdio::piped()); } else { - command.arg("--aws-event-bridge-rule"); - + command.arg("--aws-event-bridge"); + command.arg("--event-bridge-type"); + command.arg("rule"); // For setup mode, inherit the stdio to show output directly command.stdout(Stdio::inherit()).stderr(Stdio::inherit()); } From 752d0a6b6969fe6e278a92f476224a351b34d8b6 Mon Sep 17 00:00:00 2001 From: mohiiit Date: Tue, 24 Dec 2024 00:08:50 +0530 Subject: [PATCH 16/17] chore: linting and formatting of toml files --- crates/prover-clients/atlantic-service/Cargo.toml | 2 +- e2e-tests/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/prover-clients/atlantic-service/Cargo.toml b/crates/prover-clients/atlantic-service/Cargo.toml index 707a4380..17881938 100644 --- a/crates/prover-clients/atlantic-service/Cargo.toml +++ b/crates/prover-clients/atlantic-service/Cargo.toml @@ -27,8 +27,8 @@ strum = { workspace = true } strum_macros = { workspace = true } tempfile.workspace = true thiserror.workspace = true -tokio-util = { version = "0.7.12", features = ["codec"] } tokio.workspace = true +tokio-util = { version = "0.7.12", features = ["codec"] } url.workspace = true utils.workspace = true uuid.workspace = true diff --git a/e2e-tests/Cargo.toml b/e2e-tests/Cargo.toml index c522829b..806c572e 100644 --- a/e2e-tests/Cargo.toml +++ b/e2e-tests/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -alloy-sol-types.workspace = true alloy.workspace = true +alloy-sol-types.workspace = true async-trait.workspace = true aws-config.workspace = true aws-sdk-eventbridge.workspace = true From 5fa2d8106373827cee12c3b173c9d276b5f91004 Mon Sep 17 00:00:00 2001 From: mohiiit Date: Tue, 24 Dec 2024 11:55:16 +0530 Subject: [PATCH 17/17] update: time delay for txn finality in state update increased to 30 mins --- crates/settlement-clients/ethereum/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/settlement-clients/ethereum/src/lib.rs b/crates/settlement-clients/ethereum/src/lib.rs index 55cc3fe9..ce620ae4 100644 --- a/crates/settlement-clients/ethereum/src/lib.rs +++ b/crates/settlement-clients/ethereum/src/lib.rs @@ -49,9 +49,9 @@ const Y_LOW_POINT_OFFSET: usize = 14; const Y_HIGH_POINT_OFFSET: usize = Y_LOW_POINT_OFFSET + 1; // Ethereum Transaction Finality -const MAX_TX_FINALISATION_ATTEMPTS: usize = 100; +const MAX_TX_FINALISATION_ATTEMPTS: usize = 30; const REQUIRED_BLOCK_CONFIRMATIONS: u64 = 3; -const TX_WAIT_SLEEP_DELAY_SECS: u64 = 5; +const TX_WAIT_SLEEP_DELAY_SECS: u64 = 60; lazy_static! { pub static ref PROJECT_ROOT: PathBuf = PathBuf::from(format!("{}/../../../", env!("CARGO_MANIFEST_DIR")));