From b2de746701d2124d1280d762ce93737deda14b14 Mon Sep 17 00:00:00 2001 From: Ratan Kaliani Date: Mon, 26 Aug 2024 11:43:16 -0700 Subject: [PATCH 1/5] fix: operator private key --- script/bin/operator.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/script/bin/operator.rs b/script/bin/operator.rs index 3b7ed81..d4219f5 100644 --- a/script/bin/operator.rs +++ b/script/bin/operator.rs @@ -88,7 +88,12 @@ impl SP1BlobstreamOperator { .parse() .unwrap(); - let private_key = env::var("PRIVATE_KEY").expect("PRIVATE_KEY not set"); + let private_key = if !use_kms_relayer { + env::var("PRIVATE_KEY").expect("PRIVATE_KEY must be set if USE_KMS_RELAYER is false.") + } else { + String::new() + }; + let contract_address = env::var("CONTRACT_ADDRESS") .expect("CONTRACT_ADDRESS not set") .parse() From febb82fc4f05ba407e81442e5258a50f9cc7d7ac Mon Sep 17 00:00:00 2001 From: Ratan Kaliani Date: Mon, 26 Aug 2024 12:05:12 -0700 Subject: [PATCH 2/5] fix --- script/bin/operator.rs | 163 +++++++++++++++++++++++------------------ 1 file changed, 93 insertions(+), 70 deletions(-) diff --git a/script/bin/operator.rs b/script/bin/operator.rs index d4219f5..c8b7cc1 100644 --- a/script/bin/operator.rs +++ b/script/bin/operator.rs @@ -14,6 +14,7 @@ use blobstream_script::util::TendermintRPCClient; use blobstream_script::{relay, TendermintProver}; use log::{error, info}; use primitives::get_header_update_verdict; +use reqwest::Url; use sp1_sdk::{ HashableKey, ProverClient, SP1ProofWithPublicValues, SP1ProvingKey, SP1Stdin, SP1VerifyingKey, }; @@ -36,15 +37,21 @@ type EthereumFillProvider = FillProvider< Ethereum, >; +enum RelayMode { + Kms, + Local, +} + struct SP1BlobstreamOperator { client: ProverClient, pk: SP1ProvingKey, vk: SP1VerifyingKey, - wallet_filler: Arc, + provider: Arc>>, contract_address: Address, - relayer_address: Address, + relayer_address: Option
, chain_id: u64, - use_kms_relayer: bool, + use_kms_relayer: RelayMode, + wallet_filler: Option>, } sol! { @@ -75,52 +82,62 @@ impl SP1BlobstreamOperator { let client = ProverClient::new(); let (pk, vk) = client.setup(ELF); - let use_kms_relayer: bool = env::var("USE_KMS_RELAYER") - .unwrap_or("false".to_string()) - .parse() - .unwrap(); + let use_kms_relayer = + matches!(env::var("USE_KMS_RELAYER").map(|v| v.to_lowercase()), Ok(v) if v == "true"); + let use_kms_relayer = if use_kms_relayer { + RelayMode::Kms + } else { + RelayMode::Local + }; let chain_id: u64 = env::var("CHAIN_ID") .expect("CHAIN_ID not set") .parse() .unwrap(); - let rpc_url = env::var("RPC_URL") + let rpc_url: Url = env::var("RPC_URL") .expect("RPC_URL not set") .parse() .unwrap(); - let private_key = if !use_kms_relayer { - env::var("PRIVATE_KEY").expect("PRIVATE_KEY must be set if USE_KMS_RELAYER is false.") - } else { - String::new() + let provider = Arc::new(ProviderBuilder::new().on_http(rpc_url.clone())); + + let (relayer_address, wallet_filler) = match use_kms_relayer { + RelayMode::Local => { + let private_key = env::var("PRIVATE_KEY") + .expect("PRIVATE_KEY must be set if relay mode is local."); + let signer: PrivateKeySigner = + private_key.parse().expect("Failed to parse private key"); + let relayer_address = signer.address(); + let wallet = EthereumWallet::from(signer); + let wallet_filler = ProviderBuilder::new() + .with_recommended_fillers() + .wallet(wallet) + .on_http(rpc_url.clone()); + (Some(relayer_address), Some(Arc::new(wallet_filler))) + } + RelayMode::Kms => (None, None), }; let contract_address = env::var("CONTRACT_ADDRESS") .expect("CONTRACT_ADDRESS not set") .parse() .unwrap(); - let signer: PrivateKeySigner = private_key.parse().expect("Failed to parse private key"); - let relayer_address = signer.address(); - let wallet = EthereumWallet::from(signer); - let provider = ProviderBuilder::new() - .with_recommended_fillers() - .wallet(wallet) - .on_http(rpc_url); Self { client, pk, vk, - wallet_filler: Arc::new(provider), + provider, chain_id, contract_address, relayer_address, use_kms_relayer, + wallet_filler, } } /// Check the verifying key in the contract matches the verifying key in the prover. async fn check_vkey(&self) -> Result<()> { - let contract = SP1Blobstream::new(self.contract_address, self.wallet_filler.clone()); + let contract = SP1Blobstream::new(self.contract_address, self.provider.clone()); let verifying_key = contract .blobstreamProgramVkey() .call() @@ -174,55 +191,61 @@ impl SP1BlobstreamOperator { proof.bytes() }; - let contract = SP1Blobstream::new(self.contract_address, self.wallet_filler.clone()); - - if self.use_kms_relayer { - let proof_bytes = proof_as_bytes.clone().into(); - let public_values = proof.public_values.to_vec().into(); - let commit_header_range = contract.commitHeaderRange(proof_bytes, public_values); - relay::relay_with_kms( - &relay::KMSRelayRequest { - chain_id: self.chain_id, - address: self.contract_address.to_checksum(None), - calldata: commit_header_range.calldata().to_string(), - platform_request: false, - }, - NUM_RELAY_RETRIES, - ) - .await - } else { - let public_values_bytes = proof.public_values.to_vec(); - - let gas_limit = relay::get_gas_limit(self.chain_id); - let max_fee_per_gas = - relay::get_fee_cap(self.chain_id, self.wallet_filler.root()).await; - - let nonce = self - .wallet_filler - .get_transaction_count(self.relayer_address) - .await?; - - // Wait for 3 required confirmations with a timeout of 60 seconds. - const NUM_CONFIRMATIONS: u64 = 3; - const TIMEOUT_SECONDS: u64 = 60; - let receipt = contract - .commitHeaderRange(proof_as_bytes.into(), public_values_bytes.into()) - .gas_price(max_fee_per_gas) - .gas(gas_limit) - .nonce(nonce) - .send() - .await? - .with_required_confirmations(NUM_CONFIRMATIONS) - .with_timeout(Some(Duration::from_secs(TIMEOUT_SECONDS))) - .get_receipt() - .await?; - - // If status is false, it reverted. - if !receipt.status() { - error!("Transaction reverted!"); + match self.use_kms_relayer { + RelayMode::Kms => { + let contract = SP1Blobstream::new(self.contract_address, self.provider.clone()); + let proof_bytes = proof_as_bytes.clone().into(); + let public_values = proof.public_values.to_vec().into(); + let commit_header_range = contract.commitHeaderRange(proof_bytes, public_values); + relay::relay_with_kms( + &relay::KMSRelayRequest { + chain_id: self.chain_id, + address: self.contract_address.to_checksum(None), + calldata: commit_header_range.calldata().to_string(), + platform_request: false, + }, + NUM_RELAY_RETRIES, + ) + .await + } + RelayMode::Local => { + let public_values_bytes = proof.public_values.to_vec(); + let wallet_filler = self + .wallet_filler + .as_ref() + .expect("Wallet filler should be set for non-KMS relayer"); + let contract = SP1Blobstream::new(self.contract_address, wallet_filler.clone()); + let relayer_address = self + .relayer_address + .expect("Relayer address should be set for non-KMS relayer"); + + let gas_limit = relay::get_gas_limit(self.chain_id); + let max_fee_per_gas = relay::get_fee_cap(self.chain_id, wallet_filler.root()).await; + + let nonce = wallet_filler.get_transaction_count(relayer_address).await?; + + // Wait for 3 required confirmations with a timeout of 60 seconds. + const NUM_CONFIRMATIONS: u64 = 3; + const TIMEOUT_SECONDS: u64 = 60; + let receipt = contract + .commitHeaderRange(proof_as_bytes.into(), public_values_bytes.into()) + .gas_price(max_fee_per_gas) + .gas(gas_limit) + .nonce(nonce) + .send() + .await? + .with_required_confirmations(NUM_CONFIRMATIONS) + .with_timeout(Some(Duration::from_secs(TIMEOUT_SECONDS))) + .get_receipt() + .await?; + + // If status is false, it reverted. + if !receipt.status() { + error!("Transaction reverted!"); + } + + Ok(receipt.transaction_hash) } - - Ok(receipt.transaction_hash) } } @@ -233,7 +256,7 @@ impl SP1BlobstreamOperator { let block_update_interval = get_block_update_interval(); loop { - let contract = SP1Blobstream::new(self.contract_address, self.wallet_filler.clone()); + let contract = SP1Blobstream::new(self.contract_address, self.provider.clone()); // Read the data commitment max from the contract. let data_commitment_max = contract From 54c15f920fddfb8a9a58983e7bfb51eb760c92ee Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 02:04:42 +0000 Subject: [PATCH 3/5] fix: improve PRIVATE_KEY handling and documentation Co-Authored-By: ratan@succinct.xyz --- .env.example | 4 ++-- render.yaml | 7 +++++++ script/bin/operator.rs | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.env.example b/.env.example index ccdf044..c776545 100644 --- a/.env.example +++ b/.env.example @@ -3,10 +3,10 @@ TENDERMINT_RPC_URL=https://rpc.celestia-mocha.com/ CHAIN_ID=11155111 RPC_URL=https://ethereum-sepolia.publicnode.com/ CONTRACT_ADDRESS= -# Key for relaying to the contract. +# Key for relaying to the contract. Required only if USE_KMS_RELAYER is not set to 'true'. PRIVATE_KEY= # If you're using the Succinct network, set SP1_PROVER to "network". Otherwise, set it to "local" or "mock". SP1_PROVER= # Only required if SP1_PROVER is set to "network". -SP1_PRIVATE_KEY= \ No newline at end of file +SP1_PRIVATE_KEY= diff --git a/render.yaml b/render.yaml index faa421d..e963313 100644 --- a/render.yaml +++ b/render.yaml @@ -24,6 +24,7 @@ services: sync: false - key: PRIVATE_KEY sync: false + required: false - key: RPC_URL sync: false - key: SP1_PRIVATE_KEY @@ -53,6 +54,7 @@ services: sync: false - key: PRIVATE_KEY sync: false + required: false - key: RPC_URL sync: false - key: SP1_PRIVATE_KEY @@ -82,6 +84,7 @@ services: sync: false - key: PRIVATE_KEY sync: false + required: false - key: RPC_URL sync: false - key: SP1_PRIVATE_KEY @@ -111,6 +114,7 @@ services: sync: false - key: PRIVATE_KEY sync: false + required: false - key: RPC_URL sync: false - key: SP1_PRIVATE_KEY @@ -138,6 +142,7 @@ services: sync: false - key: PRIVATE_KEY sync: false + required: false - key: RPC_URL sync: false - key: SP1_PRIVATE_KEY @@ -165,6 +170,7 @@ services: sync: false - key: PRIVATE_KEY sync: false + required: false - key: RPC_URL sync: false - key: SP1_PRIVATE_KEY @@ -192,6 +198,7 @@ services: sync: false - key: PRIVATE_KEY sync: false + required: false - key: RPC_URL sync: false - key: SP1_PRIVATE_KEY diff --git a/script/bin/operator.rs b/script/bin/operator.rs index c8b7cc1..cf32cb2 100644 --- a/script/bin/operator.rs +++ b/script/bin/operator.rs @@ -103,9 +103,9 @@ impl SP1BlobstreamOperator { let (relayer_address, wallet_filler) = match use_kms_relayer { RelayMode::Local => { let private_key = env::var("PRIVATE_KEY") - .expect("PRIVATE_KEY must be set if relay mode is local."); + .expect("PRIVATE_KEY environment variable must be set when USE_KMS_RELAYER is not 'true'. Set USE_KMS_RELAYER=true to use KMS relaying instead."); let signer: PrivateKeySigner = - private_key.parse().expect("Failed to parse private key"); + private_key.parse().expect("Failed to parse PRIVATE_KEY - ensure it is a valid Ethereum private key"); let relayer_address = signer.address(); let wallet = EthereumWallet::from(signer); let wallet_filler = ProviderBuilder::new() From d975f76cc48a00d2b9b916172a0fe187829c0eaf Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 02:48:49 +0000 Subject: [PATCH 4/5] style: fix formatting issues in operator.rs Co-Authored-By: ratan@succinct.xyz --- script/bin/operator.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/script/bin/operator.rs b/script/bin/operator.rs index 7d0968f..6eccea5 100644 --- a/script/bin/operator.rs +++ b/script/bin/operator.rs @@ -110,8 +110,7 @@ impl SP1BlobstreamOperator { RelayMode::Local => { let private_key = env::var("PRIVATE_KEY") .expect("PRIVATE_KEY environment variable must be set when USE_KMS_RELAYER is not 'true'. Set USE_KMS_RELAYER=true to use KMS relaying instead."); - let signer: PrivateKeySigner = - private_key.parse().expect("Failed to parse PRIVATE_KEY - ensure it is a valid Ethereum private key"); + let signer: PrivateKeySigner = private_key.parse().expect("Failed to parse PRIVATE_KEY - ensure it is a valid Ethereum private key"); let relayer_address = signer.address(); let wallet = EthereumWallet::from(signer); let wallet_filler = ProviderBuilder::new() @@ -262,14 +261,16 @@ impl SP1BlobstreamOperator { let block_update_interval = get_block_update_interval(); let contract = match self.use_kms_relayer { - RelayMode::Kms => { - SP1Blobstream::new(self.contract_address, self.provider.clone()) - }, + RelayMode::Kms => SP1Blobstream::new(self.contract_address, self.provider.clone()), RelayMode::Local => { - let wallet_filler = self.wallet_filler + let wallet_filler = self + .wallet_filler .as_ref() .expect("Wallet filler should be set for local mode"); - SP1Blobstream::new(self.contract_address, Arc::new(wallet_filler.root().clone())) + SP1Blobstream::new( + self.contract_address, + Arc::new(wallet_filler.root().clone()), + ) } }; let data_commitment_max = contract From 95aa4ec159e362b4f94087e2b0d93e81f5fb345d Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 02:52:38 +0000 Subject: [PATCH 5/5] style: update signer initialization formatting Co-Authored-By: ratan@succinct.xyz --- script/bin/operator.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/script/bin/operator.rs b/script/bin/operator.rs index 6eccea5..f9f91ad 100644 --- a/script/bin/operator.rs +++ b/script/bin/operator.rs @@ -110,7 +110,9 @@ impl SP1BlobstreamOperator { RelayMode::Local => { let private_key = env::var("PRIVATE_KEY") .expect("PRIVATE_KEY environment variable must be set when USE_KMS_RELAYER is not 'true'. Set USE_KMS_RELAYER=true to use KMS relaying instead."); - let signer: PrivateKeySigner = private_key.parse().expect("Failed to parse PRIVATE_KEY - ensure it is a valid Ethereum private key"); + let signer: PrivateKeySigner = private_key.parse().expect( + "Failed to parse PRIVATE_KEY - ensure it is a valid Ethereum private key", + ); let relayer_address = signer.address(); let wallet = EthereumWallet::from(signer); let wallet_filler = ProviderBuilder::new()