From eea43ce90d3a610cf622069a9cc40836852a92ee Mon Sep 17 00:00:00 2001 From: Urix <43704209+uri-99@users.noreply.github.com> Date: Mon, 30 Dec 2024 14:26:50 -0300 Subject: [PATCH 1/7] fix: enable sending to holesky --- batcher/aligned-task-sender/src/commands.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/batcher/aligned-task-sender/src/commands.rs b/batcher/aligned-task-sender/src/commands.rs index f074b9156..a51258a26 100644 --- a/batcher/aligned-task-sender/src/commands.rs +++ b/batcher/aligned-task-sender/src/commands.rs @@ -250,11 +250,6 @@ struct Sender { } pub async fn send_infinite_proofs(args: SendInfiniteProofsArgs) { - if matches!(args.network.into(), Network::Holesky) { - error!("Network not supported this infinite proof sender"); - return; - } - info!("Loading wallets"); let mut senders = vec![]; let Ok(eth_rpc_provider) = Provider::::try_from(args.eth_rpc_url.clone()) else { @@ -373,6 +368,8 @@ pub async fn send_infinite_proofs(args: SendInfiniteProofsArgs) { } info!("All responses received for sender {}", i); + info!("Sleeping for {} seconds, before submitting another burst of proofs", args.burst_time_secs); + tokio::time::sleep(Duration::from_secs(args.burst_time_secs)).await; } }); From 756f5635f288ad3fcc435a4257c607a2ffc426da Mon Sep 17 00:00:00 2001 From: Urix <43704209+uri-99@users.noreply.github.com> Date: Mon, 30 Dec 2024 14:26:57 -0300 Subject: [PATCH 2/7] feat: add task_sender_send_infinite_proofs_holesky --- Makefile | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Makefile b/Makefile index 84647c96d..9f9631e90 100644 --- a/Makefile +++ b/Makefile @@ -525,6 +525,18 @@ task_sender_test_connections_holesky_stage: --batcher-url wss://stage.batcher.alignedlayer.com \ --num-senders $(NUM_SENDERS) +# ===== HOLESKY ===== +task_sender_send_infinite_proofs_holesky: + @cd batcher/aligned-task-sender && \ + cargo run --release -- send-infinite-proofs \ + --burst-size $(BURST_SIZE) --burst-time-secs $(BURST_TIME_SECS) \ + --max-fee $(MAX_FEE) \ + --eth-rpc-url https://ethereum-holesky-rpc.publicnode.com \ + --batcher-url wss://batcher.alignedlayer.com \ + --network holesky \ + --proofs-dirpath $(CURDIR)/scripts/test_files/task_sender/proofs \ + --private-keys-filepath $(CURDIR)/batcher/aligned-task-sender/wallets/holesky + __UTILS__: aligned_get_user_balance_devnet: @cd batcher/aligned/ && cargo run --release -- get-user-balance \ From bb077819653c846addb34d680d225c704044715f Mon Sep 17 00:00:00 2001 From: Urix <43704209+uri-99@users.noreply.github.com> Date: Mon, 30 Dec 2024 14:27:17 -0300 Subject: [PATCH 3/7] feat(wip): add min_batch_len. missing read from config file --- batcher/aligned-batcher/src/types/batch_queue.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/batcher/aligned-batcher/src/types/batch_queue.rs b/batcher/aligned-batcher/src/types/batch_queue.rs index 17918e7a2..8539d1cbb 100644 --- a/batcher/aligned-batcher/src/types/batch_queue.rs +++ b/batcher/aligned-batcher/src/types/batch_queue.rs @@ -160,6 +160,7 @@ pub(crate) fn try_build_batch( if batch_size > max_batch_byte_size || fee_per_proof > entry.nonced_verification_data.max_fee || batch_len > max_batch_proof_qty + || batch_len < 1000 { // Update the state for the next iteration: // * Subtract this entry size to the size of the batch size. From 48387b033898fbe8c2d5526402c16122f95b6b3b Mon Sep 17 00:00:00 2001 From: Urix <43704209+uri-99@users.noreply.github.com> Date: Mon, 30 Dec 2024 15:32:04 -0300 Subject: [PATCH 4/7] feat: read min_batch_size from config + unit tests --- batcher/aligned-batcher/src/config/mod.rs | 1 + batcher/aligned-batcher/src/lib.rs | 3 + .../aligned-batcher/src/types/batch_queue.rs | 292 +++++++++++++++++- 3 files changed, 291 insertions(+), 5 deletions(-) diff --git a/batcher/aligned-batcher/src/config/mod.rs b/batcher/aligned-batcher/src/config/mod.rs index 3a6f01e34..e6e7ba312 100644 --- a/batcher/aligned-batcher/src/config/mod.rs +++ b/batcher/aligned-batcher/src/config/mod.rs @@ -42,6 +42,7 @@ pub struct BatcherConfigFromYaml { pub max_proof_size: usize, pub max_batch_byte_size: usize, pub max_batch_proof_qty: usize, + pub min_batch_proof_qty: usize, pub pre_verification_is_enabled: bool, pub metrics_port: u16, pub telemetry_ip_port_address: String, diff --git a/batcher/aligned-batcher/src/lib.rs b/batcher/aligned-batcher/src/lib.rs index 365f22421..fc4c475d9 100644 --- a/batcher/aligned-batcher/src/lib.rs +++ b/batcher/aligned-batcher/src/lib.rs @@ -86,6 +86,7 @@ pub struct Batcher { max_proof_size: usize, max_batch_byte_size: usize, max_batch_proof_qty: usize, + min_batch_proof_qty: usize, last_uploaded_batch_block: Mutex, pre_verification_is_enabled: bool, non_paying_config: Option, @@ -249,6 +250,7 @@ impl Batcher { max_proof_size: config.batcher.max_proof_size, max_batch_byte_size: config.batcher.max_batch_byte_size, max_batch_proof_qty: config.batcher.max_batch_proof_qty, + min_batch_proof_qty: config.batcher.min_batch_proof_qty, last_uploaded_batch_block: Mutex::new(last_uploaded_batch_block), pre_verification_is_enabled: config.batcher.pre_verification_is_enabled, non_paying_config, @@ -1157,6 +1159,7 @@ impl Batcher { gas_price, self.max_batch_byte_size, self.max_batch_proof_qty, + self.min_batch_proof_qty, ) .inspect_err(|e| { *batch_posting = false; diff --git a/batcher/aligned-batcher/src/types/batch_queue.rs b/batcher/aligned-batcher/src/types/batch_queue.rs index 8539d1cbb..c45bfb04e 100644 --- a/batcher/aligned-batcher/src/types/batch_queue.rs +++ b/batcher/aligned-batcher/src/types/batch_queue.rs @@ -148,6 +148,7 @@ pub(crate) fn try_build_batch( gas_price: U256, max_batch_byte_size: usize, max_batch_proof_qty: usize, + min_batch_proof_qty: usize, ) -> Result<(BatchQueue, Vec), BatcherError> { let mut batch_queue = batch_queue; let mut batch_size = calculate_batch_size(&batch_queue)?; @@ -160,7 +161,7 @@ pub(crate) fn try_build_batch( if batch_size > max_batch_byte_size || fee_per_proof > entry.nonced_verification_data.max_fee || batch_len > max_batch_proof_qty - || batch_len < 1000 + || batch_len < min_batch_proof_qty { // Update the state for the next iteration: // * Subtract this entry size to the size of the batch size. @@ -303,7 +304,7 @@ mod test { let gas_price = U256::from(1); let (resulting_batch_queue, batch) = - try_build_batch(batch_queue, gas_price, 5000000, 50).unwrap(); + try_build_batch(batch_queue, gas_price, 5000000, 50, 1).unwrap(); assert!(resulting_batch_queue.is_empty()); @@ -406,7 +407,7 @@ mod test { let gas_price = U256::from(1); let (resulting_batch_queue, finalized_batch) = - try_build_batch(batch_queue, gas_price, 5000000, 50).unwrap(); + try_build_batch(batch_queue, gas_price, 5000000, 50, 1).unwrap(); // The resulting batch queue (entries from the old batch queue that were not willing to pay // in this batch), should be empty and hence, all entries from the batch queue should be in @@ -517,7 +518,7 @@ mod test { let gas_price = U256::from(1); let (resulting_batch_queue, finalized_batch) = - try_build_batch(batch_queue, gas_price, 5000000, 50).unwrap(); + try_build_batch(batch_queue, gas_price, 5000000, 50, 1).unwrap(); // The resulting batch queue (entries from the old batch queue that were not willing to pay // in this batch), should be empty and hence, all entries from the batch queue should be in @@ -630,7 +631,7 @@ mod test { let max_batch_proof_qty = 2; let (resulting_batch_queue, finalized_batch) = - try_build_batch(batch_queue, gas_price, 5000000, max_batch_proof_qty).unwrap(); + try_build_batch(batch_queue, gas_price, 5000000, max_batch_proof_qty, 1).unwrap(); assert_eq!(resulting_batch_queue.len(), 1); assert_eq!(finalized_batch.len(), 2); @@ -643,4 +644,285 @@ mod test { max_fee_1 ); } + + #[test] + fn batch_finalization_algorithm_works_not_smaller_than_min_batch_proof_qty() { + // The following information will be the same for each entry, it is just some dummy data to see + // algorithm working. + + let proof_generator_addr = Address::random(); + let payment_service_addr = Address::random(); + let sender_addr = Address::random(); + let bytes_for_verification_data = vec![42_u8; 10]; + let dummy_signature = Signature { + r: U256::from(1), + s: U256::from(2), + v: 3, + }; + let verification_data = VerificationData { + proving_system: ProvingSystemId::Risc0, + proof: bytes_for_verification_data.clone(), + pub_input: Some(bytes_for_verification_data.clone()), + verification_key: Some(bytes_for_verification_data.clone()), + vm_program_code: Some(bytes_for_verification_data), + proof_generator_addr, + }; + let chain_id = U256::from(42); + + // Here we create different entries for the batch queue. + // Since we are sending with the same address, the low nonces should have higher max fees. + + // Entry 1 + let nonce_1 = U256::from(1); + let max_fee_1 = U256::from(1_300_000_000_000_002u128); + let nonced_verification_data_1 = NoncedVerificationData::new( + verification_data.clone(), + nonce_1, + max_fee_1, + chain_id, + payment_service_addr, + ); + let vd_commitment_1: VerificationDataCommitment = nonced_verification_data_1.clone().into(); + let entry_1 = BatchQueueEntry::new_for_testing( + nonced_verification_data_1, + vd_commitment_1, + dummy_signature, + sender_addr, + ); + let batch_priority_1 = BatchQueueEntryPriority::new(max_fee_1, nonce_1); + + // Entry 2 + let nonce_2 = U256::from(2); + let max_fee_2 = U256::from(1_300_000_000_000_001u128); + let nonced_verification_data_2 = NoncedVerificationData::new( + verification_data.clone(), + nonce_2, + max_fee_2, + chain_id, + payment_service_addr, + ); + let vd_commitment_2: VerificationDataCommitment = nonced_verification_data_2.clone().into(); + let entry_2 = BatchQueueEntry::new_for_testing( + nonced_verification_data_2, + vd_commitment_2, + dummy_signature, + sender_addr, + ); + let batch_priority_2 = BatchQueueEntryPriority::new(max_fee_2, nonce_2); + + let mut batch_queue = BatchQueue::new(); + batch_queue.push(entry_1, batch_priority_1); + batch_queue.push(entry_2, batch_priority_2); + + let gas_price = U256::from(1); + + // The min batch len is 3, so the algorithm should not build a batch of size 2. + let min_batch_proof_qty = 3; + + let should_not_build = + try_build_batch(batch_queue, gas_price, 5000000, 1000, min_batch_proof_qty); + + assert!(should_not_build.is_err()); + } + + #[test] + fn batch_finalization_algorithm_works_size_at_least_min_batch_proof_qty() { + // The following information will be the same for each entry, it is just some dummy data to see + // algorithm working. + + let proof_generator_addr = Address::random(); + let payment_service_addr = Address::random(); + let sender_addr = Address::random(); + let bytes_for_verification_data = vec![42_u8; 10]; + let dummy_signature = Signature { + r: U256::from(1), + s: U256::from(2), + v: 3, + }; + let verification_data = VerificationData { + proving_system: ProvingSystemId::Risc0, + proof: bytes_for_verification_data.clone(), + pub_input: Some(bytes_for_verification_data.clone()), + verification_key: Some(bytes_for_verification_data.clone()), + vm_program_code: Some(bytes_for_verification_data), + proof_generator_addr, + }; + let chain_id = U256::from(42); + + // Here we create different entries for the batch queue. + // Since we are sending with the same address, the low nonces should have higher max fees. + + // Entry 1 + let nonce_1 = U256::from(1); + let max_fee_1 = U256::from(1_300_000_000_000_002u128); + let nonced_verification_data_1 = NoncedVerificationData::new( + verification_data.clone(), + nonce_1, + max_fee_1, + chain_id, + payment_service_addr, + ); + let vd_commitment_1: VerificationDataCommitment = nonced_verification_data_1.clone().into(); + let entry_1 = BatchQueueEntry::new_for_testing( + nonced_verification_data_1, + vd_commitment_1, + dummy_signature, + sender_addr, + ); + let batch_priority_1 = BatchQueueEntryPriority::new(max_fee_1, nonce_1); + + // Entry 2 + let nonce_2 = U256::from(2); + let max_fee_2 = U256::from(1_300_000_000_000_001u128); + let nonced_verification_data_2 = NoncedVerificationData::new( + verification_data.clone(), + nonce_2, + max_fee_2, + chain_id, + payment_service_addr, + ); + let vd_commitment_2: VerificationDataCommitment = nonced_verification_data_2.clone().into(); + let entry_2 = BatchQueueEntry::new_for_testing( + nonced_verification_data_2, + vd_commitment_2, + dummy_signature, + sender_addr, + ); + let batch_priority_2 = BatchQueueEntryPriority::new(max_fee_2, nonce_2); + + let mut batch_queue = BatchQueue::new(); + batch_queue.push(entry_1, batch_priority_1); + batch_queue.push(entry_2, batch_priority_2); + + let gas_price = U256::from(1); + + // The min batch len is 2, so the algorithm should work with 2 entries. + let min_batch_proof_qty = 2; + + let (resulting_batch_queue, finalized_batch) = + try_build_batch(batch_queue, gas_price, 5000000, 1000, min_batch_proof_qty).unwrap(); + + assert_eq!(resulting_batch_queue.len(), 0); + assert_eq!(finalized_batch.len(), 2); + assert_eq!( + finalized_batch[0].nonced_verification_data.max_fee, + max_fee_2 + ); + assert_eq!( + finalized_batch[1].nonced_verification_data.max_fee, + max_fee_1 + ); + } + #[test] + fn batch_finalization_algorithm_works_size_bigger_than_min_batch_proof_qty() { + // The following information will be the same for each entry, it is just some dummy data to see + // algorithm working. + + let proof_generator_addr = Address::random(); + let payment_service_addr = Address::random(); + let sender_addr = Address::random(); + let bytes_for_verification_data = vec![42_u8; 10]; + let dummy_signature = Signature { + r: U256::from(1), + s: U256::from(2), + v: 3, + }; + let verification_data = VerificationData { + proving_system: ProvingSystemId::Risc0, + proof: bytes_for_verification_data.clone(), + pub_input: Some(bytes_for_verification_data.clone()), + verification_key: Some(bytes_for_verification_data.clone()), + vm_program_code: Some(bytes_for_verification_data), + proof_generator_addr, + }; + let chain_id = U256::from(42); + + // Here we create different entries for the batch queue. + // Since we are sending with the same address, the low nonces should have higher max fees. + + // Entry 1 + let nonce_1 = U256::from(1); + let max_fee_1 = U256::from(1_300_000_000_000_002u128); + let nonced_verification_data_1 = NoncedVerificationData::new( + verification_data.clone(), + nonce_1, + max_fee_1, + chain_id, + payment_service_addr, + ); + let vd_commitment_1: VerificationDataCommitment = nonced_verification_data_1.clone().into(); + let entry_1 = BatchQueueEntry::new_for_testing( + nonced_verification_data_1, + vd_commitment_1, + dummy_signature, + sender_addr, + ); + let batch_priority_1 = BatchQueueEntryPriority::new(max_fee_1, nonce_1); + + // Entry 2 + let nonce_2 = U256::from(2); + let max_fee_2 = U256::from(1_300_000_000_000_001u128); + let nonced_verification_data_2 = NoncedVerificationData::new( + verification_data.clone(), + nonce_2, + max_fee_2, + chain_id, + payment_service_addr, + ); + let vd_commitment_2: VerificationDataCommitment = nonced_verification_data_2.clone().into(); + let entry_2 = BatchQueueEntry::new_for_testing( + nonced_verification_data_2, + vd_commitment_2, + dummy_signature, + sender_addr, + ); + let batch_priority_2 = BatchQueueEntryPriority::new(max_fee_2, nonce_2); + + // Entry 3 + let nonce_3 = U256::from(3); + let max_fee_3 = U256::from(1_300_000_000_000_000u128); + let nonced_verification_data_3 = NoncedVerificationData::new( + verification_data.clone(), + nonce_3, + max_fee_3, + chain_id, + payment_service_addr, + ); + let vd_commitment_3: VerificationDataCommitment = nonced_verification_data_3.clone().into(); + let entry_3 = BatchQueueEntry::new_for_testing( + nonced_verification_data_3, + vd_commitment_3, + dummy_signature, + sender_addr, + ); + let batch_priority_3 = BatchQueueEntryPriority::new(max_fee_3, nonce_3); + + let mut batch_queue = BatchQueue::new(); + batch_queue.push(entry_1, batch_priority_1); + batch_queue.push(entry_2, batch_priority_2); + batch_queue.push(entry_3, batch_priority_3); + + let gas_price = U256::from(1); + + // The min batch len is 2, so the algorithm should work with 3 entries. + let min_batch_proof_qty = 2; + + let (resulting_batch_queue, finalized_batch) = + try_build_batch(batch_queue, gas_price, 5000000, 1000, min_batch_proof_qty).unwrap(); + + assert_eq!(resulting_batch_queue.len(), 0); + assert_eq!(finalized_batch.len(), 3); + assert_eq!( + finalized_batch[0].nonced_verification_data.max_fee, + max_fee_3 + ); + assert_eq!( + finalized_batch[1].nonced_verification_data.max_fee, + max_fee_2 + ); + assert_eq!( + finalized_batch[2].nonced_verification_data.max_fee, + max_fee_1 + ); + } } From 911ba8fdd6bc5ba3a8e1b122035d4f3313399faa Mon Sep 17 00:00:00 2001 From: Urix <43704209+uri-99@users.noreply.github.com> Date: Mon, 30 Dec 2024 15:37:08 -0300 Subject: [PATCH 5/7] chore: cargo fmt --- batcher/aligned-task-sender/src/commands.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/batcher/aligned-task-sender/src/commands.rs b/batcher/aligned-task-sender/src/commands.rs index a51258a26..22dac5a68 100644 --- a/batcher/aligned-task-sender/src/commands.rs +++ b/batcher/aligned-task-sender/src/commands.rs @@ -368,7 +368,10 @@ pub async fn send_infinite_proofs(args: SendInfiniteProofsArgs) { } info!("All responses received for sender {}", i); - info!("Sleeping for {} seconds, before submitting another burst of proofs", args.burst_time_secs); + info!( + "Sleeping for {} seconds, before submitting another burst of proofs", + args.burst_time_secs + ); tokio::time::sleep(Duration::from_secs(args.burst_time_secs)).await; } From 34a8b289ada0a21817ede54b212a706bfa47a0b4 Mon Sep 17 00:00:00 2001 From: Urix <43704209+uri-99@users.noreply.github.com> Date: Mon, 30 Dec 2024 15:44:14 -0300 Subject: [PATCH 6/7] fix: commit change in batcher config yaml --- config-files/config-batcher.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/config-files/config-batcher.yaml b/config-files/config-batcher.yaml index 6bcaffe9a..ffbd1b92f 100644 --- a/config-files/config-batcher.yaml +++ b/config-files/config-batcher.yaml @@ -22,6 +22,7 @@ batcher: max_proof_size: 67108864 # 64 MiB max_batch_byte_size: 268435456 # 256 MiB max_batch_proof_qty: 3000 # 3000 proofs in a batch + min_batch_proof_qty: 16 # 16 proof in a batch pre_verification_is_enabled: true metrics_port: 9093 telemetry_ip_port_address: localhost:4001 From 9d9f92e0e9f42328ce2d6d1258cf28657f52c204 Mon Sep 17 00:00:00 2001 From: Urix <43704209+uri-99@users.noreply.github.com> Date: Mon, 30 Dec 2024 15:48:38 -0300 Subject: [PATCH 7/7] fix: docs of batcher about proof_qty --- docs/2_architecture/components/1_batcher.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/2_architecture/components/1_batcher.md b/docs/2_architecture/components/1_batcher.md index fbcb24c4b..579fcd933 100644 --- a/docs/2_architecture/components/1_batcher.md +++ b/docs/2_architecture/components/1_batcher.md @@ -47,14 +47,15 @@ When the conditions to build a batch are met, the Batcher runs the following bat This algorithm starts by calculating the **batch size**, in bytes, by adding the verification data bytes of each proof of the queue. The next step is to build a new **resulting priority queue**, which will store all proofs that where not included in the batch, replacing the current priority queue when this algorithm ends. -In order for the batch to be considered valid, two conditions have to be met: +In order for the batch to be considered valid, some conditions need to be met: * The **batch size** in bytes must be less than or equal to a defined limit. * All proofs found in the batch must have a `max_fee` equal or higher to the calculated **fee per proof** of the batch. +* The **batch proof quantity** must be between the a defined limits. -The **fee per proof** indicates the cost of verifying each proof within the batch. It is calculated using a formula that depends on the **batch length**, defined as the number of proofs in the batch: +The **fee per proof** indicates the cost of verifying each proof within the batch. It is calculated using a formula that depends on the **batch proof quantity**, defined as the number of proofs in the batch: ``` -gas_per_proof = (constant_gas_cost + additional_submission_gas_cost_per_proof * batch_len) / batch_len +gas_per_proof = (constant_gas_cost + additional_submission_gas_cost_per_proof * batch_proof_qty) / batch_proof_qty fee_per_proof = gas_per_proof * gas_price ```