diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d15d12d09e..c073c238a1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -83,6 +83,7 @@ jobs: target/release/marketplace-solver target/release/marketplace-builder target/release/node-metrics + target/release/dev-rollup build-arm: runs-on: buildjet-4vcpu-ubuntu-2204-arm @@ -137,6 +138,7 @@ jobs: target/release/marketplace-solver target/release/marketplace-builder target/release/node-metrics + target/release/dev-rollup build-dockers: runs-on: ubuntu-latest @@ -159,6 +161,7 @@ jobs: marketplace-solver-tag: ${{ steps.marketplace-solver.outputs.tags }} marketplace-builder-tag: ${{ steps.marketplace-builder.outputs.tags }} node-validator-tag: ${{ steps.node-validator.outputs.tags }} + dev-rollup-tag: ${{ steps.dev-rollup.outputs.tags }} steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -290,6 +293,13 @@ jobs: with: images: ghcr.io/espressosystems/espresso-sequencer/node-validator + - name: Generate dev-rollup metadata + uses: docker/metadata-action@v5 + id: dev-rollup + with: + images: ghcr.io/espressosystems/espresso-sequencer/dev-rollup + + - name: Build and push sequencer docker uses: docker/build-push-action@v6 with: @@ -459,6 +469,16 @@ jobs: tags: ${{ steps.node-validator.outputs.tags }} labels: ${{ steps.node-validator.outputs.labels }} + - name: Build and push dev-rollup docker + uses: docker/build-push-action@v6 + with: + context: ./ + file: ./docker/dev-rollup.Dockerfile + platforms: linux/amd64,linux/arm64 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.dev-rollup.outputs.tags }} + labels: ${{ steps.dev-rollup.outputs.labels }} + test-demo: if: ${{ github.event_name != 'pull_request' }} runs-on: ubuntu-latest @@ -490,6 +510,7 @@ jobs: docker pull ${{ needs.build-dockers.outputs.marketplace-solver-tag }} docker pull ${{ needs.build-dockers.outputs.marketplace-builder-tag }} docker pull ${{ needs.build-dockers.outputs.node-validator-tag }} + docker pull ${{ needs.build-dockers.outputs.dev-rollup-tag }} - name: Tag new docker images run: | @@ -509,6 +530,7 @@ jobs: docker tag ${{ needs.build-dockers.outputs.marketplace-solver-tag }} ghcr.io/espressosystems/espresso-sequencer/marketplace-solver:main docker tag ${{ needs.build-dockers.outputs.marketplace-builder-tag }} ghcr.io/espressosystems/espresso-sequencer/marketplace-builder:main docker tag ${{ needs.build-dockers.outputs.node-validator-tag }} ghcr.io/espressosystems/espresso-sequencer/node-validator:main + docker tag ${{ needs.build-dockers.outputs.dev-rollup-tag }} ghcr.io/espressosystems/espresso-sequencer/dev-rollup:main - name: Test docker demo run: | diff --git a/.github/workflows/build_static.yml b/.github/workflows/build_static.yml index f60232976d..54343f1e2b 100644 --- a/.github/workflows/build_static.yml +++ b/.github/workflows/build_static.yml @@ -94,6 +94,7 @@ jobs: ${{ env.CARGO_TARGET_DIR }}/${{ env.TARGET_TRIPLET }}/release/marketplace-solver ${{ env.CARGO_TARGET_DIR }}/${{ env.TARGET_TRIPLET }}/release/marketplace-builder ${{ env.CARGO_TARGET_DIR }}/${{ env.TARGET_TRIPLET }}/release/node-metrics + ${{ env.CARGO_TARGET_DIR }}/${{ env.TARGET_TRIPLET }}/release/dev-rollup static-dockers: runs-on: ubuntu-latest needs: static-build @@ -229,6 +230,13 @@ jobs: with: images: ghcr.io/espressosystems/espresso-sequencer/node-validator flavor: suffix=musl + + - name: Generate dev-rollup metadata + uses: docker/metadata-action@v5 + id: dev-rollup + with: + images: ghcr.io/espressosystems/espresso-sequencer/dev-rollup + flavor: suffix=musl - name: Build and push sequencer docker uses: docker/build-push-action@v6 @@ -378,4 +386,14 @@ jobs: platforms: linux/amd64,linux/arm64 push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.node-validator.outputs.tags }} - labels: ${{ steps.node-validator.outputs.labels }} \ No newline at end of file + labels: ${{ steps.node-validator.outputs.labels }} + + - name: Build and push dev-rollup docker + uses: docker/build-push-action@v6 + with: + context: ./ + file: ./docker/dev-rollup.Dockerfile + platforms: linux/amd64,linux/arm64 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.dev-rollup.outputs.tags }} + labels: ${{ steps.dev-rollup.outputs.labels }} \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 495525e71f..b2ed518beb 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -542,7 +542,7 @@ services: profiles: [marketplace] environment: - ESPRESSO_MARKETPLACE_BUILDER_IS_RESERVE=true - - ESPRESSO_MARKETPLACE_BUILDER_SOLVER_URL=http://localhost:$ESPRESSO_MARKETPLACE_SOLVER_API_PORT + - ESPRESSO_MARKETPLACE_SOLVER_API_URL=http://localhost:$ESPRESSO_MARKETPLACE_SOLVER_API_PORT - ESPRESSO_MARKETPLACE_BUILDER_NAMESPACE=10000 - ESPRESSO_SEQUENCER_HOTSHOT_EVENT_STREAMING_API_URL=http://sequencer0:$ESPRESSO_SEQUENCER_HOTSHOT_EVENT_STREAMING_API_PORT - ESPRESSO_SEQUENCER_STATE_PEERS=http://sequencer0:$ESPRESSO_SEQUENCER_API_PORT @@ -574,7 +574,7 @@ services: environment: - ESPRESSO_BUILDER_SERVER_PORT=$ESPRESSO_FALLBACK_BUILDER_SERVER_PORT - ESPRESSO_MARKETPLACE_BUILDER_IS_RESERVE=false - - ESPRESSO_MARKETPLACE_BUILDER_SOLVER_URL=http://localhost:$ESPRESSO_MARKETPLACE_SOLVER_API_PORT + - ESPRESSO_MARKETPLACE_SOLVER_API_URL=http://localhost:$ESPRESSO_MARKETPLACE_SOLVER_API_PORT - ESPRESSO_MARKETPLACE_BUILDER_NAMESPACE=10000 - ESPRESSO_SEQUENCER_HOTSHOT_EVENT_STREAMING_API_URL=http://sequencer0:$ESPRESSO_SEQUENCER_HOTSHOT_EVENT_STREAMING_API_PORT - ESPRESSO_SEQUENCER_STATE_PEERS=http://sequencer0:$ESPRESSO_SEQUENCER_API_PORT @@ -741,3 +741,13 @@ services: depends_on: sequencer1: condition: service_healthy + + dev-rollup: + image: ghcr.io/espressosystems/dev-rollup:main + command: + dev-rollup register --ns 1; dev-rollup register --ns 2; dev-rollup register --ns 3 + environment: + - ESPRESSO_MARKETPLACE_SOLVER_API_URL=http://marketplace-solver:$ESPRESSO_MARKETPLACE_SOLVER_API_PORT + depends_on: + sequencer1: + condition: service_healthy diff --git a/docker/dev-rollup.Dockerfile b/docker/dev-rollup.Dockerfile new file mode 100644 index 0000000000..337c482bcf --- /dev/null +++ b/docker/dev-rollup.Dockerfile @@ -0,0 +1,13 @@ +FROM ubuntu:jammy + +ARG TARGETARCH + +RUN apt-get update \ + && apt-get install -y curl libcurl4 wait-for-it tini \ + && rm -rf /var/lib/apt/lists/* +ENTRYPOINT ["tini", "--"] + +COPY target/$TARGETARCH/release/dev-rollup /bin/dev-rollup +RUN chmod +x /bin/dev-rollup + +CMD [ "/bin/dev-rollup"] diff --git a/marketplace-builder/src/bin/marketplace-builder.rs b/marketplace-builder/src/bin/marketplace-builder.rs index 2adfbdb5ff..f92c2d3b18 100644 --- a/marketplace-builder/src/bin/marketplace-builder.rs +++ b/marketplace-builder/src/bin/marketplace-builder.rs @@ -105,7 +105,7 @@ struct NonPermissionedBuilderOptions { pub namespaces: Vec, /// Url we will use to communicate to solver - #[clap(long, env = "ESPRESSO_MARKETPLACE_BUILDER_SOLVER_URL")] + #[clap(long, env = "ESPRESSO_MARKETPLACE_SOLVER_API_URL")] solver_url: Url, /// Bid amount in WEI. diff --git a/process-compose.yaml b/process-compose.yaml index afac841f2c..be0c193472 100644 --- a/process-compose.yaml +++ b/process-compose.yaml @@ -497,7 +497,7 @@ processes: - "$ESPRESSO_BUILDER_SERVER_PORT:$ESPRESSO_BUILDER_SERVER_PORT" environment: - ESPRESSO_MARKETPLACE_BUILDER_IS_RESERVE=true - - ESPRESSO_MARKETPLACE_BUILDER_SOLVER_URL=http://localhost:$ESPRESSO_MARKETPLACE_SOLVER_API_PORT + - ESPRESSO_MARKETPLACE_SOLVER_API_URL=http://localhost:$ESPRESSO_MARKETPLACE_SOLVER_API_PORT - ESPRESSO_MARKETPLACE_BUILDER_NAMESPACE=10000 - ESPRESSO_SEQUENCER_STATE_PEERS=http://localhost:$ESPRESSO_SEQUENCER_API_PORT - ESPRESSO_SEQUENCER_HOTSHOT_EVENT_STREAMING_API_URL=http://localhost:$ESPRESSO_SEQUENCER_HOTSHOT_EVENT_STREAMING_API_PORT @@ -523,7 +523,7 @@ processes: environment: - ESPRESSO_BUILDER_SERVER_PORT=$ESPRESSO_FALLBACK_BUILDER_SERVER_PORT - ESPRESSO_MARKETPLACE_BUILDER_IS_RESERVE=false - - ESPRESSO_MARKETPLACE_BUILDER_SOLVER_URL=http://localhost:$ESPRESSO_MARKETPLACE_SOLVER_API_PORT + - ESPRESSO_MARKETPLACE_SOLVER_API_URL=http://localhost:$ESPRESSO_MARKETPLACE_SOLVER_API_PORT - ESPRESSO_MARKETPLACE_BUILDER_NAMESPACE=10000 - ESPRESSO_SEQUENCER_STATE_PEERS=http://localhost:$ESPRESSO_SEQUENCER_API_PORT - ESPRESSO_SEQUENCER_HOTSHOT_EVENT_STREAMING_API_URL=http://localhost:$ESPRESSO_SEQUENCER_HOTSHOT_EVENT_STREAMING_API_PORT @@ -662,3 +662,12 @@ processes: depends_on: sequencer1: condition: process_healthy + + dev-rollup: + command: + dev-rollup register --ns 1; dev-rollup register --ns 2; dev-rollup register --ns 3 + environment: + - ESPRESSO_MARKETPLACE_SOLVER_API_URL=http://localhost:$ESPRESSO_MARKETPLACE_SOLVER_API_PORT + depends_on: + marketplace-solver: + condition: process_healthy diff --git a/scripts/build-docker-images b/scripts/build-docker-images index 8591c946ab..f2512c751c 100755 --- a/scripts/build-docker-images +++ b/scripts/build-docker-images @@ -35,7 +35,7 @@ for ARCH in "amd64" "arm64"; do ;; esac mkdir -p ${WORKDIR}/target/$ARCH/release - for binary in "orchestrator" "cdn-broker" "cdn-marshal" "cdn-whitelist" "sequencer" "commitment-task" "submit-transactions" "reset-storage" "state-relay-server" "state-prover" "deploy" "keygen" "permissionless-builder" "nasty-client" "pub-key" "espresso-bridge" "espresso-dev-node" "marketplace-solver" "marketplace-builder"; do + for binary in "orchestrator" "cdn-broker" "cdn-marshal" "cdn-whitelist" "sequencer" "commitment-task" "submit-transactions" "reset-storage" "state-relay-server" "state-prover" "deploy" "keygen" "permissionless-builder" "nasty-client" "pub-key" "espresso-bridge" "espresso-dev-node" "marketplace-solver" "marketplace-builder" "dev-rollup"; do cp -v "${CARGO_TARGET_DIR}/${TARGET}/release/$binary" ${WORKDIR}/target/$ARCH/release done done @@ -64,4 +64,5 @@ docker build -t ghcr.io/espressosystems/espresso-sequencer/espresso-dev-node:mai docker build -t ghcr.io/espressosystems/espresso-sequencer/bridge:main -f docker/espresso-bridge.Dockerfile ${WORKDIR} docker build -t ghcr.io/espressosystems/espresso-sequencer/marketplace-solver:main -f docker/marketplace-solver.Dockerfile ${WORKDIR} docker build -t ghcr.io/espressosystems/espresso-sequencer/marketplace-builder:main -f docker/marketplace-builder.Dockerfile ${WORKDIR} -docker build -t ghcr.io/espressosystems/espresso-sequencer/node-validator:main -f docker/node-validator.Dockerfile ${WORKDIR} \ No newline at end of file +docker build -t ghcr.io/espressosystems/espresso-sequencer/node-validator:main -f docker/node-validator.Dockerfile ${WORKDIR} +docker build -t ghcr.io/espressosystems/espresso-sequencer/dev-rollup:main -f docker/dev-rollup.Dockerfile ${WORKDIR} \ No newline at end of file diff --git a/scripts/build-docker-images-native b/scripts/build-docker-images-native index 8ac2b6f1c8..a2d9e1ef7a 100755 --- a/scripts/build-docker-images-native +++ b/scripts/build-docker-images-native @@ -87,7 +87,7 @@ mkdir -p ${WORKDIR}/data cp -rv data/genesis ${WORKDIR}/data/ mkdir -p "${WORKDIR}/target/$ARCH/release" -for binary in "orchestrator" "cdn-broker" "cdn-marshal" "cdn-whitelist" "sequencer" "commitment-task" "submit-transactions" "reset-storage" "state-relay-server" "state-prover" "deploy" "keygen" "permissionless-builder" "nasty-client" "pub-key" "espresso-bridge" "espresso-dev-node" "marketplace-solver" "marketplace-builder"; do +for binary in "orchestrator" "cdn-broker" "cdn-marshal" "cdn-whitelist" "sequencer" "commitment-task" "submit-transactions" "reset-storage" "state-relay-server" "state-prover" "deploy" "keygen" "permissionless-builder" "nasty-client" "pub-key" "espresso-bridge" "espresso-dev-node" "marketplace-solver" "marketplace-builder" "dev-rollup"; do cp -v "${CARGO_TARGET_DIR}/release/$binary" "${WORKDIR}/target/$ARCH/release" # Patch the interpreter for running without nix inside the ubuntu based docker image. if [ $KERNEL == "linux" ]; then @@ -120,3 +120,4 @@ docker build --platform $PLATFORM -t ghcr.io/espressosystems/espresso-sequencer/ docker build --platform $PLATFORM -t ghcr.io/espressosystems/espresso-sequencer/marketplace-solver:main -f docker/marketplace-solver.Dockerfile ${WORKDIR} docker build --platform $PLATFORM -t ghcr.io/espressosystems/espresso-sequencer/marketplace-builder:main -f docker/marketplace-builder.Dockerfile ${WORKDIR} docker build --platform $PLATFORM -t ghcr.io/espressosystems/espresso-sequencer/node-validator:main -f docker/node-validator.Dockerfile ${WORKDIR} +docker build --platform $PLATFORM -t ghcr.io/espressosystems/espresso-sequencer/dev-rollup:main -f docker/dev-rollup.Dockerfile ${WORKDIR} diff --git a/sequencer/src/bin/dev-rollup.rs b/sequencer/src/bin/dev-rollup.rs new file mode 100644 index 0000000000..f9c43619a0 --- /dev/null +++ b/sequencer/src/bin/dev-rollup.rs @@ -0,0 +1,216 @@ +use std::str::FromStr; + +use anyhow::Result; +use clap::{Parser, Subcommand}; +use committable::Committable; +use espresso_types::{ + v0_3::{RollupRegistration, RollupRegistrationBody, RollupUpdate, RollupUpdatebody}, + SeqTypes, +}; +use hotshot::types::BLSPubKey; +use hotshot_types::traits::{node_implementation::NodeType, signature_key::SignatureKey}; +use marketplace_solver::SolverError; + +use sequencer_utils::logging; +use url::Url; +use vbs::version::StaticVersion; + +#[derive(Debug, Parser)] +struct Options { + #[clap(flatten)] + logging: logging::Config, + + #[command(subcommand)] + command: Command, +} + +#[derive(Debug, Subcommand)] +enum Command { + Register(Register), + Update(Update), +} + +// Options for registering a rollup +#[derive(Parser, Debug)] +struct Register { + #[clap(short, long, env = "ESPRESSO_MARKETPLACE_SOLVER_API_URL")] + pub solver_url: Url, + + #[clap(short, long = "ns")] + pub namespace_id: u64, + + #[clap( + long, + env = "ESPRESSO_MARKETPLACE_RESERVE_BUILDER_URL", + default_value_t = Url::from_str("http://localhost").unwrap() + )] + pub reserve_url: Url, + + #[clap(long, default_value_t = 200)] + pub reserve_price: u64, + + #[clap(long, default_value_t = false)] + pub active: bool, + + #[clap(long, default_value = "test")] + pub text: String, + + /// The private key is provided in tagged-base64 format. + /// If not provided, a default private key with a seed of `[0; 32]` and an index of `9876` will be used. + #[clap(long = "privkey")] + pub private_key: Option, +} + +// Options for updating an already registered rollup +#[derive(Parser, Debug)] +struct Update { + #[clap(short, long, env = "ESPRESSO_MARKETPLACE_SOLVER_API_URL")] + pub solver_url: Url, + + #[clap(short, long = "ns")] + pub namespace_id: u64, + + #[clap(long, env = "ESPRESSO_MARKETPLACE_RESERVE_BUILDER_URL")] + pub reserve_url: Option, + + #[clap(long)] + pub reserve_price: Option, + + #[clap(long)] + pub active: Option, + + #[clap(long, default_value = "test")] + pub text: Option, + + /// The private key is provided in tagged-base64 format. + /// If not provided, a default private key with a seed of `[0; 32]` and an index of `9876` will be used. + #[clap(long = "privkey")] + pub private_key: Option, +} + +#[async_std::main] +async fn main() -> anyhow::Result<()> { + let opt = Options::parse(); + opt.logging.init(); + + match opt.command { + Command::Register(opt) => register(opt).await, + Command::Update(opt) => update(opt).await, + } +} + +async fn register(opt: Register) -> Result<()> { + let Register { + solver_url, + namespace_id, + reserve_url, + reserve_price, + active, + text, + private_key, + } = opt; + + let client = surf_disco::Client::>::new( + solver_url.join("marketplace-solver").unwrap(), + ); + + let (pubkey, privkey) = if let Some(privkey) = private_key { + let privkey = ::PrivateKey::from_str(&privkey) + .expect("invalid private key provided"); + let pubkey = BLSPubKey::from_private(&privkey); + + (pubkey, privkey) + } else { + BLSPubKey::generated_from_seed_indexed([0; 32], 9876) + }; + + let reg_body = RollupRegistrationBody { + namespace_id: namespace_id.into(), + reserve_url: reserve_url.clone(), + reserve_price: reserve_price.into(), + active, + signature_keys: vec![pubkey], + text, + signature_key: pubkey, + }; + + // Sign the registration body + let signature = + ::SignatureKey::sign(&privkey, reg_body.commit().as_ref()) + .expect("failed to sign"); + + let reg = RollupRegistration { + body: reg_body.clone(), + signature, + }; + + // registering a rollup + client + .post::("register_rollup") + .body_json(®) + .unwrap() + .send() + .await + .unwrap(); + + tracing::info!("rollup with namespace {namespace_id} registered"); + + Ok(()) +} + +async fn update(opt: Update) -> Result<()> { + let Update { + solver_url, + namespace_id, + reserve_url, + reserve_price, + active, + text, + private_key, + } = opt; + + let client = surf_disco::Client::>::new( + solver_url.join("marketplace-solver").unwrap(), + ); + let (pubkey, privkey) = if let Some(privkey) = private_key { + let privkey = ::PrivateKey::from_str(&privkey) + .expect("invalid private key provided"); + let pubkey = BLSPubKey::from_private(&privkey); + + (pubkey, privkey) + } else { + BLSPubKey::generated_from_seed_indexed([0; 32], 9876) + }; + + let body = RollupUpdatebody { + namespace_id: namespace_id.into(), + reserve_url, + reserve_price: reserve_price.map(Into::into), + active, + signature_keys: None, + signature_key: pubkey, + text, + }; + + // Sign the rollup update body + let signature = ::SignatureKey::sign(&privkey, body.commit().as_ref()) + .expect("failed to sign"); + + let update = RollupUpdate { + body: body.clone(), + signature, + }; + + // update a rollup + client + .post::("register_rollup") + .body_json(&update) + .unwrap() + .send() + .await + .unwrap(); + + tracing::info!("rollup with namespace {namespace_id} updated"); + + Ok(()) +}