From efbd001c9c4b33171cf77a4d3405a32ab1031553 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Thu, 4 Jul 2024 14:04:59 +0200 Subject: [PATCH 01/48] feat(sidecar): enforce max_commitments_per_slot checks --- bolt-sidecar/bin/sidecar.rs | 3 ++- bolt-sidecar/src/config/mod.rs | 7 ++++--- bolt-sidecar/src/state/execution.rs | 24 ++++++++++++++++++++---- bolt-sidecar/src/state/mod.rs | 22 +++++++++++++++++----- 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index 96c9b918f..20bea2b91 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -28,7 +28,8 @@ async fn main() -> eyre::Result<()> { let signer = Signer::new(config.private_key.clone().unwrap()); let state_client = StateClient::new(config.execution_api_url.clone()); - let mut execution_state = ExecutionState::new(state_client).await?; + let mut execution_state = + ExecutionState::new(state_client, config.limits.max_commitments_per_slot).await?; let mevboost_client = MevBoostClient::new(config.mevboost_url.clone()); let beacon_client = BeaconClient::new(config.beacon_api_url.clone()); diff --git a/bolt-sidecar/src/config/mod.rs b/bolt-sidecar/src/config/mod.rs index ca915ac90..d0f60d595 100644 --- a/bolt-sidecar/src/config/mod.rs +++ b/bolt-sidecar/src/config/mod.rs @@ -4,6 +4,7 @@ use alloy_primitives::Address; use blst::min_pk::SecretKey; use clap::Parser; use reqwest::Url; +use std::num::NonZero; use crate::crypto::bls::random_bls_secret; @@ -45,7 +46,7 @@ pub struct Opts { pub(super) mevboost_proxy_port: u16, /// Max number of commitments to accept per block #[clap(short = 'm', long)] - pub(super) max_commitments: Option, + pub(super) max_commitments: Option>, /// Validator indexes of connected validators that the sidecar /// should accept commitments on behalf of. Accepted values: /// - a comma-separated list of indexes (e.g. "1,2,3,4") @@ -135,13 +136,13 @@ impl Default for Config { #[derive(Debug, Clone)] pub struct Limits { /// Maximum number of commitments to accept per block - pub max_commitments_per_slot: usize, + pub max_commitments_per_slot: NonZero, } impl Default for Limits { fn default() -> Self { Self { - max_commitments_per_slot: 6, + max_commitments_per_slot: NonZero::new(6).expect("Valid non-zero"), } } } diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index ad01b143b..d87caaef2 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -2,7 +2,7 @@ use alloy_eips::eip4844::MAX_BLOBS_PER_BLOCK; use alloy_primitives::{Address, SignatureError}; use alloy_transport::TransportError; use reth_primitives::{transaction::TxType, TransactionSigned}; -use std::collections::HashMap; +use std::{collections::HashMap, num::NonZero}; use thiserror::Error; use crate::{ @@ -31,6 +31,9 @@ pub enum ValidationError { /// There are too many EIP-4844 transactions in the target block. #[error("Too many EIP-4844 transactions in target block")] Eip4844Limit, + /// The maximum commitments have been reached for the slot. + #[error("Max commitments reached for slot {0}")] + MaxCommitmentsReachedForSlot(usize), /// The signature is invalid. #[error("Signature error: {0:?}")] Signature(#[from] SignatureError), @@ -81,10 +84,10 @@ pub struct ExecutionState { /// We have multiple block templates because in rare cases we might have multiple /// proposal duties for a single lookahead. block_templates: HashMap, - /// The chain ID of the chain (constant). chain_id: u64, - + /// The maximum number of commitments per slot. + max_commitments_per_slot: NonZero, /// The state fetcher client. client: C, } @@ -92,7 +95,10 @@ pub struct ExecutionState { impl ExecutionState { /// Creates a new state with the given client, initializing the /// basefee and head block number. - pub async fn new(client: C) -> Result { + pub async fn new( + client: C, + max_commitments_per_slot: NonZero, + ) -> Result { Ok(Self { basefee: client.get_basefee(None).await?, block_number: client.get_head().await?, @@ -100,6 +106,7 @@ impl ExecutionState { account_states: HashMap::new(), block_templates: HashMap::new(), chain_id: client.get_chain_id().await?, + max_commitments_per_slot, client, }) } @@ -130,6 +137,15 @@ impl ExecutionState { return Err(ValidationError::ChainIdMismatch); } + // Check if there is room for more commitments + if let Some(template) = self.get_block_template(req.slot) { + if template.transactions.len() >= self.max_commitments_per_slot.get() { + return Err(ValidationError::MaxCommitmentsReachedForSlot( + self.max_commitments_per_slot.get(), + )); + } + } + let sender = req.tx.recover_signer().ok_or(ValidationError::Internal( "Failed to recover signer from transaction".to_string(), ))?; diff --git a/bolt-sidecar/src/state/mod.rs b/bolt-sidecar/src/state/mod.rs index 7fb78c20d..f08dd7733 100644 --- a/bolt-sidecar/src/state/mod.rs +++ b/bolt-sidecar/src/state/mod.rs @@ -68,6 +68,8 @@ impl Future for CommitmentDeadline { #[cfg(test)] mod tests { + use std::num::NonZero; + use alloy_consensus::constants::ETH_TO_WEI; use alloy_eips::eip2718::Encodable2718; use alloy_network::EthereumWallet; @@ -111,7 +113,9 @@ mod tests { let anvil = launch_anvil(); let client = StateClient::new(Url::parse(&anvil.endpoint()).unwrap()); - let mut state = ExecutionState::new(client).await.unwrap(); + let mut state = ExecutionState::new(client, NonZero::new(1024).expect("valid non-zero")) + .await + .unwrap(); let wallet: PrivateKeySigner = anvil.keys()[0].clone().into(); @@ -145,7 +149,9 @@ mod tests { let anvil = launch_anvil(); let client = StateClient::new(Url::parse(&anvil.endpoint()).unwrap()); - let mut state = ExecutionState::new(client).await.unwrap(); + let mut state = ExecutionState::new(client, NonZero::new(1024).expect("valid non-zero")) + .await + .unwrap(); let wallet: PrivateKeySigner = anvil.keys()[0].clone().into(); @@ -182,7 +188,9 @@ mod tests { let anvil = launch_anvil(); let client = StateClient::new(Url::parse(&anvil.endpoint()).unwrap()); - let mut state = ExecutionState::new(client).await.unwrap(); + let mut state = ExecutionState::new(client, NonZero::new(1024).expect("valid non-zero")) + .await + .unwrap(); let wallet: PrivateKeySigner = anvil.keys()[0].clone().into(); @@ -220,7 +228,9 @@ mod tests { let anvil = launch_anvil(); let client = StateClient::new(Url::parse(&anvil.endpoint()).unwrap()); - let mut state = ExecutionState::new(client).await.unwrap(); + let mut state = ExecutionState::new(client, NonZero::new(1024).expect("valid non-zero")) + .await + .unwrap(); let basefee = state.basefee(); @@ -259,7 +269,9 @@ mod tests { let anvil = launch_anvil(); let client = StateClient::new(Url::parse(&anvil.endpoint()).unwrap()); - let mut state = ExecutionState::new(client).await.unwrap(); + let mut state = ExecutionState::new(client, NonZero::new(1024).expect("valid non-zero")) + .await + .unwrap(); let wallet: PrivateKeySigner = anvil.keys()[0].clone().into(); From 6c0327ae0436716e995fc12fb69d3726126dcf62 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Thu, 4 Jul 2024 16:18:57 +0200 Subject: [PATCH 02/48] chore(sidecar): add constraints of slots to block template --- bolt-sidecar/src/builder/template.rs | 2 ++ bolt-sidecar/src/primitives/constraint.rs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/bolt-sidecar/src/builder/template.rs b/bolt-sidecar/src/builder/template.rs index b847a5dbf..2fec0eca7 100644 --- a/bolt-sidecar/src/builder/template.rs +++ b/bolt-sidecar/src/builder/template.rs @@ -26,6 +26,8 @@ pub struct BlockTemplate { state_diff: StateDiff, /// The list of transactions in the block template. pub transactions: Vec, + /// The signed constraints associated to the block + pub signed_constraints_list: Vec, } impl BlockTemplate { diff --git a/bolt-sidecar/src/primitives/constraint.rs b/bolt-sidecar/src/primitives/constraint.rs index 76c1e7b52..c793522b7 100644 --- a/bolt-sidecar/src/primitives/constraint.rs +++ b/bolt-sidecar/src/primitives/constraint.rs @@ -29,7 +29,7 @@ impl SignableECDSA for ConstraintsMessage { pub type BatchedSignedConstraints = Vec; /// A container for a list of constraints and the signature of the proposer sidecar. -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct SignedConstraints { /// The constraints that need to be signed. pub message: ConstraintsMessage, @@ -38,7 +38,7 @@ pub struct SignedConstraints { } /// A message that contains the constraints that need to be signed by the proposer sidecar. -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct ConstraintsMessage { /// The validator index of the proposer sidecar. pub validator_index: u64, From 4100a708d2c4bfb1e6e3389b2605e9f23b2ec5b0 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Thu, 4 Jul 2024 16:23:09 +0200 Subject: [PATCH 03/48] feat(sidecar): add constraints to execution state and send them after deadline --- bolt-sidecar/bin/sidecar.rs | 41 +++++++++++++++------------- bolt-sidecar/src/builder/template.rs | 12 ++++++-- bolt-sidecar/src/state/execution.rs | 20 +++++++++----- bolt-sidecar/src/state/mod.rs | 10 +++---- 4 files changed, 50 insertions(+), 33 deletions(-) diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index 20bea2b91..4335a817a 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -79,7 +79,7 @@ async fn main() -> eyre::Result<()> { }; if let Err(e) = execution_state - .try_commit(&request) + .check_commitment_validity(&request) .await { tracing::error!("Failed to commit request: {:?}", e); @@ -89,32 +89,20 @@ async fn main() -> eyre::Result<()> { // TODO: match when we have more request types let CommitmentRequest::Inclusion(request) = request; - tracing::info!( tx_hash = %request.tx.hash(), "Validation against execution state passed" ); - // parse the request into constraints and sign them with the sidecar signer - let message = ConstraintsMessage::build(validator_index, request.slot, request); + // TODO: review all this `clone` usage + // parse the request into constraints and sign them with the sidecar signer + let message = ConstraintsMessage::build(validator_index, request.slot, request.clone()); let signature = signer.sign(&message.digest())?.to_string(); - let signed_constraints = vec![SignedConstraints { message, signature }]; + let signed_constraints = SignedConstraints { message, signature }; + + execution_state.commit_transaction(request.slot, request.tx, signed_constraints.clone()); - // TODO: fix retry logic - let max_retries = 5; - let mut i = 0; - 'inner: while let Err(e) = mevboost_client - .submit_constraints(&signed_constraints) - .await - { - tracing::error!(err = ?e, "Error submitting constraints, retrying..."); - tokio::time::sleep(Duration::from_millis(100)).await; - i+=1; - if i >= max_retries { - break 'inner - } - } let res = serde_json::to_value(signed_constraints).map_err(Into::into); let _ = response_tx.send(res).ok(); @@ -139,6 +127,21 @@ async fn main() -> eyre::Result<()> { continue; }; + // TODO: fix retry logic + let max_retries = 5; + let mut i = 0; + 'inner: while let Err(e) = mevboost_client + .submit_constraints(&template.signed_constraints_list) + .await + { + tracing::error!(err = ?e, "Error submitting constraints, retrying..."); + tokio::time::sleep(Duration::from_millis(100)).await; + i+=1; + if i >= max_retries { + break 'inner + } + } + if let Err(e) = local_builder.build_new_local_payload(template.transactions).await { tracing::error!(err = ?e, "CRITICAL: Error while building local payload at slot deadline for {slot}"); }; diff --git a/bolt-sidecar/src/builder/template.rs b/bolt-sidecar/src/builder/template.rs index 2fec0eca7..9b79511c4 100644 --- a/bolt-sidecar/src/builder/template.rs +++ b/bolt-sidecar/src/builder/template.rs @@ -9,7 +9,10 @@ use std::collections::HashMap; use alloy_primitives::{Address, U256}; use reth_primitives::{TransactionSigned, TxType}; -use crate::{common::max_transaction_cost, primitives::AccountState}; +use crate::{ + common::max_transaction_cost, + primitives::{AccountState, SignedConstraints}, +}; /// A block template that serves as a fallback block, but is also used /// to keep intermediary state for new commitment requests. @@ -37,7 +40,11 @@ impl BlockTemplate { } /// Adds a transaction to the block template and updates the state diff. - pub fn add_transaction(&mut self, transaction: TransactionSigned) { + pub fn add_constraints( + &mut self, + transaction: TransactionSigned, + signed_constraints: SignedConstraints, + ) { let max_cost = max_transaction_cost(&transaction); // Update intermediate state @@ -51,6 +58,7 @@ impl BlockTemplate { .or_insert((1, max_cost)); self.transactions.push(transaction); + self.signed_constraints_list.push(signed_constraints); } /// Returns the length of the transactions in the block template. diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index d87caaef2..e17f2c510 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -8,7 +8,7 @@ use thiserror::Error; use crate::{ builder::BlockTemplate, common::{calculate_max_basefee, validate_transaction}, - primitives::{AccountState, CommitmentRequest, Slot}, + primitives::{AccountState, CommitmentRequest, SignedConstraints, Slot}, }; use super::fetcher::StateFetcher; @@ -129,7 +129,10 @@ impl ExecutionState { /// If the commitment is valid, it will be added to the block template and its account state /// will be cached. If this is succesful, any callers can be sure that the commitment is valid /// and SHOULD sign it and respond to the requester. - pub async fn try_commit(&mut self, request: &CommitmentRequest) -> Result<(), ValidationError> { + pub async fn check_commitment_validity( + &mut self, + request: &CommitmentRequest, + ) -> Result<(), ValidationError> { let CommitmentRequest::Inclusion(req) = request; // Validate the chain ID @@ -198,20 +201,23 @@ impl ExecutionState { // TODO: check max_fee_per_blob_gas against the blob_base_fee } - self.commit_transaction(req.slot, req.tx.clone()); - Ok(()) } /// Commits the transaction to the target block. Initializes a new block template /// if one does not exist for said block number. /// TODO: remove `pub` modifier once `try_commit` is fully implemented. - pub fn commit_transaction(&mut self, target_slot: u64, transaction: TransactionSigned) { + pub fn commit_transaction( + &mut self, + target_slot: u64, + transaction: TransactionSigned, + signed_constraints: SignedConstraints, + ) { if let Some(template) = self.block_templates.get_mut(&target_slot) { - template.add_transaction(transaction); + template.add_constraints(transaction, signed_constraints); } else { let mut template = BlockTemplate::default(); - template.add_transaction(transaction); + template.add_constraints(transaction, signed_constraints); self.block_templates.insert(target_slot, template); } } diff --git a/bolt-sidecar/src/state/mod.rs b/bolt-sidecar/src/state/mod.rs index f08dd7733..83cc21195 100644 --- a/bolt-sidecar/src/state/mod.rs +++ b/bolt-sidecar/src/state/mod.rs @@ -139,7 +139,7 @@ mod tests { signature: sig, }); - assert!(state.try_commit(&request).await.is_ok()); + assert!(state.check_commitment_validity(&request).await.is_ok()); } #[tokio::test] @@ -176,7 +176,7 @@ mod tests { }); assert!(matches!( - state.try_commit(&request).await, + state.check_commitment_validity(&request).await, Err(ValidationError::NonceTooHigh) )); } @@ -216,7 +216,7 @@ mod tests { }); assert!(matches!( - state.try_commit(&request).await, + state.check_commitment_validity(&request).await, Err(ValidationError::InsufficientBalance) )); } @@ -257,7 +257,7 @@ mod tests { }); assert!(matches!( - state.try_commit(&request).await, + state.check_commitment_validity(&request).await, Err(ValidationError::BaseFeeTooLow(_)) )); } @@ -295,7 +295,7 @@ mod tests { signature: sig, }); - assert!(state.try_commit(&request).await.is_ok()); + assert!(state.check_commitment_validity(&request).await.is_ok()); assert!(state.block_templates().get(&10).unwrap().transactions_len() == 1); let provider = ProviderBuilder::new().on_http(anvil.endpoint_url()); From 77693d32db5cceaa33e567b0945600d0945c9617 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Thu, 4 Jul 2024 21:07:20 +0200 Subject: [PATCH 04/48] chore(sidecar): extra private fields on constraint --- bolt-sidecar/bin/sidecar.rs | 17 +++++++++------ bolt-sidecar/src/primitives/constraint.rs | 26 +++++++++++++++++++---- bolt-sidecar/src/state/execution.rs | 4 ++-- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index 4335a817a..3917896ca 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -78,14 +78,17 @@ async fn main() -> eyre::Result<()> { } }; - if let Err(e) = execution_state + let sender = match execution_state .check_commitment_validity(&request) - .await + .await { - tracing::error!("Failed to commit request: {:?}", e); - let _ = response_tx.send(Err(ApiError::Custom(e.to_string()))); - continue; - } + Ok(sender) => { sender }, + Err(e) => { + tracing::error!("Failed to commit request: {:?}", e); + let _ = response_tx.send(Err(ApiError::Custom(e.to_string()))); + continue; + } + }; // TODO: match when we have more request types let CommitmentRequest::Inclusion(request) = request; @@ -97,7 +100,7 @@ async fn main() -> eyre::Result<()> { // TODO: review all this `clone` usage // parse the request into constraints and sign them with the sidecar signer - let message = ConstraintsMessage::build(validator_index, request.slot, request.clone()); + let message = ConstraintsMessage::build(validator_index, request.slot, request.clone(), sender); let signature = signer.sign(&message.digest())?.to_string(); let signed_constraints = SignedConstraints { message, signature }; diff --git a/bolt-sidecar/src/primitives/constraint.rs b/bolt-sidecar/src/primitives/constraint.rs index c793522b7..2ad6cbc6d 100644 --- a/bolt-sidecar/src/primitives/constraint.rs +++ b/bolt-sidecar/src/primitives/constraint.rs @@ -1,4 +1,5 @@ -use alloy_primitives::keccak256; +use alloy_primitives::{keccak256, Address}; +use reth_primitives::TransactionSigned; use secp256k1::Message; use serde::{Deserialize, Serialize}; @@ -50,8 +51,13 @@ pub struct ConstraintsMessage { impl ConstraintsMessage { /// Builds a constraints message from an inclusion request and metadata - pub fn build(validator_index: u64, slot: u64, request: InclusionRequest) -> Self { - let constraints = vec![Constraint::from_inclusion_request(request, None)]; + pub fn build( + validator_index: u64, + slot: u64, + request: InclusionRequest, + sender: Address, + ) -> Self { + let constraints = vec![Constraint::from_inclusion_request(request, None, sender)]; Self { validator_index, slot, @@ -83,17 +89,29 @@ pub struct Constraint { pub tx: String, /// The optional index at which the transaction needs to be included in the block pub index: Option, + /// The decoded transaction for internal use + #[serde(skip)] + pub(crate) tx_decoded: TransactionSigned, + /// The ec-recovered address of the transaction sender for internal use + #[serde(skip)] + pub(crate) sender: Address, } impl Constraint { /// Builds a constraint from an inclusion request and an optional index - pub fn from_inclusion_request(req: InclusionRequest, index: Option) -> Self { + pub fn from_inclusion_request( + req: InclusionRequest, + index: Option, + sender: Address, + ) -> Self { let mut encoded_tx = Vec::new(); req.tx.encode_enveloped(&mut encoded_tx); Self { tx: format!("0x{}", hex::encode(encoded_tx)), index, + tx_decoded: req.tx, + sender, } } diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index e17f2c510..bfe58d0ae 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -132,7 +132,7 @@ impl ExecutionState { pub async fn check_commitment_validity( &mut self, request: &CommitmentRequest, - ) -> Result<(), ValidationError> { + ) -> Result { let CommitmentRequest::Inclusion(req) = request; // Validate the chain ID @@ -201,7 +201,7 @@ impl ExecutionState { // TODO: check max_fee_per_blob_gas against the blob_base_fee } - Ok(()) + Ok(sender) } /// Commits the transaction to the target block. Initializes a new block template From 613d0a9cd066eaa1151b2d7f5ac0c3d5b1652c3a Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Thu, 4 Jul 2024 21:56:21 +0200 Subject: [PATCH 05/48] feat(sidecar): replace transactions with signed constraints list in block template --- bolt-sidecar/bin/sidecar.rs | 10 +- bolt-sidecar/src/builder/template.rs | 182 +++++++++++++++++---------- bolt-sidecar/src/primitives/mod.rs | 2 +- bolt-sidecar/src/state/execution.rs | 17 +-- 4 files changed, 132 insertions(+), 79 deletions(-) diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index 3917896ca..dca0f52eb 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -104,7 +104,7 @@ async fn main() -> eyre::Result<()> { let signature = signer.sign(&message.digest())?.to_string(); let signed_constraints = SignedConstraints { message, signature }; - execution_state.commit_transaction(request.slot, request.tx, signed_constraints.clone()); + execution_state.add_constraint(request.slot, signed_constraints.clone()); let res = serde_json::to_value(signed_constraints).map_err(Into::into); @@ -130,22 +130,24 @@ async fn main() -> eyre::Result<()> { continue; }; - // TODO: fix retry logic + // TODO: fix retry logic, and move this to separate task let max_retries = 5; let mut i = 0; 'inner: while let Err(e) = mevboost_client .submit_constraints(&template.signed_constraints_list) - .await + .await { tracing::error!(err = ?e, "Error submitting constraints, retrying..."); tokio::time::sleep(Duration::from_millis(100)).await; i+=1; if i >= max_retries { + tracing::error!("Max retries reached while submitting to MEV-Boost"); break 'inner } } - if let Err(e) = local_builder.build_new_local_payload(template.transactions).await { + + if let Err(e) = local_builder.build_new_local_payload(template.transactions()).await { tracing::error!(err = ?e, "CRITICAL: Error while building local payload at slot deadline for {slot}"); }; }, diff --git a/bolt-sidecar/src/builder/template.rs b/bolt-sidecar/src/builder/template.rs index 9b79511c4..356ddd8da 100644 --- a/bolt-sidecar/src/builder/template.rs +++ b/bolt-sidecar/src/builder/template.rs @@ -11,7 +11,7 @@ use reth_primitives::{TransactionSigned, TxType}; use crate::{ common::max_transaction_cost, - primitives::{AccountState, SignedConstraints}, + primitives::{constraint::Constraint, AccountState, SignedConstraints}, }; /// A block template that serves as a fallback block, but is also used @@ -27,8 +27,6 @@ use crate::{ pub struct BlockTemplate { /// The state diffs per address given the list of commitments. state_diff: StateDiff, - /// The list of transactions in the block template. - pub transactions: Vec, /// The signed constraints associated to the block pub signed_constraints_list: Vec, } @@ -40,87 +38,145 @@ impl BlockTemplate { } /// Adds a transaction to the block template and updates the state diff. - pub fn add_constraints( - &mut self, - transaction: TransactionSigned, - signed_constraints: SignedConstraints, - ) { - let max_cost = max_transaction_cost(&transaction); + pub fn add_constraints(&mut self, signed_constraints: SignedConstraints) { + let mut address_to_state_diffs: HashMap = HashMap::new(); + signed_constraints.message.constraints.iter().for_each(|c| { + address_to_state_diffs + .entry(c.sender) + .and_modify(|state| { + state.balance = state + .balance + .saturating_add(max_transaction_cost(&c.tx_decoded)); + state.transaction_count += 1; + }) + .or_insert(AccountState { + balance: max_transaction_cost(&c.tx_decoded), + transaction_count: 1, + }); + }); + + // Now update intermediate state + address_to_state_diffs.iter().for_each(|(address, diff)| { + self.state_diff + .diffs + .entry(*address) + .and_modify(|(nonce, balance)| { + *nonce += diff.transaction_count; + *balance += diff.balance; + }) + .or_insert((diff.transaction_count, diff.balance)); + }); - // Update intermediate state - self.state_diff - .diffs - .entry(transaction.recover_signer().expect("Passed validation")) - .and_modify(|(nonce, balance)| { - *nonce += 1; - *balance += max_cost; - }) - .or_insert((1, max_cost)); - - self.transactions.push(transaction); self.signed_constraints_list.push(signed_constraints); } + /// Returns all a clone of all transactions from the signed constraints list + #[inline] + pub fn transactions(&self) -> Vec { + self.signed_constraints_list + .iter() + .flat_map(|sc| sc.message.constraints.iter().map(|c| c.tx_decoded.clone())) + .collect() + } + /// Returns the length of the transactions in the block template. + #[inline] pub fn transactions_len(&self) -> usize { - self.transactions.len() + self.signed_constraints_list + .iter() + .fold(0, |acc, sc| acc + sc.message.constraints.len()) } /// Returns the blob count of the block template. + #[inline] pub fn blob_count(&self) -> usize { - self.transactions.iter().fold(0, |mut acc, tx| { - if tx.tx_type() == TxType::Eip4844 { - acc += tx.blob_versioned_hashes().unwrap_or_default().len(); - } - - acc + self.signed_constraints_list.iter().fold(0, |acc, sc| { + acc + sc + .message + .constraints + .iter() + .filter(|c| c.tx_decoded.tx_type() == TxType::Eip4844) + .count() }) } - /// Removes the transaction at the specified index and updates the state diff. - fn remove_transaction_at_index(&mut self, index: usize) { - let tx = self.transactions.remove(index); - let max_cost = max_transaction_cost(&tx); + /// Remove all signed constraints at the specified index and updates the state diff + fn remove_constraints_at_index(&mut self, index: usize) { + let sc = self.signed_constraints_list.remove(index); + let mut address_to_txs: HashMap> = HashMap::new(); + sc.message.constraints.iter().for_each(|c| { + address_to_txs + .entry(c.sender) + .and_modify(|txs| txs.push(&c.tx_decoded)) + .or_insert(vec![&c.tx_decoded]); + }); + + // Collect the diff for each address and every transaction + let address_to_diff: HashMap = address_to_txs + .iter() + .map(|(address, txs)| { + let mut state = AccountState::default(); + for tx in txs { + state.balance = state.balance.saturating_add(max_transaction_cost(tx)); + state.transaction_count = state.transaction_count.saturating_sub(1); + } + (*address, state) + }) + .collect(); // Update intermediate state - self.state_diff - .diffs - .entry(tx.recover_signer().expect("Passed validation")) - .and_modify(|(nonce, balance)| { - *nonce = nonce.saturating_sub(1); - *balance += max_cost; - }); + for (address, diff) in address_to_diff.iter() { + self.state_diff + .diffs + .entry(*address) + .and_modify(|(nonce, balance)| { + *nonce = nonce.saturating_sub(diff.transaction_count); + *balance += diff.balance; + }); + } } /// Retain removes any transactions that conflict with the given account state. - pub fn retain(&mut self, address: Address, mut state: AccountState) { - let mut indexes = Vec::new(); - - for (index, tx) in self.transactions.iter().enumerate() { - let max_cost = max_transaction_cost(tx); - if tx.recover_signer().expect("passed validation") == address - && (state.balance < max_cost || state.transaction_count > tx.nonce()) - { - tracing::trace!( - %address, - "Removing transaction at index {} due to conflict with account state", - index - ); - - indexes.push(index); - // Continue to the next iteration, not updating the state - continue; - } - - // Update intermediary state for next transaction (if the tx was not removed) - state.balance -= max_cost; - state.transaction_count += 1; + pub fn retain(&mut self, address: Address, state: AccountState) { + let mut indexes: Vec = Vec::new(); + + // The pre-confirmations made by such address, and the indexes of the signed constraints + // in which they appear + let constraints_with_address: Vec<(usize, Vec<&Constraint>)> = self + .signed_constraints_list + .iter() + .enumerate() + .map(|(idx, c)| (idx, &c.message.constraints)) + .filter(|(_idx, c)| c.iter().any(|c| c.sender == address)) + .map(|(idx, c)| (idx, c.iter().filter(|c| c.sender == address).collect())) + .collect(); + + // For every pre-confirmation, gather the max total balance cost, + // and find the one with the lowest nonce + let (max_total_cost, min_nonce) = constraints_with_address + .iter() + .flat_map(|c| c.1.clone()) + .fold((U256::ZERO, u64::MAX), |mut acc, c| { + let nonce = c.tx_decoded.nonce(); + if nonce < acc.1 { + acc.1 = nonce; + } + acc.0 += max_transaction_cost(&c.tx_decoded); + acc + }); + + if state.balance < max_total_cost || state.transaction_count > min_nonce { + // NOTE: We drop all the signed constraints containing such pre-confirmations + // since at least one of them has been invalidated. + tracing::warn!( + %address, + "Removing all signed constraints which contain such address pre-confirmations due to conflict with account state", + ); + indexes = constraints_with_address.iter().map(|c| c.0).collect(); } - // Remove transactions that conflict with the account state. We start in reverse - // order to avoid invalidating the indexes. for index in indexes.into_iter().rev() { - self.remove_transaction_at_index(index); + self.remove_constraints_at_index(index); } } } diff --git a/bolt-sidecar/src/primitives/mod.rs b/bolt-sidecar/src/primitives/mod.rs index d8bf18ae6..c352131d5 100644 --- a/bolt-sidecar/src/primitives/mod.rs +++ b/bolt-sidecar/src/primitives/mod.rs @@ -32,7 +32,7 @@ pub use constraint::{BatchedSignedConstraints, ConstraintsMessage, SignedConstra pub type Slot = u64; /// Minimal account state needed for commitment validation. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub struct AccountState { /// The nonce of the account. This is the number of transactions sent from this account pub transaction_count: u64, diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index bfe58d0ae..35406f6df 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -1,7 +1,7 @@ use alloy_eips::eip4844::MAX_BLOBS_PER_BLOCK; use alloy_primitives::{Address, SignatureError}; use alloy_transport::TransportError; -use reth_primitives::{transaction::TxType, TransactionSigned}; +use reth_primitives::transaction::TxType; use std::{collections::HashMap, num::NonZero}; use thiserror::Error; @@ -142,7 +142,7 @@ impl ExecutionState { // Check if there is room for more commitments if let Some(template) = self.get_block_template(req.slot) { - if template.transactions.len() >= self.max_commitments_per_slot.get() { + if template.transactions_len() >= self.max_commitments_per_slot.get() { return Err(ValidationError::MaxCommitmentsReachedForSlot( self.max_commitments_per_slot.get(), )); @@ -207,17 +207,12 @@ impl ExecutionState { /// Commits the transaction to the target block. Initializes a new block template /// if one does not exist for said block number. /// TODO: remove `pub` modifier once `try_commit` is fully implemented. - pub fn commit_transaction( - &mut self, - target_slot: u64, - transaction: TransactionSigned, - signed_constraints: SignedConstraints, - ) { + pub fn add_constraint(&mut self, target_slot: u64, signed_constraints: SignedConstraints) { if let Some(template) = self.block_templates.get_mut(&target_slot) { - template.add_constraints(transaction, signed_constraints); + template.add_constraints(signed_constraints); } else { let mut template = BlockTemplate::default(); - template.add_constraints(transaction, signed_constraints); + template.add_constraints(signed_constraints); self.block_templates.insert(target_slot, template); } } @@ -261,7 +256,7 @@ impl ExecutionState { tracing::trace!(%address, ?account_state, "Refreshing template..."); // Iterate over all block templates and apply the state diff for (_, template) in self.block_templates.iter_mut() { - // Retain only the transactions that are still valid based on the canonical account states. + // Retain only signed constraints where transactions are still valid based on the canonical account states. template.retain(*address, *account_state); // Update the account state with the remaining state diff for the next iteration. From bcbfd178ab663ba4ba7dfe4ec6d83e9e612e603f Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Fri, 12 Jul 2024 10:17:13 +0200 Subject: [PATCH 06/48] wip: fix getpayload response from mev-boost --- bolt-sidecar/bin/sidecar.rs | 3 +- bolt-sidecar/src/api/builder.rs | 6 +- bolt-sidecar/src/api/spec.rs | 5 ++ bolt-sidecar/src/client/mevboost.rs | 7 +- bolt-sidecar/src/client/mod.rs | 3 + bolt-sidecar/src/client/test_util.rs | 100 +++++++++++++++++++++++++++ bolt-sidecar/src/state/execution.rs | 6 +- 7 files changed, 120 insertions(+), 10 deletions(-) create mode 100644 bolt-sidecar/src/client/test_util.rs diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index dca0f52eb..941d5782b 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -106,9 +106,8 @@ async fn main() -> eyre::Result<()> { execution_state.add_constraint(request.slot, signed_constraints.clone()); - let res = serde_json::to_value(signed_constraints).map_err(Into::into); - let _ = response_tx.send(res).ok(); + let _ = response_tx.send(res); }, Ok(HeadEvent { slot, .. }) = head_tracker.next_head() => { tracing::info!(slot, "Received new head event"); diff --git a/bolt-sidecar/src/api/builder.rs b/bolt-sidecar/src/api/builder.rs index 7a6b93b94..79596db30 100644 --- a/bolt-sidecar/src/api/builder.rs +++ b/bolt-sidecar/src/api/builder.rs @@ -20,8 +20,8 @@ use std::{sync::Arc, time::Duration}; use tokio::net::TcpListener; use super::spec::{ - BuilderApi, BuilderApiError, ConstraintsApi, GET_HEADER_PATH, GET_PAYLOAD_PATH, - REGISTER_VALIDATORS_PATH, STATUS_PATH, + BuilderApiError, ConstraintsApi, GET_HEADER_PATH, GET_PAYLOAD_PATH, REGISTER_VALIDATORS_PATH, + STATUS_PATH, }; use crate::{ client::mevboost::MevBoostClient, @@ -35,7 +35,7 @@ const GET_HEADER_WITH_PROOFS_TIMEOUT: Duration = Duration::from_millis(500); /// A proxy server for the builder API. /// Forwards all requests to the target after interception. -pub struct BuilderProxyServer { +pub struct BuilderProxyServer { proxy_target: T, // TODO: fill with local payload when we fetch a payload // in failed get_header diff --git a/bolt-sidecar/src/api/spec.rs b/bolt-sidecar/src/api/spec.rs index 078e49078..50d3b6201 100644 --- a/bolt-sidecar/src/api/spec.rs +++ b/bolt-sidecar/src/api/spec.rs @@ -66,6 +66,8 @@ pub enum BuilderApiError { InvalidFork(String), #[error("Invalid local payload block hash. expected: {expected}, got: {have}")] InvalidLocalPayloadBlockHash { expected: String, have: String }, + #[error("Generic error: {0}")] + Generic(String), } impl IntoResponse for BuilderApiError { @@ -110,6 +112,9 @@ impl IntoResponse for BuilderApiError { BuilderApiError::InvalidLocalPayloadBlockHash { .. } => { (StatusCode::BAD_REQUEST, self.to_string()).into_response() } + BuilderApiError::Generic(err) => { + (StatusCode::INTERNAL_SERVER_ERROR, Json(err)).into_response() + } } } } diff --git a/bolt-sidecar/src/client/mevboost.rs b/bolt-sidecar/src/client/mevboost.rs index 5988c280c..e07c2af2f 100644 --- a/bolt-sidecar/src/client/mevboost.rs +++ b/bolt-sidecar/src/client/mevboost.rs @@ -127,7 +127,12 @@ impl BuilderApi for MevBoostClient { return Err(BuilderApiError::FailedGettingPayload(error)); } - let payload = response.json().await?; + // TODO: rm after debugging + let px = response.json::().await?; + tracing::info!("get_payload json response received: {:?}", px); + let payload = serde_json::from_value(px)?; + + // let payload = response.json().await?; Ok(payload) } diff --git a/bolt-sidecar/src/client/mod.rs b/bolt-sidecar/src/client/mod.rs index 6dd49a4d7..314286660 100644 --- a/bolt-sidecar/src/client/mod.rs +++ b/bolt-sidecar/src/client/mod.rs @@ -5,3 +5,6 @@ pub mod rpc; // Re-export the beacon_api_client pub use beacon_api_client::mainnet::Client as BeaconClient; + +#[cfg(test)] +mod test_util; diff --git a/bolt-sidecar/src/client/test_util.rs b/bolt-sidecar/src/client/test_util.rs new file mode 100644 index 000000000..aad2a11ba --- /dev/null +++ b/bolt-sidecar/src/client/test_util.rs @@ -0,0 +1,100 @@ +#![allow(unused)] + +use beacon_api_client::VersionedValue; +use ethereum_consensus::{ + builder::SignedValidatorRegistration, + deneb::{ + self, + mainnet::{BlobsBundle, SignedBlindedBeaconBlock}, + }, + types::mainnet::ExecutionPayload, +}; +use reqwest::StatusCode; +use serde_json::Value; +use tokio::sync::watch; + +use crate::{ + api::{builder::GetHeaderParams, spec::BuilderApiError}, + primitives::{BatchedSignedConstraints, GetPayloadResponse, PayloadAndBlobs, SignedBuilderBid}, + BuilderApi, ConstraintsApi, +}; + +/// Create a `GetPayloadResponse` with a default `Deneb` execution payload. +pub fn make_get_payload_response() -> GetPayloadResponse { + let execution_payload = ExecutionPayload::Deneb(deneb::ExecutionPayload::default()); + + let blobs_bundle = BlobsBundle::default(); + + GetPayloadResponse::Deneb(PayloadAndBlobs { + execution_payload, + blobs_bundle, + }) +} + +pub struct MockMevBoost { + pub response_rx: watch::Receiver, +} + +impl MockMevBoost { + pub fn new() -> (Self, watch::Sender) { + let (response_tx, response_rx) = watch::channel(Value::Null); + (Self { response_rx }, response_tx) + } +} + +#[async_trait::async_trait] +impl BuilderApi for MockMevBoost { + async fn status(&self) -> Result { + Err(BuilderApiError::Generic( + "MockMevBoost does not support getting status".to_string(), + )) + } + + async fn register_validators( + &self, + _registrations: Vec, + ) -> Result<(), BuilderApiError> { + Err(BuilderApiError::Generic( + "MockMevBoost does not support registering validators".to_string(), + )) + } + + async fn get_header( + &self, + _params: GetHeaderParams, + ) -> Result { + let response = self.response_rx.borrow().clone(); + let bid = serde_json::from_value(response)?; + Ok(bid) + } + + async fn get_payload( + &self, + _signed_block: SignedBlindedBeaconBlock, + ) -> Result { + let response = self.response_rx.borrow().clone(); + let payload = serde_json::from_value(response)?; + Ok(payload) + } +} + +#[async_trait::async_trait] +impl ConstraintsApi for MockMevBoost { + async fn submit_constraints( + &self, + _constraints: &BatchedSignedConstraints, + ) -> Result<(), BuilderApiError> { + Err(BuilderApiError::Generic( + "MockMevBoost does not support submitting constraints".to_string(), + )) + } + + async fn get_header_with_proofs( + &self, + _params: GetHeaderParams, + ) -> Result, BuilderApiError> { + let response = self.response_rx.borrow().clone(); + let bid = serde_json::from_value(response)?; + Ok(bid) + } +} diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 35406f6df..967411e4b 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -228,10 +228,8 @@ impl ExecutionState { self.slot = slot; // TODO: invalidate any state that we don't need anymore (will be based on block template) - let update = self - .client - .get_state_update(self.account_states.keys().collect::>(), block_number) - .await?; + let accounts = self.account_states.keys().collect::>(); + let update = self.client.get_state_update(accounts, block_number).await?; self.apply_state_update(update); From eaffe0b8217e6e25ea7b1330c2026b1f0296f5c3 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Fri, 12 Jul 2024 10:41:38 +0200 Subject: [PATCH 07/48] wip: save res to file for debugging --- bolt-sidecar/src/client/mevboost.rs | 8 +++++--- bolt-sidecar/src/client/test_util.rs | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bolt-sidecar/src/client/mevboost.rs b/bolt-sidecar/src/client/mevboost.rs index e07c2af2f..b9ba78157 100644 --- a/bolt-sidecar/src/client/mevboost.rs +++ b/bolt-sidecar/src/client/mevboost.rs @@ -128,9 +128,11 @@ impl BuilderApi for MevBoostClient { } // TODO: rm after debugging - let px = response.json::().await?; - tracing::info!("get_payload json response received: {:?}", px); - let payload = serde_json::from_value(px)?; + let px = response.text().await?; + tracing::info!("get_payload json response received: {}", px); + let mut file = std::fs::File::create("get_payload_response.json").unwrap(); + std::io::Write::write_all(&mut file, px.as_bytes()).unwrap(); + let payload = serde_json::from_str(&px)?; // let payload = response.json().await?; diff --git a/bolt-sidecar/src/client/test_util.rs b/bolt-sidecar/src/client/test_util.rs index aad2a11ba..3440dcef2 100644 --- a/bolt-sidecar/src/client/test_util.rs +++ b/bolt-sidecar/src/client/test_util.rs @@ -98,3 +98,7 @@ impl ConstraintsApi for MockMevBoost { Ok(bid) } } + +// fn decode_payload() { +// let stringified = r#""#; +// } From e472775285b17e87b5ad83d11e27636bfdb50e9b Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Fri, 12 Jul 2024 11:27:53 +0200 Subject: [PATCH 08/48] fix: get payload response deserialization --- bolt-sidecar/src/client/mevboost.rs | 9 +- .../test_util/deneb_get_payload_response.json | 137 ++++++++++++++++++ .../client/{test_util.rs => test_util/mod.rs} | 12 +- bolt-sidecar/src/primitives/mod.rs | 23 +-- 4 files changed, 148 insertions(+), 33 deletions(-) create mode 100644 bolt-sidecar/src/client/test_util/deneb_get_payload_response.json rename bolt-sidecar/src/client/{test_util.rs => test_util/mod.rs} (88%) diff --git a/bolt-sidecar/src/client/mevboost.rs b/bolt-sidecar/src/client/mevboost.rs index b9ba78157..5988c280c 100644 --- a/bolt-sidecar/src/client/mevboost.rs +++ b/bolt-sidecar/src/client/mevboost.rs @@ -127,14 +127,7 @@ impl BuilderApi for MevBoostClient { return Err(BuilderApiError::FailedGettingPayload(error)); } - // TODO: rm after debugging - let px = response.text().await?; - tracing::info!("get_payload json response received: {}", px); - let mut file = std::fs::File::create("get_payload_response.json").unwrap(); - std::io::Write::write_all(&mut file, px.as_bytes()).unwrap(); - let payload = serde_json::from_str(&px)?; - - // let payload = response.json().await?; + let payload = response.json().await?; Ok(payload) } diff --git a/bolt-sidecar/src/client/test_util/deneb_get_payload_response.json b/bolt-sidecar/src/client/test_util/deneb_get_payload_response.json new file mode 100644 index 000000000..abf2dbc5c --- /dev/null +++ b/bolt-sidecar/src/client/test_util/deneb_get_payload_response.json @@ -0,0 +1,137 @@ +{ + "version": "deneb", + "data": { + "execution_payload": { + "parent_hash": "0xaa37d684b11d0fa6ec387322e036d2724d22e1570d8a56f5f33192bc5a6071af", + "fee_recipient": "0x614561D2d143621E126e87831AEF287678B442b8", + "state_root": "0x8be14a13156d04c96a91d44289c26e8947430a80ff70811b9802b71a63ca4587", + "receipts_root": "0x9595d62192ec5d8c9282e38f738641938d55be51fa3987f1d5a4de9f0f2a402e", + "logs_bloom": "0x00200000000000000000020080000000000000000000000000000000004000000000000000202000000000000080200080000000000000004002000040200000000080000000000000040008000008201000000000000000000000000800000000000200000000200000140000000000080400000000000080000010000000000000000000000100000000000000000000002000200010080000004000000000020000000000200000000000001004040000200000000000000000000000000000000002000001000000000000000000020400000800001000000000400000000010000000000000000000000000000000008000000000200000000000000000", + "prev_randao": "0x5c5e6cbe95e5aca976d839b8d22aecc14a9373e2e02dfc719010e54fbd1b0a59", + "block_number": "139277", + "gas_limit": "30000000", + "gas_used": "419268", + "timestamp": "1720775112", + "extra_data": "0x426f6c74204275696c646572", + "base_fee_per_gas": "7", + "block_hash": "0x7cccf27d4db8a513dc49836c1a86cd46cdff7a7fcc9f6fea3d8313624871bbef", + "transactions": [ + "0x02f87f8501a2140cff82b58385012a05f20085012a05f20e8304119094fd5f85f5ff7c61b57e404ad29f33a6fd31200f24872386f26fc1000084579f8d2ac080a05d7fed7571ff64f39cf4e48eaf56379ae5c717269455d30051851e4d41fc660fa03b1dc40f862127a8ef69bafe88336bcd04902d79b8f5711f4dfb265a6eb21d94", + "0x02f9017b8501a2140cff8303dec685012a05f2008512a05f2000830249f094843669e5220036eddbaca89d8c8b5b82268a0fc580b901040cc7326300000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000022006292538e66f0000000000000000000000005ba38f2c245618e39f6fa067bf1dec304e73ff3c00000000000000000000000092f0ee29e6e1bf0f7c668317ada78f5774a6cb7f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000003fac6482aee49bf58515be2d3fb58378a8497cc9000000000000000000000000c6cc140787b02ae479a10e41169607000c0d44f6c080a00cf74c45dbe9ee1fb923118ec5ce9db8f88cd651196ed3f9d4f8f2a65827e611a04a6bc1d49a7e18b7c92e8f3614cae116b1832ceb311c81d54b2c87de1545f68f", + "0x03f902e58501a2140cff82301985012a05f2008501a13b8600832dc6c094f70f745d5d86ae14d1be5a99954870361166ec6c8477359400b90244ef16e8450000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001670100000000000000000000000000000010001302e31382e302d64657600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004115896cebbb4cf09200bcbe8d104ff241313a6eede040b5f2c3899e9e7afa92a25a549d5bb6b7c211983262a5d3ca8ca57c50693b1fa04559a0e6c5bab9cf8c121b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0843b9aca00e1a0019101fb28118ceccaabca22a47e35b9c3f12eb2dcb25e5c543d5b75e6cd841f01a01930332dabfdb3d1104fca86c86eeb664f68c897e9b44dda2d3ccbd024ec69eea03733b5d0b2505367077f5c2324fbead4e34aa540d5d5b8b7afee7e0c70b01c07", + "0x02f8708501a2140cff82012f800782520894b6c402298fcb88039bbfde70f5ace791f18cfac88707131d70870dc880c080a03aab1b17ecf28f85de43c7733611759b87d25ba885babacb6b4c625d715415eea03fb52cb7744ccb885906e42f6b9cf82e74b47a4b4b4072af2aa52a8dc472236e" + ], + "withdrawals": [ + { + "index": "572698", + "validator_index": "2131", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "3645" + }, + { + "index": "572699", + "validator_index": "2135", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "3645" + }, + { + "index": "572700", + "validator_index": "2139", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "3645" + }, + { + "index": "572701", + "validator_index": "2143", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "3645" + }, + { + "index": "572702", + "validator_index": "2144", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "3645" + }, + { + "index": "572703", + "validator_index": "1612", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "2430" + }, + { + "index": "572704", + "validator_index": "1621", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "2430" + }, + { + "index": "572705", + "validator_index": "1623", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "2430" + }, + { + "index": "572706", + "validator_index": "1626", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "2430" + }, + { + "index": "572707", + "validator_index": "1955", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "2430" + }, + { + "index": "572708", + "validator_index": "1959", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "2430" + }, + { + "index": "572709", + "validator_index": "1961", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "2430" + }, + { + "index": "572710", + "validator_index": "1966", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "2430" + }, + { + "index": "572711", + "validator_index": "1979", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "2430" + }, + { + "index": "572712", + "validator_index": "1994", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "2430" + }, + { + "index": "572713", + "validator_index": "1999", + "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", + "amount": "2430" + } + ], + "blob_gas_used": "131072", + "excess_blob_gas": "0" + }, + "blobs_bundle": { + "commitments": [ + "0xa20c71d1985996098aa63e8b5dc7b7fedb70de31478fe309dad3ac0e9b6d28d82be8e5e543021a0203dc785742e94b2f" + ], + "proofs": [ + "0xa2acaae116dc9dea269577cc750c4de598a387992943b18be092856c90eaa372a360aad98aa1ff88eb76423b544fca35" + ], + "blobs": [ + "0x000000000d789c3a00080000ffff00c100c10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + ] + } + } +} diff --git a/bolt-sidecar/src/client/test_util.rs b/bolt-sidecar/src/client/test_util/mod.rs similarity index 88% rename from bolt-sidecar/src/client/test_util.rs rename to bolt-sidecar/src/client/test_util/mod.rs index 3440dcef2..ad998c12f 100644 --- a/bolt-sidecar/src/client/test_util.rs +++ b/bolt-sidecar/src/client/test_util/mod.rs @@ -99,6 +99,12 @@ impl ConstraintsApi for MockMevBoost { } } -// fn decode_payload() { -// let stringified = r#""#; -// } +#[test] +fn test_decode_get_payload_response() { + let stringified = + std::fs::read_to_string("./src/client/test_util/deneb_get_payload_response.json") + .expect("failed to read get payload response file"); + + let parsed_response: GetPayloadResponse = + serde_json::from_str(&stringified).expect("failed to parse get payload response"); +} diff --git a/bolt-sidecar/src/primitives/mod.rs b/bolt-sidecar/src/primitives/mod.rs index c352131d5..51e191eb4 100644 --- a/bolt-sidecar/src/primitives/mod.rs +++ b/bolt-sidecar/src/primitives/mod.rs @@ -157,7 +157,7 @@ impl Default for PayloadAndBlobs { } } -#[derive(Debug, serde::Serialize)] +#[derive(Debug, serde::Serialize, serde::Deserialize)] #[serde(tag = "version", content = "data")] pub enum GetPayloadResponse { #[serde(rename = "bellatrix")] @@ -191,27 +191,6 @@ impl GetPayloadResponse { } } -impl<'de> serde::Deserialize<'de> for GetPayloadResponse { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let value = serde_json::Value::deserialize(deserializer)?; - if let Ok(inner) = <_ as serde::Deserialize>::deserialize(&value) { - return Ok(Self::Capella(inner)); - } - if let Ok(inner) = <_ as serde::Deserialize>::deserialize(&value) { - return Ok(Self::Deneb(inner)); - } - if let Ok(inner) = <_ as serde::Deserialize>::deserialize(&value) { - return Ok(Self::Bellatrix(inner)); - } - Err(serde::de::Error::custom( - "no variant could be deserialized from input for GetPayloadResponse", - )) - } -} - /// A struct representing the current chain head. #[derive(Debug, Clone)] pub struct ChainHead { From faa0fc2fb8c1da7d6e6b783663c547f9137a405d Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Fri, 12 Jul 2024 16:18:38 +0200 Subject: [PATCH 09/48] chore: minor changes --- bolt-sidecar/src/api/builder.rs | 4 ++-- bolt-sidecar/src/state/head_tracker.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bolt-sidecar/src/api/builder.rs b/bolt-sidecar/src/api/builder.rs index 79596db30..e2d28f82e 100644 --- a/bolt-sidecar/src/api/builder.rs +++ b/bolt-sidecar/src/api/builder.rs @@ -127,7 +127,7 @@ where Ok(res) => match res { Err(builder_err) => builder_err, Ok(header) => { - tracing::debug!(elapsed = ?start.elapsed(), "Returning signed builder bid: {:?}", header); + tracing::debug!(elapsed = ?start.elapsed(), "Returning signed builder bid"); return Ok(Json(header)); } }, @@ -215,7 +215,7 @@ where }); }; - tracing::info!("Local block found, returning: {payload:?}"); + tracing::debug!("Local block found, returning: {payload:?}"); return Ok(Json(payload)); } diff --git a/bolt-sidecar/src/state/head_tracker.rs b/bolt-sidecar/src/state/head_tracker.rs index b52df6558..6acfc6ced 100644 --- a/bolt-sidecar/src/state/head_tracker.rs +++ b/bolt-sidecar/src/state/head_tracker.rs @@ -42,7 +42,7 @@ impl HeadTracker { let mut event_stream = match beacon_client.get_events::().await { Ok(events) => events, Err(err) => { - tracing::warn!("failed to subscribe to new heads topic: {:?}", err); + tracing::warn!(?err, "failed to subscribe to new heads topic, retrying..."); tokio::time::sleep(Duration::from_secs(1)).await; continue; } @@ -51,7 +51,7 @@ impl HeadTracker { let event = match event_stream.next().await { Some(Ok(event)) => event, Some(Err(err)) => { - tracing::warn!("error reading new head event stream: {:?}", err); + tracing::warn!(?err, "error reading new head event stream, retrying..."); tokio::time::sleep(Duration::from_secs(1)).await; continue; } @@ -62,8 +62,8 @@ impl HeadTracker { } }; - if let Err(e) = new_heads_tx.send(event) { - tracing::warn!("failed to broadcast new head event to subscribers: {:?}", e); + if let Err(err) = new_heads_tx.send(event) { + tracing::warn!(?err, "failed to broadcast new head event to subscribers"); } } }); From 40da7150607648b834c81fcadcfc7dac490f681f Mon Sep 17 00:00:00 2001 From: Jonas Bostoen Date: Fri, 12 Jul 2024 09:54:26 +0200 Subject: [PATCH 10/48] feat(sidecar): use PooledTransactionsElement to support blob sidecars --- bolt-sidecar/src/primitives/commitment.rs | 19 ++++++++----------- bolt-sidecar/src/primitives/constraint.rs | 2 +- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/bolt-sidecar/src/primitives/commitment.rs b/bolt-sidecar/src/primitives/commitment.rs index 9d8bbd8ce..27253549d 100644 --- a/bolt-sidecar/src/primitives/commitment.rs +++ b/bolt-sidecar/src/primitives/commitment.rs @@ -1,8 +1,8 @@ +use serde::{de, Deserialize, Deserializer, Serialize}; use std::str::FromStr; use alloy_primitives::{keccak256, Signature, B256}; -use reth_primitives::TransactionSigned; -use serde::{de, Deserialize, Deserializer, Serialize}; +use reth_primitives::PooledTransactionsElement; /// Commitment requests sent by users or RPC proxies to the sidecar. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] @@ -18,11 +18,8 @@ pub struct InclusionRequest { /// The consensus slot number at which the transaction should be included. pub slot: u64, /// The transaction to be included. - #[serde( - deserialize_with = "deserialize_tx_signed", - serialize_with = "serialize_tx_signed" - )] - pub tx: TransactionSigned, + #[serde(deserialize_with = "deserialize_tx", serialize_with = "serialize_tx")] + pub tx: PooledTransactionsElement, /// The signature over the "slot" and "tx" fields by the user. /// A valid signature is the only proof that the user actually requested /// this specific commitment to be included at the given slot. @@ -50,16 +47,16 @@ impl InclusionRequest { } } -fn deserialize_tx_signed<'de, D>(deserializer: D) -> Result +fn deserialize_tx<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; let data = hex::decode(s.trim_start_matches("0x")).map_err(de::Error::custom)?; - TransactionSigned::decode_enveloped(&mut data.as_slice()).map_err(de::Error::custom) + PooledTransactionsElement::decode_enveloped(&mut data.as_slice()).map_err(de::Error::custom) } -fn serialize_tx_signed(tx: &TransactionSigned, serializer: S) -> Result +fn serialize_tx(tx: &PooledTransactionsElement, serializer: S) -> Result where S: serde::Serializer, { @@ -94,7 +91,7 @@ impl InclusionRequest { pub fn digest(&self) -> B256 { let mut data = Vec::new(); data.extend_from_slice(&self.slot.to_le_bytes()); - data.extend_from_slice(self.tx.hash.as_slice()); + data.extend_from_slice(self.tx.hash().as_slice()); keccak256(&data) } diff --git a/bolt-sidecar/src/primitives/constraint.rs b/bolt-sidecar/src/primitives/constraint.rs index 2ad6cbc6d..5c4644c8f 100644 --- a/bolt-sidecar/src/primitives/constraint.rs +++ b/bolt-sidecar/src/primitives/constraint.rs @@ -110,7 +110,7 @@ impl Constraint { Self { tx: format!("0x{}", hex::encode(encoded_tx)), index, - tx_decoded: req.tx, + tx_decoded: req.tx.into_transaction(), sender, } } From f2d17a27fc5ee4740a7b821eaccbc01d3257ff73 Mon Sep 17 00:00:00 2001 From: Jonas Bostoen Date: Fri, 12 Jul 2024 10:47:44 +0200 Subject: [PATCH 11/48] feat(sidecar): integrate PooledTransactionsElement everywhere --- bolt-sidecar/bin/sidecar.rs | 15 +++++-- bolt-sidecar/src/builder/state_root.rs | 2 +- bolt-sidecar/src/builder/template.rs | 52 +++++++++++++++-------- bolt-sidecar/src/common.rs | 11 +++-- bolt-sidecar/src/primitives/constraint.rs | 23 ++++------ bolt-sidecar/src/primitives/mod.rs | 38 +++++++++++++++++ bolt-sidecar/src/state/execution.rs | 8 ++-- bolt-sidecar/src/state/mod.rs | 22 +++++----- 8 files changed, 117 insertions(+), 54 deletions(-) diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index 941d5782b..4d3a0ad46 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -67,6 +67,7 @@ async fn main() -> eyre::Result<()> { loop { tokio::select! { Some(ApiEvent { request, response_tx }) = api_events_rx.recv() => { + let start = std::time::Instant::now(); tracing::info!("Received commitment request: {:?}", request); let validator_index = match consensus_state.validate_request(&request) { @@ -79,7 +80,7 @@ async fn main() -> eyre::Result<()> { }; let sender = match execution_state - .check_commitment_validity(&request) + .validate_commitment_request(&request) .await { Ok(sender) => { sender }, @@ -93,8 +94,9 @@ async fn main() -> eyre::Result<()> { // TODO: match when we have more request types let CommitmentRequest::Inclusion(request) = request; tracing::info!( + elapsed = ?start.elapsed(), tx_hash = %request.tx.hash(), - "Validation against execution state passed" + "Commitment request validated" ); // TODO: review all this `clone` usage @@ -107,7 +109,14 @@ async fn main() -> eyre::Result<()> { execution_state.add_constraint(request.slot, signed_constraints.clone()); let res = serde_json::to_value(signed_constraints).map_err(Into::into); + let _ = response_tx.send(res); + + tracing::info!( + elapsed = ?start.elapsed(), + tx_hash = %request.tx.hash(), + "Processed commitment request" + ); }, Ok(HeadEvent { slot, .. }) = head_tracker.next_head() => { tracing::info!(slot, "Received new head event"); @@ -146,7 +155,7 @@ async fn main() -> eyre::Result<()> { } - if let Err(e) = local_builder.build_new_local_payload(template.transactions()).await { + if let Err(e) = local_builder.build_new_local_payload(template.as_signed_transactions()).await { tracing::error!(err = ?e, "CRITICAL: Error while building local payload at slot deadline for {slot}"); }; }, diff --git a/bolt-sidecar/src/builder/state_root.rs b/bolt-sidecar/src/builder/state_root.rs index 73aa92f37..98a21662a 100644 --- a/bolt-sidecar/src/builder/state_root.rs +++ b/bolt-sidecar/src/builder/state_root.rs @@ -15,7 +15,7 @@ mod tests { #[tokio::test] async fn test_trace_call() -> eyre::Result<()> { dotenvy::dotenv().ok(); - tracing_subscriber::fmt::init(); + let _ = tracing_subscriber::fmt::try_init(); tracing::info!("Starting test_trace_call"); diff --git a/bolt-sidecar/src/builder/template.rs b/bolt-sidecar/src/builder/template.rs index 356ddd8da..e42767c0f 100644 --- a/bolt-sidecar/src/builder/template.rs +++ b/bolt-sidecar/src/builder/template.rs @@ -7,7 +7,7 @@ use std::collections::HashMap; use alloy_primitives::{Address, U256}; -use reth_primitives::{TransactionSigned, TxType}; +use reth_primitives::{PooledTransactionsElement, TransactionSigned}; use crate::{ common::max_transaction_cost, @@ -46,11 +46,11 @@ impl BlockTemplate { .and_modify(|state| { state.balance = state .balance - .saturating_add(max_transaction_cost(&c.tx_decoded)); + .saturating_add(max_transaction_cost(&c.transaction)); state.transaction_count += 1; }) .or_insert(AccountState { - balance: max_transaction_cost(&c.tx_decoded), + balance: max_transaction_cost(&c.transaction), transaction_count: 1, }); }); @@ -72,10 +72,25 @@ impl BlockTemplate { /// Returns all a clone of all transactions from the signed constraints list #[inline] - pub fn transactions(&self) -> Vec { + pub fn transactions(&self) -> Vec { self.signed_constraints_list .iter() - .flat_map(|sc| sc.message.constraints.iter().map(|c| c.tx_decoded.clone())) + .flat_map(|sc| sc.message.constraints.iter().map(|c| c.transaction.clone())) + .collect() + } + + /// Converts the list of signed constraints into a list of signed transactions. Use this when building + /// a local execution payload. + #[inline] + pub fn as_signed_transactions(&self) -> Vec { + self.signed_constraints_list + .iter() + .flat_map(|sc| { + sc.message + .constraints + .iter() + .map(|c| c.transaction.clone().into_transaction()) + }) .collect() } @@ -90,25 +105,28 @@ impl BlockTemplate { /// Returns the blob count of the block template. #[inline] pub fn blob_count(&self) -> usize { - self.signed_constraints_list.iter().fold(0, |acc, sc| { - acc + sc - .message - .constraints - .iter() - .filter(|c| c.tx_decoded.tx_type() == TxType::Eip4844) - .count() + self.signed_constraints_list.iter().fold(0, |mut acc, sc| { + acc += sc.message.constraints.iter().fold(0, |acc, c| { + acc + c + .transaction + .as_eip4844() + .map(|tx| tx.blob_versioned_hashes.len()) + .unwrap_or(0) + }); + + acc }) } /// Remove all signed constraints at the specified index and updates the state diff fn remove_constraints_at_index(&mut self, index: usize) { let sc = self.signed_constraints_list.remove(index); - let mut address_to_txs: HashMap> = HashMap::new(); + let mut address_to_txs: HashMap> = HashMap::new(); sc.message.constraints.iter().for_each(|c| { address_to_txs .entry(c.sender) - .and_modify(|txs| txs.push(&c.tx_decoded)) - .or_insert(vec![&c.tx_decoded]); + .and_modify(|txs| txs.push(&c.transaction)) + .or_insert(vec![&c.transaction]); }); // Collect the diff for each address and every transaction @@ -157,11 +175,11 @@ impl BlockTemplate { .iter() .flat_map(|c| c.1.clone()) .fold((U256::ZERO, u64::MAX), |mut acc, c| { - let nonce = c.tx_decoded.nonce(); + let nonce = c.transaction.nonce(); if nonce < acc.1 { acc.1 = nonce; } - acc.0 += max_transaction_cost(&c.tx_decoded); + acc.0 += max_transaction_cost(&c.transaction); acc }); diff --git a/bolt-sidecar/src/common.rs b/bolt-sidecar/src/common.rs index 4e429bcce..8caa8b7c8 100644 --- a/bolt-sidecar/src/common.rs +++ b/bolt-sidecar/src/common.rs @@ -1,7 +1,10 @@ use alloy_primitives::U256; -use reth_primitives::TransactionSigned; +use reth_primitives::PooledTransactionsElement; -use crate::{primitives::AccountState, state::ValidationError}; +use crate::{ + primitives::{AccountState, TransactionExt}, + state::ValidationError, +}; /// Calculates the max_basefee `slot_diff` blocks in the future given a current basefee (in gwei). /// Returns None if an overflow would occur. @@ -26,7 +29,7 @@ pub fn calculate_max_basefee(current: u128, block_diff: u64) -> Option { } /// Calculates the max transaction cost (gas + value) in wei. -pub fn max_transaction_cost(transaction: &TransactionSigned) -> U256 { +pub fn max_transaction_cost(transaction: &PooledTransactionsElement) -> U256 { let gas_limit = transaction.gas_limit() as u128; let fee_cap = transaction.max_fee_per_gas(); @@ -40,7 +43,7 @@ pub fn max_transaction_cost(transaction: &TransactionSigned) -> U256 { /// 2. The balance of the account must be higher than the transaction's max cost. pub fn validate_transaction( account_state: &AccountState, - transaction: &TransactionSigned, + transaction: &PooledTransactionsElement, ) -> Result<(), ValidationError> { // Check if the nonce is correct (should be the same as the transaction count) if transaction.nonce() < account_state.transaction_count { diff --git a/bolt-sidecar/src/primitives/constraint.rs b/bolt-sidecar/src/primitives/constraint.rs index 5c4644c8f..6cdfd2857 100644 --- a/bolt-sidecar/src/primitives/constraint.rs +++ b/bolt-sidecar/src/primitives/constraint.rs @@ -1,5 +1,5 @@ use alloy_primitives::{keccak256, Address}; -use reth_primitives::TransactionSigned; +use reth_primitives::PooledTransactionsElement; use secp256k1::Message; use serde::{Deserialize, Serialize}; @@ -57,7 +57,7 @@ impl ConstraintsMessage { request: InclusionRequest, sender: Address, ) -> Self { - let constraints = vec![Constraint::from_inclusion_request(request, None, sender)]; + let constraints = vec![Constraint::from_transaction(request.tx, None, sender)]; Self { validator_index, slot, @@ -85,13 +85,10 @@ impl SignableBLS for ConstraintsMessage { /// A general constraint on block building. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Constraint { - /// The raw transaction that needs to be included in the block - pub tx: String, /// The optional index at which the transaction needs to be included in the block pub index: Option, - /// The decoded transaction for internal use - #[serde(skip)] - pub(crate) tx_decoded: TransactionSigned, + /// The transaction to be included in the block + pub(crate) transaction: PooledTransactionsElement, /// The ec-recovered address of the transaction sender for internal use #[serde(skip)] pub(crate) sender: Address, @@ -99,18 +96,14 @@ pub struct Constraint { impl Constraint { /// Builds a constraint from an inclusion request and an optional index - pub fn from_inclusion_request( - req: InclusionRequest, + pub fn from_transaction( + transaction: PooledTransactionsElement, index: Option, sender: Address, ) -> Self { - let mut encoded_tx = Vec::new(); - req.tx.encode_enveloped(&mut encoded_tx); - Self { - tx: format!("0x{}", hex::encode(encoded_tx)), + transaction, index, - tx_decoded: req.tx.into_transaction(), sender, } } @@ -119,7 +112,7 @@ impl Constraint { /// TODO: remove if we go with SSZ pub fn as_bytes(&self) -> Vec { let mut data = Vec::new(); - data.extend_from_slice(self.tx.as_bytes()); + self.transaction.encode_enveloped(&mut data); data.extend_from_slice(&self.index.unwrap_or(0).to_le_bytes()); data } diff --git a/bolt-sidecar/src/primitives/mod.rs b/bolt-sidecar/src/primitives/mod.rs index 51e191eb4..35579926b 100644 --- a/bolt-sidecar/src/primitives/mod.rs +++ b/bolt-sidecar/src/primitives/mod.rs @@ -17,6 +17,7 @@ use ethereum_consensus::{ types::mainnet::ExecutionPayload, Fork, }; +use reth_primitives::{PooledTransactionsElement, TxType}; use tokio::sync::{mpsc, oneshot}; /// Commitment types, received by users wishing to receive preconfirmations. @@ -219,3 +220,40 @@ impl ChainHead { self.block.load(std::sync::atomic::Ordering::SeqCst) } } + +/// Trait that exposes additional information on transaction types that don't already do it +/// by themselves (e.g. [`PooledTransactionsElement`]). +pub trait TransactionExt { + fn gas_limit(&self) -> u64; + fn value(&self) -> U256; + fn tx_type(&self) -> TxType; +} + +impl TransactionExt for PooledTransactionsElement { + fn gas_limit(&self) -> u64 { + match self { + PooledTransactionsElement::Legacy { transaction, .. } => transaction.gas_limit, + PooledTransactionsElement::Eip2930 { transaction, .. } => transaction.gas_limit, + PooledTransactionsElement::Eip1559 { transaction, .. } => transaction.gas_limit, + PooledTransactionsElement::BlobTransaction(blob_tx) => blob_tx.transaction.gas_limit, + } + } + + fn value(&self) -> U256 { + match self { + PooledTransactionsElement::Legacy { transaction, .. } => transaction.value, + PooledTransactionsElement::Eip2930 { transaction, .. } => transaction.value, + PooledTransactionsElement::Eip1559 { transaction, .. } => transaction.value, + PooledTransactionsElement::BlobTransaction(blob_tx) => blob_tx.transaction.value, + } + } + + fn tx_type(&self) -> TxType { + match self { + PooledTransactionsElement::Legacy { .. } => TxType::Legacy, + PooledTransactionsElement::Eip2930 { .. } => TxType::Eip2930, + PooledTransactionsElement::Eip1559 { .. } => TxType::Eip1559, + PooledTransactionsElement::BlobTransaction(_) => TxType::Eip4844, + } + } +} diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 967411e4b..75ebc620b 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -8,7 +8,7 @@ use thiserror::Error; use crate::{ builder::BlockTemplate, common::{calculate_max_basefee, validate_transaction}, - primitives::{AccountState, CommitmentRequest, SignedConstraints, Slot}, + primitives::{AccountState, CommitmentRequest, SignedConstraints, Slot, TransactionExt}, }; use super::fetcher::StateFetcher; @@ -126,10 +126,10 @@ impl ExecutionState { /// timing or proposer slot targets. /// /// If the commitment is invalid because of nonce, basefee or balance errors, it will return an error. - /// If the commitment is valid, it will be added to the block template and its account state + /// If the commitment is valid, its account state /// will be cached. If this is succesful, any callers can be sure that the commitment is valid /// and SHOULD sign it and respond to the requester. - pub async fn check_commitment_validity( + pub async fn validate_commitment_request( &mut self, request: &CommitmentRequest, ) -> Result { @@ -167,6 +167,8 @@ impl ExecutionState { return Err(ValidationError::BaseFeeTooLow(max_basefee as u128)); } + // let transaction = req.tx.into_transaction(); + // If we have the account state, use it here if let Some(account_state) = self.account_state(&sender) { // Validate the transaction against the account state diff --git a/bolt-sidecar/src/state/mod.rs b/bolt-sidecar/src/state/mod.rs index 83cc21195..812368abf 100644 --- a/bolt-sidecar/src/state/mod.rs +++ b/bolt-sidecar/src/state/mod.rs @@ -80,7 +80,7 @@ mod tests { use execution::{ExecutionState, ValidationError}; use fetcher::StateClient; use reqwest::Url; - use reth_primitives::TransactionSigned; + use reth_primitives::PooledTransactionsElement; use tracing_subscriber::fmt; use crate::{ @@ -131,7 +131,7 @@ mod tests { // Trick to parse into the TransactionSigned type let tx_signed_bytes = signed.encoded_2718(); let tx_signed = - TransactionSigned::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); + PooledTransactionsElement::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); let request = CommitmentRequest::Inclusion(InclusionRequest { slot: 10, @@ -139,7 +139,7 @@ mod tests { signature: sig, }); - assert!(state.check_commitment_validity(&request).await.is_ok()); + assert!(state.validate_commitment_request(&request).await.is_ok()); } #[tokio::test] @@ -167,7 +167,7 @@ mod tests { // Trick to parse into the TransactionSigned type let tx_signed_bytes = signed.encoded_2718(); let tx_signed = - TransactionSigned::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); + PooledTransactionsElement::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); let request = CommitmentRequest::Inclusion(InclusionRequest { slot: 10, @@ -176,7 +176,7 @@ mod tests { }); assert!(matches!( - state.check_commitment_validity(&request).await, + state.validate_commitment_request(&request).await, Err(ValidationError::NonceTooHigh) )); } @@ -207,7 +207,7 @@ mod tests { // Trick to parse into the TransactionSigned type let tx_signed_bytes = signed.encoded_2718(); let tx_signed = - TransactionSigned::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); + PooledTransactionsElement::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); let request = CommitmentRequest::Inclusion(InclusionRequest { slot: 10, @@ -216,7 +216,7 @@ mod tests { }); assert!(matches!( - state.check_commitment_validity(&request).await, + state.validate_commitment_request(&request).await, Err(ValidationError::InsufficientBalance) )); } @@ -248,7 +248,7 @@ mod tests { // Trick to parse into the TransactionSigned type let tx_signed_bytes = signed.encoded_2718(); let tx_signed = - TransactionSigned::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); + PooledTransactionsElement::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); let request = CommitmentRequest::Inclusion(InclusionRequest { slot: 10, @@ -257,7 +257,7 @@ mod tests { }); assert!(matches!( - state.check_commitment_validity(&request).await, + state.validate_commitment_request(&request).await, Err(ValidationError::BaseFeeTooLow(_)) )); } @@ -287,7 +287,7 @@ mod tests { // Trick to parse into the TransactionSigned type let tx_signed_bytes = signed.encoded_2718(); let tx_signed = - TransactionSigned::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); + PooledTransactionsElement::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); let request = CommitmentRequest::Inclusion(InclusionRequest { slot: 10, @@ -295,7 +295,7 @@ mod tests { signature: sig, }); - assert!(state.check_commitment_validity(&request).await.is_ok()); + assert!(state.validate_commitment_request(&request).await.is_ok()); assert!(state.block_templates().get(&10).unwrap().transactions_len() == 1); let provider = ProviderBuilder::new().on_http(anvil.endpoint_url()); From 1ea93e9a74f0d3bb1ff0a546eb63acffa76c7970 Mon Sep 17 00:00:00 2001 From: Jonas Bostoen Date: Fri, 12 Jul 2024 15:02:35 +0200 Subject: [PATCH 12/48] fix(sidecar): integration + fix tests --- bolt-sidecar/bin/sidecar.rs | 16 ++-- bolt-sidecar/src/builder/state_root.rs | 6 +- bolt-sidecar/src/builder/template.rs | 102 +++++++--------------- bolt-sidecar/src/client/rpc.rs | 12 +++ bolt-sidecar/src/crypto/bls.rs | 7 ++ bolt-sidecar/src/primitives/commitment.rs | 5 +- bolt-sidecar/src/state/execution.rs | 52 ++++++++--- bolt-sidecar/src/state/fetcher.rs | 11 ++- bolt-sidecar/src/state/mod.rs | 37 ++++++-- 9 files changed, 144 insertions(+), 104 deletions(-) diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index 4d3a0ad46..e2c0a55e9 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -83,7 +83,7 @@ async fn main() -> eyre::Result<()> { .validate_commitment_request(&request) .await { - Ok(sender) => { sender }, + Ok(sender) => sender, Err(e) => { tracing::error!("Failed to commit request: {:?}", e); let _ = response_tx.send(Err(ApiError::Custom(e.to_string()))); @@ -96,7 +96,7 @@ async fn main() -> eyre::Result<()> { tracing::info!( elapsed = ?start.elapsed(), tx_hash = %request.tx.hash(), - "Commitment request validated" + "Validation against execution state passed" ); // TODO: review all this `clone` usage @@ -108,15 +108,9 @@ async fn main() -> eyre::Result<()> { execution_state.add_constraint(request.slot, signed_constraints.clone()); - let res = serde_json::to_value(signed_constraints).map_err(Into::into); - - let _ = response_tx.send(res); - tracing::info!( - elapsed = ?start.elapsed(), - tx_hash = %request.tx.hash(), - "Processed commitment request" - ); + let res = serde_json::to_value(signed_constraints).map_err(Into::into); + let _ = response_tx.send(res).ok(); }, Ok(HeadEvent { slot, .. }) = head_tracker.next_head() => { tracing::info!(slot, "Received new head event"); @@ -142,7 +136,7 @@ async fn main() -> eyre::Result<()> { let max_retries = 5; let mut i = 0; 'inner: while let Err(e) = mevboost_client - .submit_constraints(&template.signed_constraints_list) + .submit_constraints(&template.constraints) .await { tracing::error!(err = ?e, "Error submitting constraints, retrying..."); diff --git a/bolt-sidecar/src/builder/state_root.rs b/bolt-sidecar/src/builder/state_root.rs index 98a21662a..a23d93f67 100644 --- a/bolt-sidecar/src/builder/state_root.rs +++ b/bolt-sidecar/src/builder/state_root.rs @@ -17,9 +17,13 @@ mod tests { dotenvy::dotenv().ok(); let _ = tracing_subscriber::fmt::try_init(); + let Some(rpc_url) = std::env::var("RPC_URL").ok() else { + tracing::warn!("RPC_URL not found in environment variables, skipping test"); + return Ok(()); + }; + tracing::info!("Starting test_trace_call"); - let rpc_url = std::env::var("RPC_URL").expect("RPC_URL must be set"); let rpc_url = Url::parse(&rpc_url).unwrap(); let client = RpcClient::new(rpc_url.clone()); diff --git a/bolt-sidecar/src/builder/template.rs b/bolt-sidecar/src/builder/template.rs index e42767c0f..1973e84fc 100644 --- a/bolt-sidecar/src/builder/template.rs +++ b/bolt-sidecar/src/builder/template.rs @@ -28,7 +28,7 @@ pub struct BlockTemplate { /// The state diffs per address given the list of commitments. state_diff: StateDiff, /// The signed constraints associated to the block - pub signed_constraints_list: Vec, + pub constraints: Vec, } impl BlockTemplate { @@ -37,43 +37,10 @@ impl BlockTemplate { &self.state_diff } - /// Adds a transaction to the block template and updates the state diff. - pub fn add_constraints(&mut self, signed_constraints: SignedConstraints) { - let mut address_to_state_diffs: HashMap = HashMap::new(); - signed_constraints.message.constraints.iter().for_each(|c| { - address_to_state_diffs - .entry(c.sender) - .and_modify(|state| { - state.balance = state - .balance - .saturating_add(max_transaction_cost(&c.transaction)); - state.transaction_count += 1; - }) - .or_insert(AccountState { - balance: max_transaction_cost(&c.transaction), - transaction_count: 1, - }); - }); - - // Now update intermediate state - address_to_state_diffs.iter().for_each(|(address, diff)| { - self.state_diff - .diffs - .entry(*address) - .and_modify(|(nonce, balance)| { - *nonce += diff.transaction_count; - *balance += diff.balance; - }) - .or_insert((diff.transaction_count, diff.balance)); - }); - - self.signed_constraints_list.push(signed_constraints); - } - - /// Returns all a clone of all transactions from the signed constraints list + /// Returns the cloned list of transactions from the constraints. #[inline] pub fn transactions(&self) -> Vec { - self.signed_constraints_list + self.constraints .iter() .flat_map(|sc| sc.message.constraints.iter().map(|c| c.transaction.clone())) .collect() @@ -83,7 +50,7 @@ impl BlockTemplate { /// a local execution payload. #[inline] pub fn as_signed_transactions(&self) -> Vec { - self.signed_constraints_list + self.constraints .iter() .flat_map(|sc| { sc.message @@ -97,7 +64,7 @@ impl BlockTemplate { /// Returns the length of the transactions in the block template. #[inline] pub fn transactions_len(&self) -> usize { - self.signed_constraints_list + self.constraints .iter() .fold(0, |acc, sc| acc + sc.message.constraints.len()) } @@ -105,7 +72,7 @@ impl BlockTemplate { /// Returns the blob count of the block template. #[inline] pub fn blob_count(&self) -> usize { - self.signed_constraints_list.iter().fold(0, |mut acc, sc| { + self.constraints.iter().fold(0, |mut acc, sc| { acc += sc.message.constraints.iter().fold(0, |acc, c| { acc + c .transaction @@ -118,38 +85,34 @@ impl BlockTemplate { }) } + /// Adds a list of constraints to the block template and updates the state diff. + pub fn add_constraints(&mut self, constraints: SignedConstraints) { + for constraint in constraints.message.constraints.iter() { + let max_cost = max_transaction_cost(&constraint.transaction); + self.state_diff + .diffs + .entry(constraint.sender) + .and_modify(|(nonce, balance)| { + *nonce += 1; + *balance += max_cost; + }) + .or_insert((1, max_cost)); + } + + self.constraints.push(constraints); + } + /// Remove all signed constraints at the specified index and updates the state diff fn remove_constraints_at_index(&mut self, index: usize) { - let sc = self.signed_constraints_list.remove(index); - let mut address_to_txs: HashMap> = HashMap::new(); - sc.message.constraints.iter().for_each(|c| { - address_to_txs - .entry(c.sender) - .and_modify(|txs| txs.push(&c.transaction)) - .or_insert(vec![&c.transaction]); - }); - - // Collect the diff for each address and every transaction - let address_to_diff: HashMap = address_to_txs - .iter() - .map(|(address, txs)| { - let mut state = AccountState::default(); - for tx in txs { - state.balance = state.balance.saturating_add(max_transaction_cost(tx)); - state.transaction_count = state.transaction_count.saturating_sub(1); - } - (*address, state) - }) - .collect(); + let constraints = self.constraints.remove(index); - // Update intermediate state - for (address, diff) in address_to_diff.iter() { + for constraint in constraints.message.constraints.iter() { self.state_diff .diffs - .entry(*address) + .entry(constraint.sender) .and_modify(|(nonce, balance)| { - *nonce = nonce.saturating_sub(diff.transaction_count); - *balance += diff.balance; + *nonce = nonce.saturating_sub(1); + *balance -= max_transaction_cost(&constraint.transaction); }); } } @@ -161,7 +124,7 @@ impl BlockTemplate { // The pre-confirmations made by such address, and the indexes of the signed constraints // in which they appear let constraints_with_address: Vec<(usize, Vec<&Constraint>)> = self - .signed_constraints_list + .constraints .iter() .enumerate() .map(|(idx, c)| (idx, &c.message.constraints)) @@ -184,13 +147,12 @@ impl BlockTemplate { }); if state.balance < max_total_cost || state.transaction_count > min_nonce { - // NOTE: We drop all the signed constraints containing such pre-confirmations - // since at least one of them has been invalidated. + // Remove invalidated constraints due to balance / nonce of chain state tracing::warn!( %address, - "Removing all signed constraints which contain such address pre-confirmations due to conflict with account state", + "Removing invalidated constraints for address" ); - indexes = constraints_with_address.iter().map(|c| c.0).collect(); + indexes = constraints_with_address.iter().map(|(i, _)| *i).collect(); } for index in indexes.into_iter().rev() { diff --git a/bolt-sidecar/src/client/rpc.rs b/bolt-sidecar/src/client/rpc.rs index 5696e62db..cba55d1a4 100644 --- a/bolt-sidecar/src/client/rpc.rs +++ b/bolt-sidecar/src/client/rpc.rs @@ -50,6 +50,18 @@ impl RpcClient { Ok(fee_history.latest_block_base_fee().unwrap()) } + /// Get the blob basefee of the latest block. + pub async fn get_blob_basefee(&self, block_number: Option) -> TransportResult { + let tag = block_number.map_or(BlockNumberOrTag::Latest, BlockNumberOrTag::Number); + + let fee_history: FeeHistory = self + .0 + .request("eth_feeHistory", (U64::from(1), tag, &[] as &[f64])) + .await?; + + Ok(fee_history.latest_block_blob_base_fee().unwrap_or(0)) + } + /// Get the latest block number pub async fn get_head(&self) -> TransportResult { let result: U64 = self.0.request("eth_blockNumber", ()).await?; diff --git a/bolt-sidecar/src/crypto/bls.rs b/bolt-sidecar/src/crypto/bls.rs index 122690d7c..e06257135 100644 --- a/bolt-sidecar/src/crypto/bls.rs +++ b/bolt-sidecar/src/crypto/bls.rs @@ -62,6 +62,13 @@ impl Signer { Self { key } } + /// Create a signer with a random BLS key. + pub fn random() -> Self { + Self { + key: random_bls_secret(), + } + } + /// Verify the signature of the object with the given public key. #[allow(dead_code)] pub fn verify( diff --git a/bolt-sidecar/src/primitives/commitment.rs b/bolt-sidecar/src/primitives/commitment.rs index 27253549d..98a127d64 100644 --- a/bolt-sidecar/src/primitives/commitment.rs +++ b/bolt-sidecar/src/primitives/commitment.rs @@ -34,10 +34,7 @@ impl InclusionRequest { /// Validates the transaction fee against a minimum basefee. /// Returns true if the fee is greater than or equal to the min, false otherwise. pub fn validate_basefee(&self, min: u128) -> bool { - if self.tx.max_fee_per_gas() < min { - return false; - } - true + self.tx.max_fee_per_gas() >= min } /// Validates the transaction chain id against the provided chain id. diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 75ebc620b..92683900b 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -1,14 +1,16 @@ use alloy_eips::eip4844::MAX_BLOBS_PER_BLOCK; use alloy_primitives::{Address, SignatureError}; use alloy_transport::TransportError; -use reth_primitives::transaction::TxType; +use reth_primitives::{ + revm_primitives::EnvKzgSettings, BlobTransactionValidationError, PooledTransactionsElement, +}; use std::{collections::HashMap, num::NonZero}; use thiserror::Error; use crate::{ builder::BlockTemplate, common::{calculate_max_basefee, validate_transaction}, - primitives::{AccountState, CommitmentRequest, SignedConstraints, Slot, TransactionExt}, + primitives::{AccountState, CommitmentRequest, SignedConstraints, Slot}, }; use super::fetcher::StateFetcher; @@ -17,8 +19,14 @@ use super::fetcher::StateFetcher; #[derive(Debug, Error)] pub enum ValidationError { /// The transaction fee is too low to cover the maximum base fee. - #[error("Transaction fee is too low, need {0} gwei to cover the maximum base fee")] + #[error("Transaction fee is too low, need {0} gwei to cover the maximum basefee")] BaseFeeTooLow(u128), + /// The transaction blob fee is too low to cover the maximum blob base fee. + #[error("Transaction blob fee is too low, need {0} gwei to cover the maximum blob basefee")] + BlobBaseFeeTooLow(u128), + /// The transaction blob is invalid. + #[error(transparent)] + BlobValidation(#[from] BlobTransactionValidationError), /// The transaction nonce is too low. #[error("Transaction nonce too low")] NonceTooLow, @@ -69,12 +77,12 @@ impl ValidationError { pub struct ExecutionState { /// The latest block number. block_number: u64, - /// The latest slot number. slot: u64, - - /// The base fee at the head block. + /// The basefee at the head block. basefee: u128, + /// The blob basefee at the head block. + blob_basefee: u128, /// The cached account states. This should never be read directly. /// These only contain the canonical account states at the head block, /// not the intermediate states. @@ -88,6 +96,8 @@ pub struct ExecutionState { chain_id: u64, /// The maximum number of commitments per slot. max_commitments_per_slot: NonZero, + /// The KZG settings for validating blobs. + kzg_settings: EnvKzgSettings, /// The state fetcher client. client: C, } @@ -99,13 +109,19 @@ impl ExecutionState { client: C, max_commitments_per_slot: NonZero, ) -> Result { + let (basefee, blob_basefee) = + tokio::try_join!(client.get_basefee(None), client.get_blob_basefee(None))?; + Ok(Self { - basefee: client.get_basefee(None).await?, + basefee, + blob_basefee, block_number: client.get_head().await?, slot: 0, account_states: HashMap::new(), block_templates: HashMap::new(), chain_id: client.get_chain_id().await?, + // Load the default KZG settings + kzg_settings: EnvKzgSettings::default(), max_commitments_per_slot, client, }) @@ -129,6 +145,8 @@ impl ExecutionState { /// If the commitment is valid, its account state /// will be cached. If this is succesful, any callers can be sure that the commitment is valid /// and SHOULD sign it and respond to the requester. + /// + /// TODO: should also validate everything in https://github.com/paradigmxyz/reth/blob/9aa44e1a90b262c472b14cd4df53264c649befc2/crates/transaction-pool/src/validate/eth.rs#L153 pub async fn validate_commitment_request( &mut self, request: &CommitmentRequest, @@ -167,8 +185,6 @@ impl ExecutionState { return Err(ValidationError::BaseFeeTooLow(max_basefee as u128)); } - // let transaction = req.tx.into_transaction(); - // If we have the account state, use it here if let Some(account_state) = self.account_state(&sender) { // Validate the transaction against the account state @@ -193,14 +209,27 @@ impl ExecutionState { } // Check EIP-4844-specific limits - if req.tx.tx_type() == TxType::Eip4844 { + if let Some(transaction) = req.tx.as_eip4844() { if let Some(template) = self.block_templates.get(&req.slot) { if template.blob_count() >= MAX_BLOBS_PER_BLOCK { return Err(ValidationError::Eip4844Limit); } } - // TODO: check max_fee_per_blob_gas against the blob_base_fee + let PooledTransactionsElement::BlobTransaction(ref blob_transaction) = req.tx else { + unreachable!("EIP-4844 transaction should be a blob transaction") + }; + + // Calculate max possible increase in blob basefee + let max_blob_basefee = calculate_max_basefee(self.blob_basefee, slot_diff) + .ok_or(reject_internal("Overflow calculating max blob basefee"))?; + + if blob_transaction.transaction.max_fee_per_blob_gas < max_blob_basefee { + return Err(ValidationError::BlobBaseFeeTooLow(max_blob_basefee)); + } + + // Validate blob against KZG settings + transaction.validate_blob(&blob_transaction.sidecar, self.kzg_settings.get())?; } Ok(sender) @@ -302,6 +331,7 @@ impl ExecutionState { pub struct StateUpdate { pub account_states: HashMap, pub min_basefee: u128, + pub min_blob_basefee: u128, pub block_number: u64, } diff --git a/bolt-sidecar/src/state/fetcher.rs b/bolt-sidecar/src/state/fetcher.rs index 2df3b150e..6f9a5341f 100644 --- a/bolt-sidecar/src/state/fetcher.rs +++ b/bolt-sidecar/src/state/fetcher.rs @@ -33,6 +33,8 @@ pub trait StateFetcher { async fn get_basefee(&self, block_number: Option) -> Result; + async fn get_blob_basefee(&self, block_number: Option) -> Result; + async fn get_account_state( &self, address: &Address, @@ -105,12 +107,14 @@ impl StateFetcher for StateClient { batch.send().await?; let basefee = self.client.get_basefee(None); + let blob_basefee = self.client.get_blob_basefee(None); // Collect the results - let (nonce_vec, balance_vec, basefee) = tokio::join!( + let (nonce_vec, balance_vec, basefee, blob_basefee) = tokio::join!( nonce_futs.collect::>(), balance_futs.collect::>(), basefee, + blob_basefee, ); // Insert the results @@ -145,6 +149,7 @@ impl StateFetcher for StateClient { Ok(StateUpdate { account_states, min_basefee: basefee?, + min_blob_basefee: blob_basefee?, block_number, }) } @@ -157,6 +162,10 @@ impl StateFetcher for StateClient { self.client.get_basefee(block_number).await } + async fn get_blob_basefee(&self, block_number: Option) -> Result { + self.client.get_blob_basefee(block_number).await + } + async fn get_account_state( &self, address: &Address, diff --git a/bolt-sidecar/src/state/mod.rs b/bolt-sidecar/src/state/mod.rs index 812368abf..7b17c67b4 100644 --- a/bolt-sidecar/src/state/mod.rs +++ b/bolt-sidecar/src/state/mod.rs @@ -84,7 +84,8 @@ mod tests { use tracing_subscriber::fmt; use crate::{ - primitives::{CommitmentRequest, InclusionRequest}, + crypto::{bls::Signer, SignableBLS, SignerBLS}, + primitives::{CommitmentRequest, ConstraintsMessage, InclusionRequest, SignedConstraints}, test_util::{default_test_transaction, launch_anvil}, }; @@ -266,6 +267,8 @@ mod tests { async fn test_invalidate_inclusion_request() { let _ = fmt::try_init(); + let target_slot = 10; + let anvil = launch_anvil(); let client = StateClient::new(Url::parse(&anvil.endpoint()).unwrap()); @@ -284,19 +287,37 @@ mod tests { let signer: EthereumWallet = wallet.into(); let signed = tx.build(&signer).await.unwrap(); + let bls_signer = Signer::random(); + // Trick to parse into the TransactionSigned type let tx_signed_bytes = signed.encoded_2718(); let tx_signed = PooledTransactionsElement::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); - let request = CommitmentRequest::Inclusion(InclusionRequest { - slot: 10, + let inclusion_request = InclusionRequest { + slot: target_slot, tx: tx_signed, signature: sig, - }); + }; + + let request = CommitmentRequest::Inclusion(inclusion_request.clone()); assert!(state.validate_commitment_request(&request).await.is_ok()); - assert!(state.block_templates().get(&10).unwrap().transactions_len() == 1); + + let message = ConstraintsMessage::build(0, target_slot, inclusion_request, sender); + let signature = bls_signer.sign(&message.digest()).unwrap().to_string(); + let signed_constraints = SignedConstraints { message, signature }; + + state.add_constraint(target_slot, signed_constraints.clone()); + + assert!( + state + .block_templates() + .get(&target_slot) + .unwrap() + .transactions_len() + == 1 + ); let provider = ProviderBuilder::new().on_http(anvil.endpoint_url()); @@ -314,7 +335,11 @@ mod tests { .await .unwrap(); - let transactions_len = state.block_templates().get(&10).unwrap().transactions_len(); + let transactions_len = state + .block_templates() + .get(&target_slot) + .unwrap() + .transactions_len(); assert!(transactions_len == 0); } } From 66879edc7373c2f1ebc60c7352334a7ef27cb144 Mon Sep 17 00:00:00 2001 From: Jonas Bostoen Date: Fri, 12 Jul 2024 15:10:08 +0200 Subject: [PATCH 13/48] fix(sidecar): remove stale templates + test --- bolt-sidecar/src/state/execution.rs | 3 ++ bolt-sidecar/src/state/mod.rs | 62 +++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 92683900b..c46dd2de9 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -264,6 +264,9 @@ impl ExecutionState { self.apply_state_update(update); + // Remove any block templates that are no longer valid + self.block_templates.remove(&slot); + Ok(()) } diff --git a/bolt-sidecar/src/state/mod.rs b/bolt-sidecar/src/state/mod.rs index 7b17c67b4..d8a127cf3 100644 --- a/bolt-sidecar/src/state/mod.rs +++ b/bolt-sidecar/src/state/mod.rs @@ -342,4 +342,66 @@ mod tests { .transactions_len(); assert!(transactions_len == 0); } + + #[tokio::test] + async fn test_invalidate_stale_template() { + let _ = fmt::try_init(); + + let target_slot = 10; + + let anvil = launch_anvil(); + let client = StateClient::new(Url::parse(&anvil.endpoint()).unwrap()); + + let mut state = ExecutionState::new(client, NonZero::new(1024).expect("valid non-zero")) + .await + .unwrap(); + + let wallet: PrivateKeySigner = anvil.keys()[0].clone().into(); + + let sender = anvil.addresses()[0]; + + let tx = default_test_transaction(sender, None); + + let sig = wallet.sign_message_sync(&hex!("abcd")).unwrap(); + + let signer: EthereumWallet = wallet.into(); + let signed = tx.build(&signer).await.unwrap(); + + let bls_signer = Signer::random(); + + // Trick to parse into the TransactionSigned type + let tx_signed_bytes = signed.encoded_2718(); + let tx_signed = + PooledTransactionsElement::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); + + let inclusion_request = InclusionRequest { + slot: target_slot, + tx: tx_signed, + signature: sig, + }; + + let request = CommitmentRequest::Inclusion(inclusion_request.clone()); + + assert!(state.validate_commitment_request(&request).await.is_ok()); + + let message = ConstraintsMessage::build(0, target_slot, inclusion_request, sender); + let signature = bls_signer.sign(&message.digest()).unwrap().to_string(); + let signed_constraints = SignedConstraints { message, signature }; + + state.add_constraint(target_slot, signed_constraints.clone()); + + assert!( + state + .block_templates() + .get(&target_slot) + .unwrap() + .transactions_len() + == 1 + ); + + // Update the head, which should invalidate the transaction due to a nonce conflict + state.update_head(None, target_slot).await.unwrap(); + + assert!(state.block_templates().get(&target_slot).is_none()); + } } From d61e8a76024b8e8985a01d00b17813629c4a71e6 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Mon, 15 Jul 2024 10:22:45 +0200 Subject: [PATCH 14/48] chore(sidecar): ignore trace call test since it's slow and we're using trace calls in prod --- bolt-sidecar/src/builder/state_root.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/bolt-sidecar/src/builder/state_root.rs b/bolt-sidecar/src/builder/state_root.rs index a23d93f67..4d7b48411 100644 --- a/bolt-sidecar/src/builder/state_root.rs +++ b/bolt-sidecar/src/builder/state_root.rs @@ -12,6 +12,7 @@ mod tests { use crate::{builder::CallTraceManager, client::rpc::RpcClient}; + #[ignore] #[tokio::test] async fn test_trace_call() -> eyre::Result<()> { dotenvy::dotenv().ok(); From 5c48b8e9629761d68228cc18ab04c253c020dec0 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Mon, 15 Jul 2024 10:24:19 +0200 Subject: [PATCH 15/48] chore: addressed review comments --- bolt-sidecar/bin/sidecar.rs | 2 +- bolt-sidecar/src/builder/state_root.rs | 10 ++++++---- bolt-sidecar/src/builder/template.rs | 16 ++++++++-------- bolt-sidecar/src/client/rpc.rs | 7 +++++-- bolt-sidecar/src/primitives/constraint.rs | 2 +- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index e2c0a55e9..d83a97e8c 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -136,7 +136,7 @@ async fn main() -> eyre::Result<()> { let max_retries = 5; let mut i = 0; 'inner: while let Err(e) = mevboost_client - .submit_constraints(&template.constraints) + .submit_constraints(&template.signed_constraints_list) .await { tracing::error!(err = ?e, "Error submitting constraints, retrying..."); diff --git a/bolt-sidecar/src/builder/state_root.rs b/bolt-sidecar/src/builder/state_root.rs index 4d7b48411..d2d1b23e5 100644 --- a/bolt-sidecar/src/builder/state_root.rs +++ b/bolt-sidecar/src/builder/state_root.rs @@ -10,7 +10,9 @@ mod tests { use partial_mpt::StateTrie; use reqwest::Url; - use crate::{builder::CallTraceManager, client::rpc::RpcClient}; + use crate::{ + builder::CallTraceManager, client::rpc::RpcClient, test_util::try_get_execution_api_url, + }; #[ignore] #[tokio::test] @@ -18,14 +20,14 @@ mod tests { dotenvy::dotenv().ok(); let _ = tracing_subscriber::fmt::try_init(); - let Some(rpc_url) = std::env::var("RPC_URL").ok() else { - tracing::warn!("RPC_URL not found in environment variables, skipping test"); + let Some(rpc_url) = try_get_execution_api_url().await else { + tracing::warn!("EL_RPC not reachable, skipping test"); return Ok(()); }; tracing::info!("Starting test_trace_call"); - let rpc_url = Url::parse(&rpc_url).unwrap(); + let rpc_url = Url::parse(rpc_url).unwrap(); let client = RpcClient::new(rpc_url.clone()); let (call_trace_manager, call_trace_handler) = CallTraceManager::new(rpc_url); diff --git a/bolt-sidecar/src/builder/template.rs b/bolt-sidecar/src/builder/template.rs index 1973e84fc..4c12701f4 100644 --- a/bolt-sidecar/src/builder/template.rs +++ b/bolt-sidecar/src/builder/template.rs @@ -28,7 +28,7 @@ pub struct BlockTemplate { /// The state diffs per address given the list of commitments. state_diff: StateDiff, /// The signed constraints associated to the block - pub constraints: Vec, + pub signed_constraints_list: Vec, } impl BlockTemplate { @@ -40,7 +40,7 @@ impl BlockTemplate { /// Returns the cloned list of transactions from the constraints. #[inline] pub fn transactions(&self) -> Vec { - self.constraints + self.signed_constraints_list .iter() .flat_map(|sc| sc.message.constraints.iter().map(|c| c.transaction.clone())) .collect() @@ -50,7 +50,7 @@ impl BlockTemplate { /// a local execution payload. #[inline] pub fn as_signed_transactions(&self) -> Vec { - self.constraints + self.signed_constraints_list .iter() .flat_map(|sc| { sc.message @@ -64,7 +64,7 @@ impl BlockTemplate { /// Returns the length of the transactions in the block template. #[inline] pub fn transactions_len(&self) -> usize { - self.constraints + self.signed_constraints_list .iter() .fold(0, |acc, sc| acc + sc.message.constraints.len()) } @@ -72,7 +72,7 @@ impl BlockTemplate { /// Returns the blob count of the block template. #[inline] pub fn blob_count(&self) -> usize { - self.constraints.iter().fold(0, |mut acc, sc| { + self.signed_constraints_list.iter().fold(0, |mut acc, sc| { acc += sc.message.constraints.iter().fold(0, |acc, c| { acc + c .transaction @@ -99,12 +99,12 @@ impl BlockTemplate { .or_insert((1, max_cost)); } - self.constraints.push(constraints); + self.signed_constraints_list.push(constraints); } /// Remove all signed constraints at the specified index and updates the state diff fn remove_constraints_at_index(&mut self, index: usize) { - let constraints = self.constraints.remove(index); + let constraints = self.signed_constraints_list.remove(index); for constraint in constraints.message.constraints.iter() { self.state_diff @@ -124,7 +124,7 @@ impl BlockTemplate { // The pre-confirmations made by such address, and the indexes of the signed constraints // in which they appear let constraints_with_address: Vec<(usize, Vec<&Constraint>)> = self - .constraints + .signed_constraints_list .iter() .enumerate() .map(|(idx, c)| (idx, &c.message.constraints)) diff --git a/bolt-sidecar/src/client/rpc.rs b/bolt-sidecar/src/client/rpc.rs index cba55d1a4..c57f6ab50 100644 --- a/bolt-sidecar/src/client/rpc.rs +++ b/bolt-sidecar/src/client/rpc.rs @@ -51,12 +51,15 @@ impl RpcClient { } /// Get the blob basefee of the latest block. + /// + /// Reference: https://github.com/ethereum/execution-apis/blob/main/src/eth/fee_market.yaml pub async fn get_blob_basefee(&self, block_number: Option) -> TransportResult { + let block_count = U64::from(1); let tag = block_number.map_or(BlockNumberOrTag::Latest, BlockNumberOrTag::Number); - + let reward_percentiles: Vec = vec![]; let fee_history: FeeHistory = self .0 - .request("eth_feeHistory", (U64::from(1), tag, &[] as &[f64])) + .request("eth_feeHistory", (block_count, tag, &reward_percentiles)) .await?; Ok(fee_history.latest_block_blob_base_fee().unwrap_or(0)) diff --git a/bolt-sidecar/src/primitives/constraint.rs b/bolt-sidecar/src/primitives/constraint.rs index 6cdfd2857..5543c8910 100644 --- a/bolt-sidecar/src/primitives/constraint.rs +++ b/bolt-sidecar/src/primitives/constraint.rs @@ -95,7 +95,7 @@ pub struct Constraint { } impl Constraint { - /// Builds a constraint from an inclusion request and an optional index + /// Builds a constraint from a transaction, with an optional index pub fn from_transaction( transaction: PooledTransactionsElement, index: Option, From 9a53ded9a05f7e859cc304b082f1c6f073626e2e Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Mon, 15 Jul 2024 10:29:10 +0200 Subject: [PATCH 16/48] chore(sidecar): pre-confirmation -> preconfirmation --- bolt-sidecar/src/builder/template.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bolt-sidecar/src/builder/template.rs b/bolt-sidecar/src/builder/template.rs index 4c12701f4..46edc332f 100644 --- a/bolt-sidecar/src/builder/template.rs +++ b/bolt-sidecar/src/builder/template.rs @@ -121,7 +121,7 @@ impl BlockTemplate { pub fn retain(&mut self, address: Address, state: AccountState) { let mut indexes: Vec = Vec::new(); - // The pre-confirmations made by such address, and the indexes of the signed constraints + // The preconfirmations made by such address, and the indexes of the signed constraints // in which they appear let constraints_with_address: Vec<(usize, Vec<&Constraint>)> = self .signed_constraints_list @@ -132,7 +132,7 @@ impl BlockTemplate { .map(|(idx, c)| (idx, c.iter().filter(|c| c.sender == address).collect())) .collect(); - // For every pre-confirmation, gather the max total balance cost, + // For every preconfirmation, gather the max total balance cost, // and find the one with the lowest nonce let (max_total_cost, min_nonce) = constraints_with_address .iter() From 34021ea024775a9d205ca6a4d01d1ffd9f033a73 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Mon, 15 Jul 2024 10:33:31 +0200 Subject: [PATCH 17/48] chore(sidecar): retain logic cleanup --- bolt-sidecar/src/builder/template.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/bolt-sidecar/src/builder/template.rs b/bolt-sidecar/src/builder/template.rs index 46edc332f..51516b951 100644 --- a/bolt-sidecar/src/builder/template.rs +++ b/bolt-sidecar/src/builder/template.rs @@ -137,13 +137,11 @@ impl BlockTemplate { let (max_total_cost, min_nonce) = constraints_with_address .iter() .flat_map(|c| c.1.clone()) - .fold((U256::ZERO, u64::MAX), |mut acc, c| { - let nonce = c.transaction.nonce(); - if nonce < acc.1 { - acc.1 = nonce; - } - acc.0 += max_transaction_cost(&c.transaction); - acc + .fold((U256::ZERO, u64::MAX), |(total_cost, min_nonce), c| { + ( + total_cost + max_transaction_cost(&c.transaction), + min_nonce.min(c.transaction.nonce()), + ) }); if state.balance < max_total_cost || state.transaction_count > min_nonce { From 8084f9347bc4371e980b1a53177e8d4117cfbf83 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Mon, 15 Jul 2024 10:38:05 +0200 Subject: [PATCH 18/48] fix(sidecar): max commitments reached error --- bolt-sidecar/src/state/execution.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index c46dd2de9..9fcd68ecd 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -40,8 +40,8 @@ pub enum ValidationError { #[error("Too many EIP-4844 transactions in target block")] Eip4844Limit, /// The maximum commitments have been reached for the slot. - #[error("Max commitments reached for slot {0}")] - MaxCommitmentsReachedForSlot(usize), + #[error("Max commitments reached for slot {0}: {1}")] + MaxCommitmentsReachedForSlot(u64, usize), /// The signature is invalid. #[error("Signature error: {0:?}")] Signature(#[from] SignatureError), @@ -162,6 +162,7 @@ impl ExecutionState { if let Some(template) = self.get_block_template(req.slot) { if template.transactions_len() >= self.max_commitments_per_slot.get() { return Err(ValidationError::MaxCommitmentsReachedForSlot( + self.slot, self.max_commitments_per_slot.get(), )); } From d4418b56771e493b28bfae9124b020935b5a9f1d Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Mon, 15 Jul 2024 10:54:29 +0200 Subject: [PATCH 19/48] chore(sidecar): chain_id method for pooled transaction type --- bolt-sidecar/src/primitives/commitment.rs | 2 ++ bolt-sidecar/src/primitives/mod.rs | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/bolt-sidecar/src/primitives/commitment.rs b/bolt-sidecar/src/primitives/commitment.rs index 98a127d64..dba6b0010 100644 --- a/bolt-sidecar/src/primitives/commitment.rs +++ b/bolt-sidecar/src/primitives/commitment.rs @@ -4,6 +4,8 @@ use std::str::FromStr; use alloy_primitives::{keccak256, Signature, B256}; use reth_primitives::PooledTransactionsElement; +use super::TransactionExt; + /// Commitment requests sent by users or RPC proxies to the sidecar. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(untagged)] diff --git a/bolt-sidecar/src/primitives/mod.rs b/bolt-sidecar/src/primitives/mod.rs index 35579926b..660c632bc 100644 --- a/bolt-sidecar/src/primitives/mod.rs +++ b/bolt-sidecar/src/primitives/mod.rs @@ -227,6 +227,7 @@ pub trait TransactionExt { fn gas_limit(&self) -> u64; fn value(&self) -> U256; fn tx_type(&self) -> TxType; + fn chain_id(&self) -> Option; } impl TransactionExt for PooledTransactionsElement { @@ -256,4 +257,15 @@ impl TransactionExt for PooledTransactionsElement { PooledTransactionsElement::BlobTransaction(_) => TxType::Eip4844, } } + + fn chain_id(&self) -> Option { + match self { + PooledTransactionsElement::Legacy { transaction, .. } => transaction.chain_id, + PooledTransactionsElement::Eip2930 { transaction, .. } => Some(transaction.chain_id), + PooledTransactionsElement::Eip1559 { transaction, .. } => Some(transaction.chain_id), + PooledTransactionsElement::BlobTransaction(blob_tx) => { + Some(blob_tx.transaction.chain_id) + } + } + } } From 6a00784626789e166de85b774dd1111fa7ed41bb Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Mon, 15 Jul 2024 11:49:42 +0200 Subject: [PATCH 20/48] chore(sidecar): manually decode hex chain_id --- bolt-sidecar/src/client/rpc.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/bolt-sidecar/src/client/rpc.rs b/bolt-sidecar/src/client/rpc.rs index c57f6ab50..b6ff5ec32 100644 --- a/bolt-sidecar/src/client/rpc.rs +++ b/bolt-sidecar/src/client/rpc.rs @@ -14,7 +14,7 @@ use alloy_primitives::{Address, B256, U256, U64}; use alloy_rpc_client::{self as alloy, Waiter}; use alloy_rpc_types::{Block, EIP1186AccountProofResponse, FeeHistory, TransactionRequest}; use alloy_rpc_types_trace::parity::{TraceResults, TraceType}; -use alloy_transport::TransportResult; +use alloy_transport::{TransportErrorKind, TransportResult}; use alloy_transport_http::Http; use reqwest::{Client, Url}; @@ -35,7 +35,17 @@ impl RpcClient { /// Get the chain ID. pub async fn get_chain_id(&self) -> TransportResult { - self.0.request("eth_chainId", ()).await + let chain_id: String = self.0.request("eth_chainId", ()).await?; + let chain_id = chain_id + .get(2..) + .ok_or(TransportErrorKind::Custom("not hex prefixed result".into()))?; + + let decoded = u64::from_str_radix(chain_id, 16).map_err(|e| { + TransportErrorKind::Custom( + format!("could not decode {} into u64: {}", chain_id, e).into(), + ) + })?; + Ok(decoded) } /// Get the basefee of the latest block. From 0e5ffa7ffecce7dc8c907e76e7f568f0deeb04a7 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Mon, 15 Jul 2024 15:30:38 +0200 Subject: [PATCH 21/48] chore(sidecar): validator indexes docs --- bolt-sidecar/src/config/validator_indexes.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bolt-sidecar/src/config/validator_indexes.rs b/bolt-sidecar/src/config/validator_indexes.rs index d9c9db5bd..54321f907 100644 --- a/bolt-sidecar/src/config/validator_indexes.rs +++ b/bolt-sidecar/src/config/validator_indexes.rs @@ -13,6 +13,7 @@ impl FromStr for ValidatorIndexes { type Err = eyre::Report; /// Parse an array of validator indexes. Accepted values: + /// - a single index (e.g. "1") /// - a comma-separated list of indexes (e.g. "1,2,3,4") /// - a contiguous range of indexes (e.g. "1..4") /// - a mix of the above (e.g. "1,2..4,6..8") @@ -57,6 +58,9 @@ mod tests { use super::ValidatorIndexes; use std::str::FromStr; + let indexes = ValidatorIndexes::from_str("1").unwrap(); + assert_eq!(indexes.0, vec![1]); + let indexes = ValidatorIndexes::from_str("1,2,3,4").unwrap(); assert_eq!(indexes.0, vec![1, 2, 3, 4]); From 9204aef61488ed3be11f490ffa6c5e5bb6fc9919 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Mon, 15 Jul 2024 17:22:52 +0200 Subject: [PATCH 22/48] fix(sidecar): constraint type is skipping raw tx bytes fields --- bolt-sidecar/bin/sidecar.rs | 3 +-- bolt-sidecar/src/primitives/commitment.rs | 5 +++- bolt-sidecar/src/primitives/constraint.rs | 28 ++++++++++++----------- bolt-sidecar/src/state/mod.rs | 4 ++-- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index d83a97e8c..b7c51d4ab 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -102,13 +102,12 @@ async fn main() -> eyre::Result<()> { // TODO: review all this `clone` usage // parse the request into constraints and sign them with the sidecar signer - let message = ConstraintsMessage::build(validator_index, request.slot, request.clone(), sender); + let message = ConstraintsMessage::build(validator_index, request.clone(), sender); let signature = signer.sign(&message.digest())?.to_string(); let signed_constraints = SignedConstraints { message, signature }; execution_state.add_constraint(request.slot, signed_constraints.clone()); - let res = serde_json::to_value(signed_constraints).map_err(Into::into); let _ = response_tx.send(res).ok(); }, diff --git a/bolt-sidecar/src/primitives/commitment.rs b/bolt-sidecar/src/primitives/commitment.rs index dba6b0010..da8c10c53 100644 --- a/bolt-sidecar/src/primitives/commitment.rs +++ b/bolt-sidecar/src/primitives/commitment.rs @@ -55,7 +55,10 @@ where PooledTransactionsElement::decode_enveloped(&mut data.as_slice()).map_err(de::Error::custom) } -fn serialize_tx(tx: &PooledTransactionsElement, serializer: S) -> Result +pub(crate) fn serialize_tx( + tx: &PooledTransactionsElement, + serializer: S, +) -> Result where S: serde::Serializer, { diff --git a/bolt-sidecar/src/primitives/constraint.rs b/bolt-sidecar/src/primitives/constraint.rs index 5543c8910..9281ed102 100644 --- a/bolt-sidecar/src/primitives/constraint.rs +++ b/bolt-sidecar/src/primitives/constraint.rs @@ -1,11 +1,11 @@ use alloy_primitives::{keccak256, Address}; use reth_primitives::PooledTransactionsElement; use secp256k1::Message; -use serde::{Deserialize, Serialize}; +use serde::Serialize; use crate::crypto::{ecdsa::SignableECDSA, SignableBLS}; -use super::InclusionRequest; +use super::{commitment::serialize_tx, InclusionRequest}; /// What the proposer sidecar will need to sign to confirm the inclusion request. impl SignableECDSA for ConstraintsMessage { @@ -30,7 +30,9 @@ impl SignableECDSA for ConstraintsMessage { pub type BatchedSignedConstraints = Vec; /// A container for a list of constraints and the signature of the proposer sidecar. -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +/// +/// Reference: https://chainbound.github.io/bolt-docs/api/builder-api#ethv1builderconstraints +#[derive(Serialize, Debug, Clone, PartialEq, Default)] pub struct SignedConstraints { /// The constraints that need to be signed. pub message: ConstraintsMessage, @@ -39,7 +41,9 @@ pub struct SignedConstraints { } /// A message that contains the constraints that need to be signed by the proposer sidecar. -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +/// +/// Reference: https://chainbound.github.io/bolt-docs/api/builder-api#ethv1builderconstraints +#[derive(Serialize, Debug, Clone, PartialEq, Default)] pub struct ConstraintsMessage { /// The validator index of the proposer sidecar. pub validator_index: u64, @@ -51,16 +55,11 @@ pub struct ConstraintsMessage { impl ConstraintsMessage { /// Builds a constraints message from an inclusion request and metadata - pub fn build( - validator_index: u64, - slot: u64, - request: InclusionRequest, - sender: Address, - ) -> Self { + pub fn build(validator_index: u64, request: InclusionRequest, sender: Address) -> Self { let constraints = vec![Constraint::from_transaction(request.tx, None, sender)]; Self { validator_index, - slot, + slot: request.slot, constraints, } } @@ -83,11 +82,14 @@ impl SignableBLS for ConstraintsMessage { } /// A general constraint on block building. -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +/// +/// Reference: https://chainbound.github.io/bolt-docs/api/builder-api#ethv1builderconstraints +#[derive(Serialize, Debug, Clone, PartialEq)] pub struct Constraint { /// The optional index at which the transaction needs to be included in the block pub index: Option, - /// The transaction to be included in the block + /// The transaction to be included in the block, in hex format + #[serde(rename(serialize = "tx"), serialize_with = "serialize_tx")] pub(crate) transaction: PooledTransactionsElement, /// The ec-recovered address of the transaction sender for internal use #[serde(skip)] diff --git a/bolt-sidecar/src/state/mod.rs b/bolt-sidecar/src/state/mod.rs index d8a127cf3..7a4f274f1 100644 --- a/bolt-sidecar/src/state/mod.rs +++ b/bolt-sidecar/src/state/mod.rs @@ -304,7 +304,7 @@ mod tests { assert!(state.validate_commitment_request(&request).await.is_ok()); - let message = ConstraintsMessage::build(0, target_slot, inclusion_request, sender); + let message = ConstraintsMessage::build(0, inclusion_request, sender); let signature = bls_signer.sign(&message.digest()).unwrap().to_string(); let signed_constraints = SignedConstraints { message, signature }; @@ -384,7 +384,7 @@ mod tests { assert!(state.validate_commitment_request(&request).await.is_ok()); - let message = ConstraintsMessage::build(0, target_slot, inclusion_request, sender); + let message = ConstraintsMessage::build(0, inclusion_request, sender); let signature = bls_signer.sign(&message.digest()).unwrap().to_string(); let signed_constraints = SignedConstraints { message, signature }; From 9ff23cecbdd40cdca5eac653d11bf583c87546b1 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Tue, 16 Jul 2024 15:49:19 +0200 Subject: [PATCH 23/48] fix(builder): fetch constraints when worker build payload and not on payload attributes, which is called immediately in the slot before the commitment deadline Co-authored-by: nicolas --- builder/builder/builder.go | 20 ++++---- builder/builder/eth_service.go | 26 ++++++----- builder/miner/multi_worker.go | 44 +++++++++--------- builder/miner/payload_building.go | 62 ++++++++++++++----------- builder/miner/worker.go | 35 ++++++++------ builder/miner/worker_test.go | 34 ++++++++------ mev-boost-relay/services/api/service.go | 2 + 7 files changed, 126 insertions(+), 97 deletions(-) diff --git a/builder/builder/builder.go b/builder/builder/builder.go index 4c0a9a3b9..913a199ed 100644 --- a/builder/builder/builder.go +++ b/builder/builder/builder.go @@ -177,6 +177,9 @@ func NewBuilder(args BuilderArgs) (*Builder, error) { } slotCtx, slotCtxCancel := context.WithCancel(context.Background()) + + constraintsCache := shardmap.NewFIFOMap[uint64, types.HashToConstraintDecoded](64, 16, shardmap.HashUint64) + return &Builder{ ds: args.ds, blockConsumer: args.blockConsumer, @@ -193,7 +196,7 @@ func NewBuilder(args BuilderArgs) (*Builder, error) { discardRevertibleTxOnErr: args.discardRevertibleTxOnErr, submissionOffsetFromEndOfSlot: args.submissionOffsetFromEndOfSlot, - constraintsCache: shardmap.NewFIFOMap[uint64, types.HashToConstraintDecoded](64, 16, shardmap.HashUint64), + constraintsCache: constraintsCache, limiter: args.limiter, slotCtx: slotCtx, @@ -418,7 +421,7 @@ func (b *Builder) Stop() error { } // BOLT: modify to calculate merkle inclusion proofs for preconfirmed transactions -func (b *Builder) onSealedBlock(opts SubmitBlockOpts, constraints types.HashToConstraintDecoded) error { +func (b *Builder) onSealedBlock(opts SubmitBlockOpts) error { executableData := engine.BlockToExecutableData(opts.Block, opts.BlockValue, opts.BlobSidecars) var dataVersion spec.DataVersion if b.eth.Config().IsCancun(opts.Block.Number(), opts.Block.Time()) { @@ -456,6 +459,10 @@ func (b *Builder) onSealedBlock(opts SubmitBlockOpts, constraints types.HashToCo var versionedBlockRequestWithPreconfsProofs *common.VersionedSubmitBlockRequestWithProofs + // BOLT: fetch constraints from the cache, which is automatically updated by the SSE subscription + constraints, _ := b.constraintsCache.Get(opts.PayloadAttributes.Slot) + log.Info(fmt.Sprintf("[BOLT]: Found %d constraints for slot %d", len(constraints), opts.PayloadAttributes.Slot)) + if len(constraints) > 0 { message := fmt.Sprintf("sealing block %d with %d constraints", opts.Block.Number(), len(constraints)) log.Info(message) @@ -495,6 +502,7 @@ func (b *Builder) onSealedBlock(opts SubmitBlockOpts, constraints types.HashToCo // NOTE: we can ignore preconfs for `processBuiltBlock` go b.processBuiltBlock(opts.Block, opts.BlockValue, opts.OrdersClosedAt, opts.SealedAt, opts.CommitedBundles, opts.AllBundles, opts.UsedSbundles, &blockBidMsg) if versionedBlockRequestWithPreconfsProofs != nil { + log.Info(fmt.Sprintf("[BOLT]: Sending sealed block to relay %s", versionedBlockRequestWithPreconfsProofs)) err = b.relay.SubmitBlockWithProofs(versionedBlockRequestWithPreconfsProofs, opts.ValidatorData) } else if len(constraints) == 0 { // If versionedBlockRequestWithPreconfsProofs is nil and no constraints, then we don't have proofs to send @@ -662,10 +670,6 @@ func (b *Builder) runBuildingJob(slotCtx context.Context, proposerPubkey phase0. log.Debug("runBuildingJob", "slot", attrs.Slot, "parent", attrs.HeadHash, "payloadTimestamp", uint64(attrs.Timestamp)) - // fetch constraints here - constraints, _ := b.constraintsCache.Get(attrs.Slot) - log.Info(fmt.Sprintf("[BOLT]: Got %d constraints for slot %d", len(constraints), attrs.Slot)) - submitBestBlock := func() { queueMu.Lock() if queueBestEntry.block.Hash() != queueLastSubmittedHash { @@ -682,7 +686,7 @@ func (b *Builder) runBuildingJob(slotCtx context.Context, proposerPubkey phase0. ValidatorData: vd, PayloadAttributes: attrs, } - err := b.onSealedBlock(submitBlockOpts, constraints) + err := b.onSealedBlock(submitBlockOpts) if err != nil { log.Error("could not run sealed block hook", "err", err) @@ -738,7 +742,7 @@ func (b *Builder) runBuildingJob(slotCtx context.Context, proposerPubkey phase0. "slot", attrs.Slot, "parent", attrs.HeadHash, "resubmit-interval", b.builderResubmitInterval.String()) - err := b.eth.BuildBlock(attrs, blockHook, constraints) + err := b.eth.BuildBlock(attrs, blockHook, b.constraintsCache) if err != nil { log.Warn("Failed to build block", "err", err) } diff --git a/builder/builder/eth_service.go b/builder/builder/eth_service.go index b17c7dfd8..4d692b022 100644 --- a/builder/builder/eth_service.go +++ b/builder/builder/eth_service.go @@ -5,6 +5,7 @@ import ( "math/big" "time" + "github.com/chainbound/shardmap" "github.com/ethereum/go-ethereum/beacon/engine" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -15,7 +16,7 @@ import ( ) type IEthereumService interface { - BuildBlock(attrs *types.BuilderPayloadAttributes, sealedBlockCallback miner.BlockHookFn, constraints types.HashToConstraintDecoded) error + BuildBlock(attrs *types.BuilderPayloadAttributes, sealedBlockCallback miner.BlockHookFn, constraintsCache *shardmap.FIFOMap[uint64, types.HashToConstraintDecoded]) error GetBlockByHash(hash common.Hash) *types.Block Config() *params.ChainConfig Synced() bool @@ -33,7 +34,7 @@ type testEthereumService struct { testPreconfs []*types.Transaction } -func (t *testEthereumService) BuildBlock(attrs *types.BuilderPayloadAttributes, sealedBlockCallback miner.BlockHookFn, constraints types.HashToConstraintDecoded) error { +func (t *testEthereumService) BuildBlock(attrs *types.BuilderPayloadAttributes, sealedBlockCallback miner.BlockHookFn, constraintsCache *shardmap.FIFOMap[uint64, types.HashToConstraintDecoded]) error { sealedBlockCallback(t.testBlock, t.testBlockValue, t.testBlobSidecar, time.Now(), t.testBundlesMerged, t.testAllBundles, t.testUsedSbundles) return nil } @@ -53,19 +54,20 @@ func NewEthereumService(eth *eth.Ethereum) *EthereumService { } // TODO: we should move to a setup similar to catalyst local blocks & payload ids -func (s *EthereumService) BuildBlock(attrs *types.BuilderPayloadAttributes, sealedBlockCallback miner.BlockHookFn, constraints types.HashToConstraintDecoded) error { +func (s *EthereumService) BuildBlock(attrs *types.BuilderPayloadAttributes, sealedBlockCallback miner.BlockHookFn, constraintsCache *shardmap.FIFOMap[uint64, types.HashToConstraintDecoded]) error { // Send a request to generate a full block in the background. // The result can be obtained via the returned channel. args := &miner.BuildPayloadArgs{ - Parent: attrs.HeadHash, - Timestamp: uint64(attrs.Timestamp), - FeeRecipient: attrs.SuggestedFeeRecipient, - GasLimit: attrs.GasLimit, - Random: attrs.Random, - Withdrawals: attrs.Withdrawals, - BeaconRoot: attrs.ParentBeaconBlockRoot, - BlockHook: sealedBlockCallback, - Constraints: constraints, + Parent: attrs.HeadHash, + Timestamp: uint64(attrs.Timestamp), + FeeRecipient: attrs.SuggestedFeeRecipient, + GasLimit: attrs.GasLimit, + Random: attrs.Random, + Withdrawals: attrs.Withdrawals, + BeaconRoot: attrs.ParentBeaconBlockRoot, + Slot: attrs.Slot, + BlockHook: sealedBlockCallback, + ConstraintsCache: constraintsCache, } payload, err := s.eth.Miner().BuildPayload(args) diff --git a/builder/miner/multi_worker.go b/builder/miner/multi_worker.go index af1a26580..602df2763 100644 --- a/builder/miner/multi_worker.go +++ b/builder/miner/multi_worker.go @@ -93,16 +93,17 @@ func (w *multiWorker) buildPayload(args *BuildPayloadArgs) (*Payload, error) { // to deliver for not missing slot. var empty *newPayloadResult emptyParams := &generateParams{ - timestamp: args.Timestamp, - forceTime: true, - parentHash: args.Parent, - coinbase: args.FeeRecipient, - random: args.Random, - gasLimit: args.GasLimit, - withdrawals: args.Withdrawals, - beaconRoot: args.BeaconRoot, - noTxs: true, - constraints: args.Constraints, + timestamp: args.Timestamp, + forceTime: true, + parentHash: args.Parent, + coinbase: args.FeeRecipient, + random: args.Random, + gasLimit: args.GasLimit, + withdrawals: args.Withdrawals, + beaconRoot: args.BeaconRoot, + noTxs: true, + slot: args.Slot, + constraintsCache: args.ConstraintsCache, } for _, worker := range w.workers { empty = worker.getSealingBlock(emptyParams) @@ -131,17 +132,18 @@ func (w *multiWorker) buildPayload(args *BuildPayloadArgs) (*Payload, error) { workerPayload := newPayload(empty.block, args.Id()) workerPayloads = append(workerPayloads, workerPayload) fullParams := &generateParams{ - timestamp: args.Timestamp, - forceTime: true, - parentHash: args.Parent, - coinbase: args.FeeRecipient, - random: args.Random, - withdrawals: args.Withdrawals, - beaconRoot: args.BeaconRoot, - gasLimit: args.GasLimit, - noTxs: false, - onBlock: args.BlockHook, - constraints: args.Constraints, + timestamp: args.Timestamp, + forceTime: true, + parentHash: args.Parent, + coinbase: args.FeeRecipient, + random: args.Random, + withdrawals: args.Withdrawals, + beaconRoot: args.BeaconRoot, + gasLimit: args.GasLimit, + noTxs: false, + onBlock: args.BlockHook, + slot: args.Slot, + constraintsCache: args.ConstraintsCache, } go func(w *worker) { diff --git a/builder/miner/payload_building.go b/builder/miner/payload_building.go index 6ba95abff..ed3a4fe1c 100644 --- a/builder/miner/payload_building.go +++ b/builder/miner/payload_building.go @@ -23,6 +23,7 @@ import ( "sync" "time" + "github.com/chainbound/shardmap" "github.com/ethereum/go-ethereum/beacon/engine" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -35,16 +36,17 @@ import ( // Check engine-api specification for more details. // https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#payloadattributesv3 type BuildPayloadArgs struct { - Parent common.Hash // The parent block to build payload on top - Timestamp uint64 // The provided timestamp of generated payload - FeeRecipient common.Address // The provided recipient address for collecting transaction fee - Random common.Hash // The provided randomness value - Withdrawals types.Withdrawals // The provided withdrawals - BeaconRoot *common.Hash // The provided beaconRoot (Cancun) - Version engine.PayloadVersion // Versioning byte for payload id calculation. - GasLimit uint64 - BlockHook BlockHookFn - Constraints types.HashToConstraintDecoded + Parent common.Hash // The parent block to build payload on top + Timestamp uint64 // The provided timestamp of generated payload + FeeRecipient common.Address // The provided recipient address for collecting transaction fee + Random common.Hash // The provided randomness value + Withdrawals types.Withdrawals // The provided withdrawals + BeaconRoot *common.Hash // The provided beaconRoot (Cancun) + Version engine.PayloadVersion // Versioning byte for payload id calculation. + GasLimit uint64 + BlockHook BlockHookFn + Slot uint64 + ConstraintsCache *shardmap.FIFOMap[uint64, types.HashToConstraintDecoded] } // Id computes an 8-byte identifier by hashing the components of the payload arguments. @@ -249,15 +251,17 @@ func (w *worker) buildPayload(args *BuildPayloadArgs) (*Payload, error) { // enough to run. The empty payload can at least make sure there is something // to deliver for not missing slot. emptyParams := &generateParams{ - timestamp: args.Timestamp, - forceTime: true, - parentHash: args.Parent, - coinbase: args.FeeRecipient, - random: args.Random, - withdrawals: args.Withdrawals, - beaconRoot: args.BeaconRoot, - noTxs: true, - onBlock: args.BlockHook, + timestamp: args.Timestamp, + forceTime: true, + parentHash: args.Parent, + coinbase: args.FeeRecipient, + random: args.Random, + withdrawals: args.Withdrawals, + beaconRoot: args.BeaconRoot, + noTxs: true, + onBlock: args.BlockHook, + slot: args.Slot, + constraintsCache: args.ConstraintsCache, } empty := w.getSealingBlock(emptyParams) if empty.err != nil { @@ -281,15 +285,17 @@ func (w *worker) buildPayload(args *BuildPayloadArgs) (*Payload, error) { endTimer := time.NewTimer(time.Second * 12) fullParams := &generateParams{ - timestamp: args.Timestamp, - forceTime: true, - parentHash: args.Parent, - coinbase: args.FeeRecipient, - random: args.Random, - withdrawals: args.Withdrawals, - beaconRoot: args.BeaconRoot, - noTxs: false, - onBlock: args.BlockHook, + timestamp: args.Timestamp, + forceTime: true, + parentHash: args.Parent, + coinbase: args.FeeRecipient, + random: args.Random, + withdrawals: args.Withdrawals, + beaconRoot: args.BeaconRoot, + noTxs: false, + onBlock: args.BlockHook, + slot: args.Slot, + constraintsCache: args.ConstraintsCache, } for { diff --git a/builder/miner/worker.go b/builder/miner/worker.go index 3a5b8363d..6400861a6 100644 --- a/builder/miner/worker.go +++ b/builder/miner/worker.go @@ -25,6 +25,7 @@ import ( "sync/atomic" "time" + "github.com/chainbound/shardmap" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" @@ -1250,17 +1251,18 @@ func (w *worker) commitTransactions(env *environment, plainTxs, blobTxs *transac // generateParams wraps various of settings for generating sealing task. type generateParams struct { - timestamp uint64 // The timestamp for sealing task - forceTime bool // Flag whether the given timestamp is immutable or not - parentHash common.Hash // Parent block hash, empty means the latest chain head - coinbase common.Address // The fee recipient address for including transaction - gasLimit uint64 // The validator's requested gas limit target - random common.Hash // The randomness generated by beacon chain, empty before the merge - withdrawals types.Withdrawals // List of withdrawals to include in block. - beaconRoot *common.Hash // The beacon root (cancun field). - noTxs bool // Flag whether an empty block without any transaction is expected - onBlock BlockHookFn // Callback to call for each produced block - constraints types.HashToConstraintDecoded // The preconfirmations to include in the block + timestamp uint64 // The timestamp for sealing task + forceTime bool // Flag whether the given timestamp is immutable or not + parentHash common.Hash // Parent block hash, empty means the latest chain head + coinbase common.Address // The fee recipient address for including transaction + gasLimit uint64 // The validator's requested gas limit target + random common.Hash // The randomness generated by beacon chain, empty before the merge + withdrawals types.Withdrawals // List of withdrawals to include in block. + beaconRoot *common.Hash // The beacon root (cancun field). + noTxs bool // Flag whether an empty block without any transaction is expected + onBlock BlockHookFn // Callback to call for each produced block + slot uint64 // The slot in which the block is being produced + constraintsCache *shardmap.FIFOMap[uint64, types.HashToConstraintDecoded] // The preconfirmations to include in the block } func doPrepareHeader(genParams *generateParams, chain *core.BlockChain, config *Config, chainConfig *params.ChainConfig, extra []byte, engine consensus.Engine) (*types.Header, *types.Header, error) { @@ -1745,7 +1747,14 @@ func (w *worker) generateWork(params *generateParams) *newPayloadResult { orderCloseTime := time.Now() - blockBundles, allBundles, usedSbundles, mempoolTxHashes, err := w.fillTransactionsSelectAlgo(nil, work, params.constraints) + var constraints types.HashToConstraintDecoded + + if params.constraintsCache != nil { + constraints, _ = params.constraintsCache.Get(params.slot) + log.Info(fmt.Sprintf("[BOLT]: found %d constraints for slot %d ", len(constraints), params.slot)) + } + + blockBundles, allBundles, usedSbundles, mempoolTxHashes, err := w.fillTransactionsSelectAlgo(nil, work, constraints) if err != nil { return &newPayloadResult{err: err} } @@ -1753,7 +1762,7 @@ func (w *worker) generateWork(params *generateParams) *newPayloadResult { // NOTE: as done with builder txs, we need to fill mempoolTxHashes with the constraints hashes // in order to pass block validation. Otherwise the constraints will be rejected as unknown // because they not part of the mempool and not part of the known bundles - for hash := range params.constraints { + for hash := range constraints { mempoolTxHashes[hash] = struct{}{} } diff --git a/builder/miner/worker_test.go b/builder/miner/worker_test.go index 16c9d9957..745a47618 100644 --- a/builder/miner/worker_test.go +++ b/builder/miner/worker_test.go @@ -24,6 +24,7 @@ import ( "testing" "time" + "github.com/chainbound/shardmap" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" @@ -77,8 +78,8 @@ var ( pendingTxs []*types.Transaction newTxs []*types.Transaction - // Test testConstraints - testConstraints = make(types.HashToConstraintDecoded) + // Test testConstraintsCache + testConstraintsCache = new(shardmap.FIFOMap[uint64, types.HashToConstraintDecoded]) testConfig = &Config{ Recommit: time.Second, @@ -121,7 +122,10 @@ func init() { } else { idx = nil } - testConstraints[tx1.Hash()] = &types.ConstraintDecoded{Index: idx, Tx: tx1} + constraints := make(map[common.Hash]*types.ConstraintDecoded) + constraints[tx1.Hash()] = &types.ConstraintDecoded{Index: idx, Tx: tx1} + // FIXME: slot 0 is probably not correct for these tests + testConstraintsCache.Put(0, constraints) } pendingTxs = append(pendingTxs, tx1) @@ -425,10 +429,10 @@ func TestGetSealingWorkWithConstraints(t *testing.T) { local := new(params.ChainConfig) *local = *ethashChainConfig local.TerminalTotalDifficulty = big.NewInt(0) - testGetSealingWork(t, local, ethash.NewFaker(), testConstraints) + testGetSealingWork(t, local, ethash.NewFaker(), testConstraintsCache) } -func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine, constraints types.HashToConstraintDecoded) { +func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine, constraintsCache *shardmap.FIFOMap[uint64, types.HashToConstraintDecoded]) { defer engine.Close() w, b := newTestWorker(t, chainConfig, engine, rawdb.NewMemoryDatabase(), nil, 0) defer w.close() @@ -520,16 +524,16 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co // This API should work even when the automatic sealing is not enabled for _, c := range cases { r := w.getSealingBlock(&generateParams{ - parentHash: c.parent, - timestamp: timestamp, - coinbase: c.coinbase, - random: c.random, - withdrawals: nil, - beaconRoot: nil, - noTxs: false, - forceTime: true, - onBlock: nil, - constraints: constraints, + parentHash: c.parent, + timestamp: timestamp, + coinbase: c.coinbase, + random: c.random, + withdrawals: nil, + beaconRoot: nil, + noTxs: false, + forceTime: true, + onBlock: nil, + constraintsCache: constraintsCache, }) if c.expectErr { if r.err == nil { diff --git a/mev-boost-relay/services/api/service.go b/mev-boost-relay/services/api/service.go index 9a313967b..d390d4369 100644 --- a/mev-boost-relay/services/api/service.go +++ b/mev-boost-relay/services/api/service.go @@ -2694,6 +2694,8 @@ func (api *RelayAPI) handleSubmitNewBlockWithProofs(w http.ResponseWriter, req * } } + log.Infof("Received block bid with proofs from builder: %s", payload) + // BOLT: Send an event to the web demo slot, _ := payload.Inner.Slot() message := fmt.Sprintf("received block bid with %d preconfirmations for slot %d", len(payload.Proofs.TransactionHashes), slot) From 2a4148319b311cf81a50292897f891a01856775b Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Tue, 16 Jul 2024 15:51:21 +0200 Subject: [PATCH 24/48] fix(sidecar): enforce invariant on local payload, which is set IFF we sign a local header Co-authored-by: nicolas --- bolt-sidecar/bin/sidecar.rs | 2 ++ bolt-sidecar/src/api/builder.rs | 38 ++++++++++++++------------- bolt-sidecar/src/builder/signature.rs | 2 +- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index b7c51d4ab..86601537e 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -131,6 +131,8 @@ async fn main() -> eyre::Result<()> { continue; }; + tracing::trace!(?template.signed_constraints_list, "Submitting constraints to MEV-Boost"); + // TODO: fix retry logic, and move this to separate task let max_retries = 5; let mut i = 0; diff --git a/bolt-sidecar/src/api/builder.rs b/bolt-sidecar/src/api/builder.rs index e2d28f82e..1864d0ee4 100644 --- a/bolt-sidecar/src/api/builder.rs +++ b/bolt-sidecar/src/api/builder.rs @@ -37,9 +37,7 @@ const GET_HEADER_WITH_PROOFS_TIMEOUT: Duration = Duration::from_millis(500); /// Forwards all requests to the target after interception. pub struct BuilderProxyServer { proxy_target: T, - // TODO: fill with local payload when we fetch a payload - // in failed get_header - // This will only be some in case of a failed get_header + /// INVARIANT: This will be `Some` IFF we have signed a local header for the latest slot. local_payload: Mutex>, /// The payload fetcher to get locally built payloads. payload_fetcher: P, @@ -127,6 +125,11 @@ where Ok(res) => match res { Err(builder_err) => builder_err, Ok(header) => { + // Clear the local payload cache if we have a successful response + // By definition of `server.local_payload`, this will be `Some` IFF we have signed a local header + let mut local_payload = server.local_payload.lock(); + *local_payload = None; + tracing::debug!(elapsed = ?start.elapsed(), "Returning signed builder bid"); return Ok(Json(header)); } @@ -137,33 +140,31 @@ where // On ANY error, we fall back to locally built block tracing::warn!(slot, elapsed = ?start.elapsed(), err = ?err, "Proxy error, fetching local payload instead"); - let payload = match server.payload_fetcher.fetch_payload(slot).await { - Some(payload) => { - tracing::info!(elapsed = ?start.elapsed(), "Fetched local payload for slot {slot}"); - payload - } + let payload_and_bid = match server.payload_fetcher.fetch_payload(slot).await { + Some(payload_and_bid) => payload_and_bid, None => { // TODO: handle failure? In this case, we don't have a fallback block - // which means we haven't made any commitments. This means the beacon client should + // which means we haven't made any commitments. This means the EL should // fallback to local block building. tracing::error!("No local payload produced for slot {slot}"); return Err(BuilderApiError::FailedToFetchLocalPayload(slot)); } }; - let hash = payload.bid.message.header.block_hash.clone(); - let number = payload.bid.message.header.block_number; + let hash = payload_and_bid.bid.message.header.block_hash.clone(); + let number = payload_and_bid.bid.message.header.block_number; + tracing::info!(elapsed = ?start.elapsed(), %hash, "Fetched local payload for slot {slot}"); { - // Set the payload for the following get_payload request + // Since we've signed a local header, set the payload for + // the following `get_payload` request. let mut local_payload = server.local_payload.lock(); - *local_payload = Some(payload.payload); + *local_payload = Some(payload_and_bid.payload); } let versioned_bid = VersionedValue:: { version: Fork::Deneb, - data: payload.bid, - // TODO: a more elegant way to do this? Can we avoid this meta field? + data: payload_and_bid.bid, meta: Default::default(), }; @@ -192,7 +193,8 @@ where e })?; - // If we have a locally built payload, return it and clear the cache. + // If we have a locally built payload, it means we signed a local header. + // Return it and clear the cache. if let Some(payload) = server.local_payload.lock().take() { let requested_block = &signed_blinded_block .message @@ -204,8 +206,8 @@ where // beacon node has signed, we are at risk of equivocation and slashing. if payload.block_hash() != requested_block { tracing::error!( - expected = requested_block.to_string(), - have = payload.block_hash().to_string(), + expected = %requested_block.to_string(), + have = %payload.block_hash().to_string(), "Local block hash does not match requested block hash" ); diff --git a/bolt-sidecar/src/builder/signature.rs b/bolt-sidecar/src/builder/signature.rs index b34f0ed65..1c7a77eb8 100644 --- a/bolt-sidecar/src/builder/signature.rs +++ b/bolt-sidecar/src/builder/signature.rs @@ -9,7 +9,7 @@ use tree_hash_derive::TreeHash; use crate::ChainConfig; -/// Sign a SSZ object a BLS secret key, using the Application Builder domain +/// Sign a SSZ object with a BLS secret key, using the Application Builder domain /// for signing arbitrary builder-api messages in the out-of-protocol specifications. /// /// Fun Note: we use a `blst` secret key to sign a message, and produce an `alloy` signature, From 79b38539997ad04f51215c53c5bc396b5cca8b70 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Mon, 15 Jul 2024 16:34:30 +0200 Subject: [PATCH 25/48] feat: populate blobs bundle when self-building --- bolt-sidecar/bin/sidecar.rs | 2 +- bolt-sidecar/src/builder/mod.rs | 9 +++--- bolt-sidecar/src/builder/template.rs | 44 +++++++++++++++++++++++++++- bolt-sidecar/src/primitives/mod.rs | 10 ++++++- 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index 86601537e..94708ac8c 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -150,7 +150,7 @@ async fn main() -> eyre::Result<()> { } - if let Err(e) = local_builder.build_new_local_payload(template.as_signed_transactions()).await { + if let Err(e) = local_builder.build_new_local_payload(&template).await { tracing::error!(err = ?e, "CRITICAL: Error while building local payload at slot deadline for {slot}"); }; }, diff --git a/bolt-sidecar/src/builder/mod.rs b/bolt-sidecar/src/builder/mod.rs index 16d20cf87..c49a69dfb 100644 --- a/bolt-sidecar/src/builder/mod.rs +++ b/bolt-sidecar/src/builder/mod.rs @@ -6,7 +6,6 @@ use ethereum_consensus::{ ssz::prelude::{List, MerkleizationError}, }; use payload_builder::FallbackPayloadBuilder; -use reth_primitives::TransactionSigned; use signature::sign_builder_message; use crate::{ @@ -99,8 +98,11 @@ impl LocalBuilder { /// pub async fn build_new_local_payload( &mut self, - transactions: Vec, + template: &BlockTemplate, ) -> Result<(), BuilderError> { + let transactions = template.as_signed_transactions(); + let blobs_bundle = template.as_blobs_bundle(); + // 1. build a fallback payload with the given transactions, on top of // the current head of the chain let sealed_block = self @@ -119,8 +121,7 @@ impl LocalBuilder { let eth_payload = compat::to_consensus_execution_payload(&sealed_block); let payload_and_blobs = PayloadAndBlobs { execution_payload: eth_payload, - // TODO: add included blobs here - blobs_bundle: Default::default(), + blobs_bundle, }; // 2. create a signed builder bid with the sealed block header we just created diff --git a/bolt-sidecar/src/builder/template.rs b/bolt-sidecar/src/builder/template.rs index 51516b951..7fe4eb95a 100644 --- a/bolt-sidecar/src/builder/template.rs +++ b/bolt-sidecar/src/builder/template.rs @@ -7,11 +7,15 @@ use std::collections::HashMap; use alloy_primitives::{Address, U256}; +use ethereum_consensus::{ + crypto::{KzgCommitment, KzgProof}, + deneb::mainnet::{Blob, BlobsBundle}, +}; use reth_primitives::{PooledTransactionsElement, TransactionSigned}; use crate::{ common::max_transaction_cost, - primitives::{constraint::Constraint, AccountState, SignedConstraints}, + primitives::{constraint::Constraint, AccountState, SignedConstraints, TransactionExt}, }; /// A block template that serves as a fallback block, but is also used @@ -61,6 +65,44 @@ impl BlockTemplate { .collect() } + /// Converts the list of signed constraints into a list of all blobs in all transactions + /// in the constraints. Use this when building a local execution payload. + #[inline] + pub fn as_blobs_bundle(&self) -> BlobsBundle { + let (commitments, proofs, blobs) = self + .signed_constraints_list + .iter() + .flat_map(|sc| sc.message.constraints.iter()) + .filter_map(|c| c.transaction.blob_sidecar()) + .fold( + (Vec::new(), Vec::new(), Vec::new()), + |(mut commitments, mut proofs, mut blobs), bs| { + commitments.extend( + bs.commitments + .iter() + .map(|c| KzgCommitment::try_from(c.as_slice()).unwrap()), + ); + proofs.extend( + bs.proofs + .iter() + .map(|p| KzgProof::try_from(p.as_slice()).unwrap()), + ); + blobs.extend( + bs.blobs + .iter() + .map(|b| Blob::try_from(b.as_slice()).unwrap()), + ); + (commitments, proofs, blobs) + }, + ); + + BlobsBundle { + commitments, + proofs, + blobs, + } + } + /// Returns the length of the transactions in the block template. #[inline] pub fn transactions_len(&self) -> usize { diff --git a/bolt-sidecar/src/primitives/mod.rs b/bolt-sidecar/src/primitives/mod.rs index 660c632bc..75c91eb95 100644 --- a/bolt-sidecar/src/primitives/mod.rs +++ b/bolt-sidecar/src/primitives/mod.rs @@ -17,7 +17,7 @@ use ethereum_consensus::{ types::mainnet::ExecutionPayload, Fork, }; -use reth_primitives::{PooledTransactionsElement, TxType}; +use reth_primitives::{BlobTransactionSidecar, PooledTransactionsElement, TxType}; use tokio::sync::{mpsc, oneshot}; /// Commitment types, received by users wishing to receive preconfirmations. @@ -228,6 +228,7 @@ pub trait TransactionExt { fn value(&self) -> U256; fn tx_type(&self) -> TxType; fn chain_id(&self) -> Option; + fn blob_sidecar(&self) -> Option<&BlobTransactionSidecar>; } impl TransactionExt for PooledTransactionsElement { @@ -268,4 +269,11 @@ impl TransactionExt for PooledTransactionsElement { } } } + + fn blob_sidecar(&self) -> Option<&BlobTransactionSidecar> { + match self { + PooledTransactionsElement::BlobTransaction(blob_tx) => Some(&blob_tx.sidecar), + _ => None, + } + } } From c175f899a6409e2593df2c2493b429904ab59e89 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Mon, 15 Jul 2024 10:19:16 +0200 Subject: [PATCH 26/48] wip: commitment test utils --- bolt-sidecar/bin/sidecar.rs | 9 ++-- bolt-sidecar/src/state/execution.rs | 78 +++++++++++++++++++++++------ bolt-sidecar/src/test_util.rs | 45 ++++++++++++++++- 3 files changed, 108 insertions(+), 24 deletions(-) diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index 94708ac8c..30decb895 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -73,19 +73,16 @@ async fn main() -> eyre::Result<()> { let validator_index = match consensus_state.validate_request(&request) { Ok(index) => index, Err(e) => { - tracing::error!("Failed to validate request: {:?}", e); + tracing::error!(err = ?e, "Failed to validate request"); let _ = response_tx.send(Err(ApiError::Custom(e.to_string()))); continue; } }; - let sender = match execution_state - .validate_commitment_request(&request) - .await - { + let sender = match execution_state.validate_commitment_request(&request).await { Ok(sender) => sender, Err(e) => { - tracing::error!("Failed to commit request: {:?}", e); + tracing::error!(err = ?e, "Failed to commit request"); let _ = response_tx.send(Err(ApiError::Custom(e.to_string()))); continue; } diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 9fcd68ecd..9212cd7ef 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -27,6 +27,9 @@ pub enum ValidationError { /// The transaction blob is invalid. #[error(transparent)] BlobValidation(#[from] BlobTransactionValidationError), + /// The max basefee calculation incurred an overflow error. + #[error("Invalid max basefee calculation: overflow")] + MaxBaseFeeCalcOverflow, /// The transaction nonce is too low. #[error("Transaction nonce too low")] NonceTooLow, @@ -87,7 +90,6 @@ pub struct ExecutionState { /// These only contain the canonical account states at the head block, /// not the intermediate states. account_states: HashMap, - /// The block templates by target SLOT NUMBER. /// We have multiple block templates because in rare cases we might have multiple /// proposal duties for a single lookahead. @@ -138,6 +140,7 @@ impl ExecutionState { } /// Validates the commitment request against state (historical + intermediate). + /// /// NOTE: This function only simulates against execution state, it does not consider /// timing or proposer slot targets. /// @@ -168,22 +171,23 @@ impl ExecutionState { } } - let sender = req.tx.recover_signer().ok_or(ValidationError::Internal( - "Failed to recover signer from transaction".to_string(), - ))?; + let sender = req + .tx + .recover_signer() + .ok_or(ValidationError::RecoverSigner)?; tracing::debug!(%sender, target_slot = req.slot, "Trying to commit inclusion request to block template"); // Check if the max_fee_per_gas would cover the maximum possible basefee. - let slot_diff = req.slot - self.slot; + let slot_diff = req.slot.saturating_sub(self.slot); // Calculate the max possible basefee given the slot diff let max_basefee = calculate_max_basefee(self.basefee, slot_diff) - .ok_or(reject_internal("Overflow calculating max basefee"))?; + .ok_or(ValidationError::MaxBaseFeeCalcOverflow)?; // Validate the base fee if !req.validate_basefee(max_basefee) { - return Err(ValidationError::BaseFeeTooLow(max_basefee as u128)); + return Err(ValidationError::BaseFeeTooLow(max_basefee)); } // If we have the account state, use it here @@ -194,11 +198,13 @@ impl ExecutionState { } else { tracing::debug!(address = %sender, "Unknown account state"); // If we don't have the account state, we need to fetch it - let account_state = self - .client - .get_account_state(&sender, None) - .await - .map_err(|e| reject_internal(&e.to_string()))?; + let account_state = + self.client + .get_account_state(&sender, None) + .await + .map_err(|e| { + ValidationError::Internal(format!("Failed to fetch account state: {:?}", e)) + })?; tracing::debug!(address = %sender, "Fetched account state: {account_state:?}"); @@ -223,7 +229,7 @@ impl ExecutionState { // Calculate max possible increase in blob basefee let max_blob_basefee = calculate_max_basefee(self.blob_basefee, slot_diff) - .ok_or(reject_internal("Overflow calculating max blob basefee"))?; + .ok_or(ValidationError::MaxBaseFeeCalcOverflow)?; if blob_transaction.transaction.max_fee_per_blob_gas < max_blob_basefee { return Err(ValidationError::BlobBaseFeeTooLow(max_blob_basefee)); @@ -259,7 +265,6 @@ impl ExecutionState { ) -> Result<(), TransportError> { self.slot = slot; - // TODO: invalidate any state that we don't need anymore (will be based on block template) let accounts = self.account_states.keys().collect::>(); let update = self.client.get_state_update(accounts, block_number).await?; @@ -339,6 +344,47 @@ pub struct StateUpdate { pub block_number: u64, } -fn reject_internal(reason: &str) -> ValidationError { - ValidationError::Internal(reason.to_string()) +#[cfg(test)] +mod tests { + use std::num::NonZero; + + use reqwest::Url; + + use crate::{ + state::{fetcher::StateFetcher, ExecutionState, StateClient, ValidationError}, + test_util::{create_signed_commitment_request, default_test_transaction, launch_anvil}, + }; + + #[tokio::test] + async fn test_check_commitment_validity() -> eyre::Result<()> { + let anvil = launch_anvil(); + let client = StateClient::new(Url::parse(&anvil.endpoint())?); + + let max_comms = NonZero::new(10).unwrap(); + let mut state = ExecutionState::new(client.clone(), max_comms).await?; + + let sender = anvil.addresses().first().unwrap(); + let sender_pk = anvil.keys().first().unwrap(); + + // initialize the state by updating the head once + let slot = client.get_head().await?; + state.update_head(None, slot).await?; + + let mut tx = default_test_transaction(*sender, None); + + // Base fee too low + tx.gas_price = Some(0); + let req = create_signed_commitment_request(tx.clone(), sender_pk, slot + 1).await?; + let res = state.validate_commitment_request(&req).await; + assert!(matches!(res, Err(ValidationError::BaseFeeTooLow(_)))); + + // Nonce too high + tx.gas_price = Some(1_000_000_000); + tx.nonce = Some(100); + let req = create_signed_commitment_request(tx, sender_pk, slot + 1).await?; + let res = state.validate_commitment_request(&req).await; + assert!(matches!(res, Err(ValidationError::NonceTooHigh))); + + Ok(()) + } } diff --git a/bolt-sidecar/src/test_util.rs b/bolt-sidecar/src/test_util.rs index 9708b24fe..f1b1aaa8d 100644 --- a/bolt-sidecar/src/test_util.rs +++ b/bolt-sidecar/src/test_util.rs @@ -1,12 +1,20 @@ -use alloy_network::TransactionBuilder; +use alloy_eips::eip2718::Encodable2718; +use alloy_network::{EthereumWallet, TransactionBuilder}; use alloy_node_bindings::{Anvil, AnvilInstance}; -use alloy_primitives::{Address, U256}; +use alloy_primitives::{keccak256, Address, B256, U256}; use alloy_rpc_types::TransactionRequest; +use alloy_signer::{ + k256::{ecdsa::SigningKey as K256SigningKey, SecretKey as K256SecretKey}, + Signer, +}; +use alloy_signer_local::PrivateKeySigner; use blst::min_pk::SecretKey; +use reth_primitives::TransactionSigned; use secp256k1::Message; use crate::{ crypto::{ecdsa::SignableECDSA, SignableBLS}, + primitives::{CommitmentRequest, InclusionRequest}, Config, }; @@ -130,3 +138,36 @@ impl SignableECDSA for TestSignableData { Message::from_digest_slice(as_32.as_slice()).expect("valid message") } } + +/// Create a valid signed commitment request for testing purposes +/// from the given transaction, private key of the sender, and slot. +pub(crate) async fn create_signed_commitment_request( + tx: TransactionRequest, + sk: &K256SecretKey, + slot: u64, +) -> eyre::Result { + let sk = K256SigningKey::from_slice(sk.to_bytes().as_slice())?; + let signer = PrivateKeySigner::from_signing_key(sk.clone()); + let wallet = EthereumWallet::from(signer.clone()); + + let tx_signed = tx.build(&wallet).await?; + let raw_encoded = tx_signed.encoded_2718(); + let tx_signed_reth = TransactionSigned::decode_enveloped(&mut raw_encoded.as_slice())?; + + let tx_hash = tx_signed_reth.hash(); + + let message_digest = { + let mut data = Vec::new(); + data.extend_from_slice(&slot.to_le_bytes()); + data.extend_from_slice(tx_hash.as_slice()); + B256::from(keccak256(data)) + }; + + let signature = signer.sign_hash(&message_digest).await?; + + Ok(CommitmentRequest::Inclusion(InclusionRequest { + tx: tx_signed_reth, + slot, + signature, + })) +} From a7cafca8a9796d2b586fbdb4b84e8a52d699ad29 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Mon, 15 Jul 2024 10:36:27 +0200 Subject: [PATCH 27/48] chore: small nit --- bolt-sidecar/src/test_util.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bolt-sidecar/src/test_util.rs b/bolt-sidecar/src/test_util.rs index f1b1aaa8d..a17ab1ea3 100644 --- a/bolt-sidecar/src/test_util.rs +++ b/bolt-sidecar/src/test_util.rs @@ -9,7 +9,7 @@ use alloy_signer::{ }; use alloy_signer_local::PrivateKeySigner; use blst::min_pk::SecretKey; -use reth_primitives::TransactionSigned; +use reth_primitives::PooledTransactionsElement; use secp256k1::Message; use crate::{ @@ -152,9 +152,9 @@ pub(crate) async fn create_signed_commitment_request( let tx_signed = tx.build(&wallet).await?; let raw_encoded = tx_signed.encoded_2718(); - let tx_signed_reth = TransactionSigned::decode_enveloped(&mut raw_encoded.as_slice())?; + let tx_pooled = PooledTransactionsElement::decode_enveloped(&mut raw_encoded.as_slice())?; - let tx_hash = tx_signed_reth.hash(); + let tx_hash = tx_pooled.hash(); let message_digest = { let mut data = Vec::new(); @@ -166,7 +166,7 @@ pub(crate) async fn create_signed_commitment_request( let signature = signer.sign_hash(&message_digest).await?; Ok(CommitmentRequest::Inclusion(InclusionRequest { - tx: tx_signed_reth, + tx: tx_pooled, slot, signature, })) From 95902fdaf2365ad7718227815d7b061da3b74df3 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Mon, 15 Jul 2024 11:13:31 +0200 Subject: [PATCH 28/48] feat: cleaned tests with test_util --- bolt-sidecar/src/primitives/commitment.rs | 9 + bolt-sidecar/src/state/execution.rs | 45 ---- bolt-sidecar/src/state/mod.rs | 288 +++++++++------------- 3 files changed, 121 insertions(+), 221 deletions(-) diff --git a/bolt-sidecar/src/primitives/commitment.rs b/bolt-sidecar/src/primitives/commitment.rs index da8c10c53..f9d0b2418 100644 --- a/bolt-sidecar/src/primitives/commitment.rs +++ b/bolt-sidecar/src/primitives/commitment.rs @@ -14,6 +14,15 @@ pub enum CommitmentRequest { Inclusion(InclusionRequest), } +impl CommitmentRequest { + /// Returns the inner request if this is an inclusion request, otherwise `None`. + pub fn as_inclusion_request(&self) -> Option<&InclusionRequest> { + match self { + CommitmentRequest::Inclusion(req) => Some(req), + } + } +} + /// Request to include a transaction at a specific slot. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct InclusionRequest { diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 9212cd7ef..cd5dcc2d7 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -343,48 +343,3 @@ pub struct StateUpdate { pub min_blob_basefee: u128, pub block_number: u64, } - -#[cfg(test)] -mod tests { - use std::num::NonZero; - - use reqwest::Url; - - use crate::{ - state::{fetcher::StateFetcher, ExecutionState, StateClient, ValidationError}, - test_util::{create_signed_commitment_request, default_test_transaction, launch_anvil}, - }; - - #[tokio::test] - async fn test_check_commitment_validity() -> eyre::Result<()> { - let anvil = launch_anvil(); - let client = StateClient::new(Url::parse(&anvil.endpoint())?); - - let max_comms = NonZero::new(10).unwrap(); - let mut state = ExecutionState::new(client.clone(), max_comms).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - let mut tx = default_test_transaction(*sender, None); - - // Base fee too low - tx.gas_price = Some(0); - let req = create_signed_commitment_request(tx.clone(), sender_pk, slot + 1).await?; - let res = state.validate_commitment_request(&req).await; - assert!(matches!(res, Err(ValidationError::BaseFeeTooLow(_)))); - - // Nonce too high - tx.gas_price = Some(1_000_000_000); - tx.nonce = Some(100); - let req = create_signed_commitment_request(tx, sender_pk, slot + 1).await?; - let res = state.validate_commitment_request(&req).await; - assert!(matches!(res, Err(ValidationError::NonceTooHigh))); - - Ok(()) - } -} diff --git a/bolt-sidecar/src/state/mod.rs b/bolt-sidecar/src/state/mod.rs index 7a4f274f1..767b4582f 100644 --- a/bolt-sidecar/src/state/mod.rs +++ b/bolt-sidecar/src/state/mod.rs @@ -73,20 +73,16 @@ mod tests { use alloy_consensus::constants::ETH_TO_WEI; use alloy_eips::eip2718::Encodable2718; use alloy_network::EthereumWallet; - use alloy_primitives::{hex, uint, Uint}; + use alloy_primitives::{uint, Uint}; use alloy_provider::{network::TransactionBuilder, Provider, ProviderBuilder}; - use alloy_signer::SignerSync; use alloy_signer_local::PrivateKeySigner; use execution::{ExecutionState, ValidationError}; - use fetcher::StateClient; - use reqwest::Url; - use reth_primitives::PooledTransactionsElement; - use tracing_subscriber::fmt; + use fetcher::{StateClient, StateFetcher}; use crate::{ crypto::{bls::Signer, SignableBLS, SignerBLS}, - primitives::{CommitmentRequest, ConstraintsMessage, InclusionRequest, SignedConstraints}, - test_util::{default_test_transaction, launch_anvil}, + primitives::{ConstraintsMessage, SignedConstraints}, + test_util::{create_signed_commitment_request, default_test_transaction, launch_anvil}, }; use super::*; @@ -107,208 +103,161 @@ mod tests { } #[tokio::test] - async fn test_valid_inclusion_request() { - let _ = fmt::try_init(); + async fn test_valid_inclusion_request() -> eyre::Result<()> { + let _ = tracing_subscriber::fmt::try_init(); - // let mut state = State::new(get_client()).await.unwrap(); let anvil = launch_anvil(); - let client = StateClient::new(Url::parse(&anvil.endpoint()).unwrap()); + let client = StateClient::new(anvil.endpoint_url()); - let mut state = ExecutionState::new(client, NonZero::new(1024).expect("valid non-zero")) - .await - .unwrap(); + let max_comms = NonZero::new(10).unwrap(); + let mut state = ExecutionState::new(client.clone(), max_comms).await?; - let wallet: PrivateKeySigner = anvil.keys()[0].clone().into(); - - let sender = anvil.addresses()[0]; + let sender = anvil.addresses().first().unwrap(); + let sender_pk = anvil.keys().first().unwrap(); - let tx = default_test_transaction(sender, None); + // initialize the state by updating the head once + let slot = client.get_head().await?; + state.update_head(None, slot).await?; - let sig = wallet.sign_message_sync(&hex!("abcd")).unwrap(); - - let signer: EthereumWallet = wallet.into(); - let signed = tx.build(&signer).await.unwrap(); + let tx = default_test_transaction(*sender, None); - // Trick to parse into the TransactionSigned type - let tx_signed_bytes = signed.encoded_2718(); - let tx_signed = - PooledTransactionsElement::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); - - let request = CommitmentRequest::Inclusion(InclusionRequest { - slot: 10, - tx: tx_signed, - signature: sig, - }); + let request = create_signed_commitment_request(tx, sender_pk, 10).await?; assert!(state.validate_commitment_request(&request).await.is_ok()); + + Ok(()) } #[tokio::test] - async fn test_invalid_inclusion_request_nonce() { - let _ = fmt::try_init(); + async fn test_invalid_inclusion_request_nonce() -> eyre::Result<()> { + let _ = tracing_subscriber::fmt::try_init(); let anvil = launch_anvil(); - let client = StateClient::new(Url::parse(&anvil.endpoint()).unwrap()); - - let mut state = ExecutionState::new(client, NonZero::new(1024).expect("valid non-zero")) - .await - .unwrap(); + let client = StateClient::new(anvil.endpoint_url()); - let wallet: PrivateKeySigner = anvil.keys()[0].clone().into(); - - let sender = anvil.addresses()[0]; + let max_comms = NonZero::new(10).unwrap(); + let mut state = ExecutionState::new(client.clone(), max_comms).await?; - let tx = default_test_transaction(sender, Some(1)); + let sender = anvil.addresses().first().unwrap(); + let sender_pk = anvil.keys().first().unwrap(); - let sig = wallet.sign_message_sync(&hex!("abcd")).unwrap(); - - let signer: EthereumWallet = wallet.into(); - let signed = tx.build(&signer).await.unwrap(); + // initialize the state by updating the head once + let slot = client.get_head().await?; + state.update_head(None, slot).await?; - // Trick to parse into the TransactionSigned type - let tx_signed_bytes = signed.encoded_2718(); - let tx_signed = - PooledTransactionsElement::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); + // Create a transaction with a nonce that is too high + let tx = default_test_transaction(*sender, Some(1)); - let request = CommitmentRequest::Inclusion(InclusionRequest { - slot: 10, - tx: tx_signed, - signature: sig, - }); + let request = create_signed_commitment_request(tx, sender_pk, 10).await?; assert!(matches!( state.validate_commitment_request(&request).await, Err(ValidationError::NonceTooHigh) )); + + Ok(()) } #[tokio::test] - async fn test_invalid_inclusion_request_balance() { - let _ = fmt::try_init(); + async fn test_invalid_inclusion_request_balance() -> eyre::Result<()> { + let _ = tracing_subscriber::fmt::try_init(); let anvil = launch_anvil(); - let client = StateClient::new(Url::parse(&anvil.endpoint()).unwrap()); + let client = StateClient::new(anvil.endpoint_url()); - let mut state = ExecutionState::new(client, NonZero::new(1024).expect("valid non-zero")) - .await - .unwrap(); + let max_comms = NonZero::new(10).unwrap(); + let mut state = ExecutionState::new(client.clone(), max_comms).await?; - let wallet: PrivateKeySigner = anvil.keys()[0].clone().into(); + let sender = anvil.addresses().first().unwrap(); + let sender_pk = anvil.keys().first().unwrap(); - let sender = anvil.addresses()[0]; + // initialize the state by updating the head once + let slot = client.get_head().await?; + state.update_head(None, slot).await?; - let tx = default_test_transaction(sender, None) + // Create a transaction with a value that is too high + let tx = default_test_transaction(*sender, None) .with_value(uint!(11_000_U256 * Uint::from(ETH_TO_WEI))); - let sig = wallet.sign_message_sync(&hex!("abcd")).unwrap(); - - let signer: EthereumWallet = wallet.into(); - let signed = tx.build(&signer).await.unwrap(); - - // Trick to parse into the TransactionSigned type - let tx_signed_bytes = signed.encoded_2718(); - let tx_signed = - PooledTransactionsElement::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); - - let request = CommitmentRequest::Inclusion(InclusionRequest { - slot: 10, - tx: tx_signed, - signature: sig, - }); + let request = create_signed_commitment_request(tx, sender_pk, 10).await?; assert!(matches!( state.validate_commitment_request(&request).await, Err(ValidationError::InsufficientBalance) )); + + Ok(()) } #[tokio::test] - async fn test_invalid_inclusion_request_basefee() { - let _ = fmt::try_init(); + async fn test_invalid_inclusion_request_basefee() -> eyre::Result<()> { + let _ = tracing_subscriber::fmt::try_init(); let anvil = launch_anvil(); - let client = StateClient::new(Url::parse(&anvil.endpoint()).unwrap()); + let client = StateClient::new(anvil.endpoint_url()); - let mut state = ExecutionState::new(client, NonZero::new(1024).expect("valid non-zero")) - .await - .unwrap(); + let max_comms = NonZero::new(10).unwrap(); + let mut state = ExecutionState::new(client.clone(), max_comms).await?; let basefee = state.basefee(); - let wallet: PrivateKeySigner = anvil.keys()[0].clone().into(); - - let sender = anvil.addresses()[0]; - - let tx = default_test_transaction(sender, None).with_max_fee_per_gas(basefee - 1); + let sender = anvil.addresses().first().unwrap(); + let sender_pk = anvil.keys().first().unwrap(); - let sig = wallet.sign_message_sync(&hex!("abcd")).unwrap(); + // initialize the state by updating the head once + let slot = client.get_head().await?; + state.update_head(None, slot).await?; - let signer: EthereumWallet = wallet.into(); - let signed = tx.build(&signer).await.unwrap(); - - // Trick to parse into the TransactionSigned type - let tx_signed_bytes = signed.encoded_2718(); - let tx_signed = - PooledTransactionsElement::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); + // Create a transaction with a basefee that is too low + let tx = default_test_transaction(*sender, None).with_max_fee_per_gas(basefee - 1); - let request = CommitmentRequest::Inclusion(InclusionRequest { - slot: 10, - tx: tx_signed, - signature: sig, - }); + let request = create_signed_commitment_request(tx, sender_pk, 10).await?; assert!(matches!( state.validate_commitment_request(&request).await, Err(ValidationError::BaseFeeTooLow(_)) )); + + Ok(()) } #[tokio::test] - async fn test_invalidate_inclusion_request() { - let _ = fmt::try_init(); - - let target_slot = 10; + async fn test_invalidate_inclusion_request() -> eyre::Result<()> { + let _ = tracing_subscriber::fmt::try_init(); let anvil = launch_anvil(); - let client = StateClient::new(Url::parse(&anvil.endpoint()).unwrap()); - - let mut state = ExecutionState::new(client, NonZero::new(1024).expect("valid non-zero")) - .await - .unwrap(); + let client = StateClient::new(anvil.endpoint_url()); + let provider = ProviderBuilder::new().on_http(anvil.endpoint_url()); - let wallet: PrivateKeySigner = anvil.keys()[0].clone().into(); + let max_comms = NonZero::new(10).unwrap(); + let mut state = ExecutionState::new(client.clone(), max_comms).await?; - let sender = anvil.addresses()[0]; + let sender = anvil.addresses().first().unwrap(); + let sender_pk = anvil.keys().first().unwrap(); - let tx = default_test_transaction(sender, None); + // initialize the state by updating the head once + let slot = client.get_head().await?; + state.update_head(None, slot).await?; - let sig = wallet.sign_message_sync(&hex!("abcd")).unwrap(); + let tx = default_test_transaction(*sender, None); + // build the signed transaction for submission later + let wallet: PrivateKeySigner = anvil.keys()[0].clone().into(); let signer: EthereumWallet = wallet.into(); - let signed = tx.build(&signer).await.unwrap(); - - let bls_signer = Signer::random(); - - // Trick to parse into the TransactionSigned type - let tx_signed_bytes = signed.encoded_2718(); - let tx_signed = - PooledTransactionsElement::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); - - let inclusion_request = InclusionRequest { - slot: target_slot, - tx: tx_signed, - signature: sig, - }; + let signed = tx.clone().build(&signer).await?; - let request = CommitmentRequest::Inclusion(inclusion_request.clone()); + let target_slot = 10; + let request = create_signed_commitment_request(tx, sender_pk, target_slot).await?; + let inclusion_request = request.as_inclusion_request().unwrap().clone(); assert!(state.validate_commitment_request(&request).await.is_ok()); - let message = ConstraintsMessage::build(0, inclusion_request, sender); + let bls_signer = Signer::random(); + let message = ConstraintsMessage::build(0, inclusion_request, *sender); let signature = bls_signer.sign(&message.digest()).unwrap().to_string(); let signed_constraints = SignedConstraints { message, signature }; - state.add_constraint(target_slot, signed_constraints.clone()); + state.add_constraint(target_slot, signed_constraints); assert!( state @@ -319,76 +268,60 @@ mod tests { == 1 ); - let provider = ProviderBuilder::new().on_http(anvil.endpoint_url()); - let notif = provider .send_raw_transaction(&signed.encoded_2718()) - .await - .unwrap(); + .await?; // Wait for confirmation - let receipt = notif.get_receipt().await.unwrap(); + let receipt = notif.get_receipt().await?; // Update the head, which should invalidate the transaction due to a nonce conflict state .update_head(receipt.block_number, receipt.block_number.unwrap()) - .await - .unwrap(); + .await?; let transactions_len = state .block_templates() .get(&target_slot) .unwrap() .transactions_len(); + assert!(transactions_len == 0); + + Ok(()) } #[tokio::test] - async fn test_invalidate_stale_template() { - let _ = fmt::try_init(); - - let target_slot = 10; + async fn test_invalidate_stale_template() -> eyre::Result<()> { + let _ = tracing_subscriber::fmt::try_init(); let anvil = launch_anvil(); - let client = StateClient::new(Url::parse(&anvil.endpoint()).unwrap()); - - let mut state = ExecutionState::new(client, NonZero::new(1024).expect("valid non-zero")) - .await - .unwrap(); - - let wallet: PrivateKeySigner = anvil.keys()[0].clone().into(); - - let sender = anvil.addresses()[0]; - - let tx = default_test_transaction(sender, None); - - let sig = wallet.sign_message_sync(&hex!("abcd")).unwrap(); + let client = StateClient::new(anvil.endpoint_url()); - let signer: EthereumWallet = wallet.into(); - let signed = tx.build(&signer).await.unwrap(); + let max_comms = NonZero::new(10).unwrap(); + let mut state = ExecutionState::new(client.clone(), max_comms).await?; - let bls_signer = Signer::random(); + let sender = anvil.addresses().first().unwrap(); + let sender_pk = anvil.keys().first().unwrap(); - // Trick to parse into the TransactionSigned type - let tx_signed_bytes = signed.encoded_2718(); - let tx_signed = - PooledTransactionsElement::decode_enveloped(&mut tx_signed_bytes.as_slice()).unwrap(); + // initialize the state by updating the head once + let slot = client.get_head().await?; + state.update_head(None, slot).await?; - let inclusion_request = InclusionRequest { - slot: target_slot, - tx: tx_signed, - signature: sig, - }; + let tx = default_test_transaction(*sender, None); - let request = CommitmentRequest::Inclusion(inclusion_request.clone()); + let target_slot = 10; + let request = create_signed_commitment_request(tx, sender_pk, target_slot).await?; + let inclusion_request = request.as_inclusion_request().unwrap().clone(); assert!(state.validate_commitment_request(&request).await.is_ok()); - let message = ConstraintsMessage::build(0, inclusion_request, sender); + let bls_signer = Signer::random(); + let message = ConstraintsMessage::build(0, inclusion_request, *sender); let signature = bls_signer.sign(&message.digest()).unwrap().to_string(); let signed_constraints = SignedConstraints { message, signature }; - state.add_constraint(target_slot, signed_constraints.clone()); + state.add_constraint(target_slot, signed_constraints); assert!( state @@ -399,9 +332,12 @@ mod tests { == 1 ); - // Update the head, which should invalidate the transaction due to a nonce conflict - state.update_head(None, target_slot).await.unwrap(); + // fast-forward the head to the target slot, which should invalidate the entire template + // because it's now stale + state.update_head(None, target_slot).await?; assert!(state.block_templates().get(&target_slot).is_none()); + + Ok(()) } } From 816cd5ad1a46b1ea93a171996c9b304960c4bc50 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Mon, 15 Jul 2024 11:21:21 +0200 Subject: [PATCH 29/48] chore: added todo --- bolt-sidecar/src/primitives/commitment.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bolt-sidecar/src/primitives/commitment.rs b/bolt-sidecar/src/primitives/commitment.rs index f9d0b2418..03a37da6a 100644 --- a/bolt-sidecar/src/primitives/commitment.rs +++ b/bolt-sidecar/src/primitives/commitment.rs @@ -15,10 +15,13 @@ pub enum CommitmentRequest { } impl CommitmentRequest { - /// Returns the inner request if this is an inclusion request, otherwise `None`. + /// Returns a reference to the inner request if this is an inclusion request, otherwise `None`. pub fn as_inclusion_request(&self) -> Option<&InclusionRequest> { match self { CommitmentRequest::Inclusion(req) => Some(req), + // TODO: remove this when we have more request types + #[allow(unreachable_patterns)] + _ => None, } } } From c23b69cb0447c2cb43aa82829e03e930db625161 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Mon, 15 Jul 2024 11:58:59 +0200 Subject: [PATCH 30/48] chore: added tx validation constantsC --- bolt-sidecar/src/primitives/mod.rs | 10 +++++ bolt-sidecar/src/state/execution.rs | 70 ++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 7 deletions(-) diff --git a/bolt-sidecar/src/primitives/mod.rs b/bolt-sidecar/src/primitives/mod.rs index 75c91eb95..076fd6cac 100644 --- a/bolt-sidecar/src/primitives/mod.rs +++ b/bolt-sidecar/src/primitives/mod.rs @@ -229,6 +229,7 @@ pub trait TransactionExt { fn tx_type(&self) -> TxType; fn chain_id(&self) -> Option; fn blob_sidecar(&self) -> Option<&BlobTransactionSidecar>; + fn input_data_size(&self) -> usize; } impl TransactionExt for PooledTransactionsElement { @@ -276,4 +277,13 @@ impl TransactionExt for PooledTransactionsElement { _ => None, } } + + fn input_data_size(&self) -> usize { + match self { + PooledTransactionsElement::Legacy { transaction, .. } => transaction.input.len(), + PooledTransactionsElement::Eip2930 { transaction, .. } => transaction.input.len(), + PooledTransactionsElement::Eip1559 { transaction, .. } => transaction.input.len(), + PooledTransactionsElement::BlobTransaction(blob_tx) => blob_tx.transaction.input.len(), + } + } } diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index cd5dcc2d7..a663df553 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -10,7 +10,7 @@ use thiserror::Error; use crate::{ builder::BlockTemplate, common::{calculate_max_basefee, validate_transaction}, - primitives::{AccountState, CommitmentRequest, SignedConstraints, Slot}, + primitives::{AccountState, CommitmentRequest, SignedConstraints, Slot, TransactionExt}, }; use super::fetcher::StateFetcher; @@ -102,6 +102,27 @@ pub struct ExecutionState { kzg_settings: EnvKzgSettings, /// The state fetcher client. client: C, + /// Constant values used for validation + constants: Constants, +} + +/// Constants used for validation. +#[derive(Debug)] +pub struct Constants { + block_gas_limit: u64, + max_tx_input_bytes: usize, + #[allow(unused)] + max_init_code_byte_size: usize, +} + +impl Default for Constants { + fn default() -> Self { + Self { + block_gas_limit: 30_000_000, + max_tx_input_bytes: 4 * 32 * 1024, // 128kb + max_init_code_byte_size: 2 * 24576, + } + } } impl ExecutionState { @@ -111,21 +132,27 @@ impl ExecutionState { client: C, max_commitments_per_slot: NonZero, ) -> Result { - let (basefee, blob_basefee) = - tokio::try_join!(client.get_basefee(None), client.get_blob_basefee(None))?; + let (basefee, blob_basefee, block_number, chain_id) = tokio::try_join!( + client.get_basefee(None), + client.get_blob_basefee(None), + client.get_head(), + client.get_chain_id() + )?; Ok(Self { basefee, blob_basefee, - block_number: client.get_head().await?, + block_number, + chain_id, + max_commitments_per_slot, + client, slot: 0, account_states: HashMap::new(), block_templates: HashMap::new(), - chain_id: client.get_chain_id().await?, // Load the default KZG settings kzg_settings: EnvKzgSettings::default(), - max_commitments_per_slot, - client, + // Load the default constants + constants: Constants::default(), }) } @@ -171,6 +198,35 @@ impl ExecutionState { } } + // Check if the input data size exceeds the maximum. + if req.tx.input_data_size() > self.constants.max_tx_input_bytes { + return Err(ValidationError::Internal(format!( + "Transaction input size exceeds maximum: {} > {}", + req.tx.input_data_size(), + self.constants.max_tx_input_bytes + ))); + } + + // Check if the gas limit is higher than the maximum block gas limit + if req.tx.gas_limit() > self.constants.block_gas_limit { + return Err(ValidationError::Internal(format!( + "Transaction gas limit exceeds block gas limit: {} > {}", + req.tx.gas_limit(), + self.constants.block_gas_limit + ))); + } + + // Ensure max_priority_fee_per_gas is less than max_fee_per_gas, if any + if req + .tx + .max_priority_fee_per_gas() + .is_some_and(|max_priority_fee| max_priority_fee > req.tx.max_fee_per_gas()) + { + return Err(ValidationError::Internal( + "max_priority_fee_per_gas is greater than max_fee_per_gas".to_string(), + )); + } + let sender = req .tx .recover_signer() From 07876bddd91fb0110d0ba873ee1512a5ce8b9590 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Mon, 15 Jul 2024 14:51:13 +0200 Subject: [PATCH 31/48] feat: added code check --- bolt-sidecar/src/client/rpc.rs | 22 +++++++++++++++++++++- bolt-sidecar/src/common.rs | 5 +++++ bolt-sidecar/src/primitives/mod.rs | 15 +++++++++------ bolt-sidecar/src/state/execution.rs | 9 ++++++--- bolt-sidecar/src/state/fetcher.rs | 27 +++++++++++++++++++++++++-- 5 files changed, 66 insertions(+), 12 deletions(-) diff --git a/bolt-sidecar/src/client/rpc.rs b/bolt-sidecar/src/client/rpc.rs index b6ff5ec32..d116ba211 100644 --- a/bolt-sidecar/src/client/rpc.rs +++ b/bolt-sidecar/src/client/rpc.rs @@ -10,7 +10,7 @@ use std::{ use alloy::ClientBuilder; use alloy_eips::BlockNumberOrTag; -use alloy_primitives::{Address, B256, U256, U64}; +use alloy_primitives::{Address, Bytes, B256, U256, U64}; use alloy_rpc_client::{self as alloy, Waiter}; use alloy_rpc_types::{Block, EIP1186AccountProofResponse, FeeHistory, TransactionRequest}; use alloy_rpc_types_trace::parity::{TraceResults, TraceType}; @@ -100,16 +100,22 @@ impl RpcClient { .add_call("eth_getTransactionCount", &(address, tag)) .expect("Correct parameters"); + let code = batch + .add_call("eth_getCode", &(address, tag)) + .expect("Correct parameters"); + // After the batch is complete, we can get the results. // Note that requests may error separately! batch.send().await?; let tx_count: U64 = tx_count.await?; let balance: U256 = balance.await?; + let code: Bytes = code.await?; Ok(AccountState { balance, transaction_count: tx_count.to(), + has_code: !code.is_empty(), }) } @@ -261,4 +267,18 @@ mod tests { Ok(()) } + + #[tokio::test] + async fn test_smart_contract_code() -> eyre::Result<()> { + let rpc_url = Url::parse("https://cloudflare-eth.com")?; + let rpc_client = RpcClient::new(rpc_url); + + // random deployed smart contract address + let addr = Address::from_str("0xBA12222222228d8Ba445958a75a0704d566BF2C8")?; + let account = rpc_client.get_account_state(&addr, None).await?; + + assert!(account.has_code); + + Ok(()) + } } diff --git a/bolt-sidecar/src/common.rs b/bolt-sidecar/src/common.rs index 8caa8b7c8..73bed1016 100644 --- a/bolt-sidecar/src/common.rs +++ b/bolt-sidecar/src/common.rs @@ -59,6 +59,11 @@ pub fn validate_transaction( return Err(ValidationError::InsufficientBalance); } + // Check if the account has code (i.e. is a smart contract) + if account_state.has_code { + return Err(ValidationError::AccountHasCode); + } + Ok(()) } diff --git a/bolt-sidecar/src/primitives/mod.rs b/bolt-sidecar/src/primitives/mod.rs index 076fd6cac..51266c912 100644 --- a/bolt-sidecar/src/primitives/mod.rs +++ b/bolt-sidecar/src/primitives/mod.rs @@ -37,7 +37,10 @@ pub type Slot = u64; pub struct AccountState { /// The nonce of the account. This is the number of transactions sent from this account pub transaction_count: u64, + /// The balance of the account in wei pub balance: U256, + /// Flag to indicate if the account is a smart contract or an EOA + pub has_code: bool, } #[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] @@ -229,7 +232,7 @@ pub trait TransactionExt { fn tx_type(&self) -> TxType; fn chain_id(&self) -> Option; fn blob_sidecar(&self) -> Option<&BlobTransactionSidecar>; - fn input_data_size(&self) -> usize; + fn size(&self) -> usize; } impl TransactionExt for PooledTransactionsElement { @@ -278,12 +281,12 @@ impl TransactionExt for PooledTransactionsElement { } } - fn input_data_size(&self) -> usize { + fn size(&self) -> usize { match self { - PooledTransactionsElement::Legacy { transaction, .. } => transaction.input.len(), - PooledTransactionsElement::Eip2930 { transaction, .. } => transaction.input.len(), - PooledTransactionsElement::Eip1559 { transaction, .. } => transaction.input.len(), - PooledTransactionsElement::BlobTransaction(blob_tx) => blob_tx.transaction.input.len(), + PooledTransactionsElement::Legacy { transaction, .. } => transaction.size(), + PooledTransactionsElement::Eip2930 { transaction, .. } => transaction.size(), + PooledTransactionsElement::Eip1559 { transaction, .. } => transaction.size(), + PooledTransactionsElement::BlobTransaction(blob_tx) => blob_tx.transaction.size(), } } } diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index a663df553..75c4eadd3 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -36,6 +36,9 @@ pub enum ValidationError { /// The transaction nonce is too high. #[error("Transaction nonce too high")] NonceTooHigh, + /// The sender account is a smart contract and has code. + #[error("Account has code")] + AccountHasCode, /// The sender does not have enough balance to pay for the transaction. #[error("Not enough balance to pay for value + maximum fee")] InsufficientBalance, @@ -198,11 +201,11 @@ impl ExecutionState { } } - // Check if the input data size exceeds the maximum. - if req.tx.input_data_size() > self.constants.max_tx_input_bytes { + // Check if the transaction size exceeds the maximum + if req.tx.size() > self.constants.max_tx_input_bytes { return Err(ValidationError::Internal(format!( "Transaction input size exceeds maximum: {} > {}", - req.tx.input_data_size(), + req.tx.size(), self.constants.max_tx_input_bytes ))); } diff --git a/bolt-sidecar/src/state/fetcher.rs b/bolt-sidecar/src/state/fetcher.rs index 6f9a5341f..cebf5b021 100644 --- a/bolt-sidecar/src/state/fetcher.rs +++ b/bolt-sidecar/src/state/fetcher.rs @@ -5,7 +5,7 @@ use std::{collections::HashMap, time::Duration}; use alloy_eips::BlockNumberOrTag; -use alloy_primitives::{Address, U256, U64}; +use alloy_primitives::{Address, Bytes, U256, U64}; use alloy_transport::TransportError; use futures::{stream::FuturesOrdered, StreamExt}; use reqwest::Url; @@ -78,6 +78,7 @@ impl StateFetcher for StateClient { let mut nonce_futs = FuturesOrdered::new(); let mut balance_futs = FuturesOrdered::new(); + let mut code_futs = FuturesOrdered::new(); let block_number = if let Some(block_number) = block_number { block_number @@ -94,10 +95,14 @@ impl StateFetcher for StateClient { let balance = batch .add_call("eth_getBalance", &(addr, tag)) .expect("Invalid parameters"); + let code = batch + .add_call("eth_getCode", &(addr, tag)) + .expect("Invalid parameters"); // Push the futures onto ordered list nonce_futs.push_back(nonce); balance_futs.push_back(balance); + code_futs.push_back(code); } // Make sure to send the batch! @@ -110,9 +115,10 @@ impl StateFetcher for StateClient { let blob_basefee = self.client.get_blob_basefee(None); // Collect the results - let (nonce_vec, balance_vec, basefee, blob_basefee) = tokio::join!( + let (nonce_vec, balance_vec, code_vec, basefee, blob_basefee) = tokio::join!( nonce_futs.collect::>(), balance_futs.collect::>(), + code_futs.collect::>(), basefee, blob_basefee, ); @@ -129,6 +135,7 @@ impl StateFetcher for StateClient { .or_insert(AccountState { transaction_count: nonce.to(), balance: U256::ZERO, + has_code: false, }); } @@ -143,6 +150,22 @@ impl StateFetcher for StateClient { .or_insert(AccountState { transaction_count: 0, balance, + has_code: false, + }); + } + + for (addr, code) in addresses.iter().zip(code_vec) { + let code: Bytes = code?; + + account_states + .entry(**addr) + .and_modify(|s: &mut AccountState| { + s.has_code = !code.is_empty(); + }) + .or_insert(AccountState { + transaction_count: 0, + balance: U256::ZERO, + has_code: !code.is_empty(), }); } From 5bff4b5c750c602a21cdf1a73cea5af256293f27 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Mon, 15 Jul 2024 15:17:12 +0200 Subject: [PATCH 32/48] feat: init code check --- bolt-sidecar/src/primitives/mod.rs | 24 +++++++++++++++++++++- bolt-sidecar/src/state/execution.rs | 32 +++++++++++++++++------------ 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/bolt-sidecar/src/primitives/mod.rs b/bolt-sidecar/src/primitives/mod.rs index 51266c912..920856011 100644 --- a/bolt-sidecar/src/primitives/mod.rs +++ b/bolt-sidecar/src/primitives/mod.rs @@ -17,7 +17,9 @@ use ethereum_consensus::{ types::mainnet::ExecutionPayload, Fork, }; -use reth_primitives::{BlobTransactionSidecar, PooledTransactionsElement, TxType}; +use reth_primitives::{ + BlobTransactionSidecar, Bytes, PooledTransactionsElement, TransactionKind, TxType, +}; use tokio::sync::{mpsc, oneshot}; /// Commitment types, received by users wishing to receive preconfirmations. @@ -230,6 +232,8 @@ pub trait TransactionExt { fn gas_limit(&self) -> u64; fn value(&self) -> U256; fn tx_type(&self) -> TxType; + fn tx_kind(&self) -> TransactionKind; + fn input(&self) -> &Bytes; fn chain_id(&self) -> Option; fn blob_sidecar(&self) -> Option<&BlobTransactionSidecar>; fn size(&self) -> usize; @@ -263,6 +267,24 @@ impl TransactionExt for PooledTransactionsElement { } } + fn tx_kind(&self) -> TransactionKind { + match self { + PooledTransactionsElement::Legacy { transaction, .. } => transaction.to, + PooledTransactionsElement::Eip2930 { transaction, .. } => transaction.to, + PooledTransactionsElement::Eip1559 { transaction, .. } => transaction.to, + PooledTransactionsElement::BlobTransaction(blob_tx) => blob_tx.transaction.to, + } + } + + fn input(&self) -> &Bytes { + match self { + PooledTransactionsElement::Legacy { transaction, .. } => &transaction.input, + PooledTransactionsElement::Eip2930 { transaction, .. } => &transaction.input, + PooledTransactionsElement::Eip1559 { transaction, .. } => &transaction.input, + PooledTransactionsElement::BlobTransaction(blob_tx) => &blob_tx.transaction.input, + } + } + fn chain_id(&self) -> Option { match self { PooledTransactionsElement::Legacy { transaction, .. } => transaction.chain_id, diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 75c4eadd3..8420d251a 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -39,6 +39,15 @@ pub enum ValidationError { /// The sender account is a smart contract and has code. #[error("Account has code")] AccountHasCode, + /// The gas limit is too high. + #[error("Gas limit too high")] + GasLimitTooHigh, + /// The transaction input size is too high. + #[error("Transaction input size too high")] + TransactionSizeTooHigh, + /// Max priority fee per gas is greater than max fee per gas. + #[error("Max priority fee per gas is greater than max fee per gas")] + MaxPriorityFeePerGasTooHigh, /// The sender does not have enough balance to pay for the transaction. #[error("Not enough balance to pay for value + maximum fee")] InsufficientBalance, @@ -203,20 +212,19 @@ impl ExecutionState { // Check if the transaction size exceeds the maximum if req.tx.size() > self.constants.max_tx_input_bytes { - return Err(ValidationError::Internal(format!( - "Transaction input size exceeds maximum: {} > {}", - req.tx.size(), - self.constants.max_tx_input_bytes - ))); + return Err(ValidationError::TransactionSizeTooHigh); + } + + // Check if the transaction is a contract creation and the init code size exceeds the maximum + if req.tx.tx_kind().is_create() + && req.tx.input().len() > self.constants.max_init_code_byte_size + { + return Err(ValidationError::TransactionSizeTooHigh); } // Check if the gas limit is higher than the maximum block gas limit if req.tx.gas_limit() > self.constants.block_gas_limit { - return Err(ValidationError::Internal(format!( - "Transaction gas limit exceeds block gas limit: {} > {}", - req.tx.gas_limit(), - self.constants.block_gas_limit - ))); + return Err(ValidationError::GasLimitTooHigh); } // Ensure max_priority_fee_per_gas is less than max_fee_per_gas, if any @@ -225,9 +233,7 @@ impl ExecutionState { .max_priority_fee_per_gas() .is_some_and(|max_priority_fee| max_priority_fee > req.tx.max_fee_per_gas()) { - return Err(ValidationError::Internal( - "max_priority_fee_per_gas is greater than max_fee_per_gas".to_string(), - )); + return Err(ValidationError::MaxPriorityFeePerGasTooHigh); } let sender = req From ed7ab9c2421e72822b1cbae49e8816a7ed2b64ed Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Tue, 16 Jul 2024 09:57:52 +0200 Subject: [PATCH 33/48] chore: small fixes --- bolt-sidecar/src/state/execution.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 8420d251a..a6d29f5ad 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -123,7 +123,6 @@ pub struct ExecutionState { pub struct Constants { block_gas_limit: u64, max_tx_input_bytes: usize, - #[allow(unused)] max_init_code_byte_size: usize, } @@ -131,7 +130,7 @@ impl Default for Constants { fn default() -> Self { Self { block_gas_limit: 30_000_000, - max_tx_input_bytes: 4 * 32 * 1024, // 128kb + max_tx_input_bytes: 4 * 32 * 1024, max_init_code_byte_size: 2 * 24576, } } From 4064db65678b9e6af9fa42c4758a28f85708a303 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Tue, 16 Jul 2024 16:21:39 +0200 Subject: [PATCH 34/48] chore: rename --- bolt-sidecar/src/state/execution.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index a6d29f5ad..265de6ed9 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -114,19 +114,19 @@ pub struct ExecutionState { kzg_settings: EnvKzgSettings, /// The state fetcher client. client: C, - /// Constant values used for validation - constants: Constants, + /// Other values used for validation + validation_params: ValidationParams, } -/// Constants used for validation. +/// Other values used for validation. #[derive(Debug)] -pub struct Constants { +pub struct ValidationParams { block_gas_limit: u64, max_tx_input_bytes: usize, max_init_code_byte_size: usize, } -impl Default for Constants { +impl Default for ValidationParams { fn default() -> Self { Self { block_gas_limit: 30_000_000, @@ -162,8 +162,8 @@ impl ExecutionState { block_templates: HashMap::new(), // Load the default KZG settings kzg_settings: EnvKzgSettings::default(), - // Load the default constants - constants: Constants::default(), + // TODO: add a way to configure these values from CLI + validation_params: ValidationParams::default(), }) } @@ -210,19 +210,19 @@ impl ExecutionState { } // Check if the transaction size exceeds the maximum - if req.tx.size() > self.constants.max_tx_input_bytes { + if req.tx.size() > self.validation_params.max_tx_input_bytes { return Err(ValidationError::TransactionSizeTooHigh); } // Check if the transaction is a contract creation and the init code size exceeds the maximum if req.tx.tx_kind().is_create() - && req.tx.input().len() > self.constants.max_init_code_byte_size + && req.tx.input().len() > self.validation_params.max_init_code_byte_size { return Err(ValidationError::TransactionSizeTooHigh); } // Check if the gas limit is higher than the maximum block gas limit - if req.tx.gas_limit() > self.constants.block_gas_limit { + if req.tx.gas_limit() > self.validation_params.block_gas_limit { return Err(ValidationError::GasLimitTooHigh); } From 1af755b549c42a6fa21f8db985f52fad986a050a Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Tue, 16 Jul 2024 17:01:20 +0200 Subject: [PATCH 35/48] fix(sidecar): same nonce pre-confirmations on the same slot Co-authored-by: merklefruit --- bolt-sidecar/bin/sidecar.rs | 13 +++--- bolt-sidecar/src/json_rpc/api.rs | 10 +++-- bolt-sidecar/src/primitives/commitment.rs | 18 ++++---- bolt-sidecar/src/primitives/constraint.rs | 8 +++- bolt-sidecar/src/state/execution.rs | 52 +++++++++++++---------- bolt-sidecar/src/state/mod.rs | 4 +- bolt-sidecar/src/test_util.rs | 1 + 7 files changed, 58 insertions(+), 48 deletions(-) diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index 30decb895..fb9093eb3 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -79,13 +79,10 @@ async fn main() -> eyre::Result<()> { } }; - let sender = match execution_state.validate_commitment_request(&request).await { - Ok(sender) => sender, - Err(e) => { - tracing::error!(err = ?e, "Failed to commit request"); - let _ = response_tx.send(Err(ApiError::Custom(e.to_string()))); - continue; - } + if let Err(e) = execution_state.validate_commitment_request(&request).await { + tracing::error!(err = ?e, "Failed to commit request"); + let _ = response_tx.send(Err(ApiError::Custom(e.to_string()))); + continue; }; // TODO: match when we have more request types @@ -99,7 +96,7 @@ async fn main() -> eyre::Result<()> { // TODO: review all this `clone` usage // parse the request into constraints and sign them with the sidecar signer - let message = ConstraintsMessage::build(validator_index, request.clone(), sender); + let message = ConstraintsMessage::build(validator_index, request.clone()); let signature = signer.sign(&message.digest())?.to_string(); let signed_constraints = SignedConstraints { message, signature }; diff --git a/bolt-sidecar/src/json_rpc/api.rs b/bolt-sidecar/src/json_rpc/api.rs index ac7bbffaa..2b4f88aa6 100644 --- a/bolt-sidecar/src/json_rpc/api.rs +++ b/bolt-sidecar/src/json_rpc/api.rs @@ -104,7 +104,7 @@ impl CommitmentsRpc for JsonRpcApi { let request = serde_json::from_value::(params)?; #[allow(irrefutable_let_patterns)] // TODO: remove this when we have more request types - let CommitmentRequest::Inclusion(request) = request + let CommitmentRequest::Inclusion(mut request) = request else { return Err(ApiError::Custom( "request must be an inclusion request".to_string(), @@ -113,7 +113,9 @@ impl CommitmentsRpc for JsonRpcApi { info!(?request, "received inclusion commitment request"); - let tx_sender = request.tx.recover_signer().ok_or(ApiError::Custom( + // NOTE: request.sender is skipped from deserialization and initialized as Address::ZERO + // by the default Deserialization. It must be set here. + request.sender = request.tx.recover_signer().ok_or(ApiError::Custom( "failed to recover signer from transaction".to_string(), ))?; @@ -124,9 +126,9 @@ impl CommitmentsRpc for JsonRpcApi { // TODO: relax this check to allow for external signers to request commitments // about transactions that they did not sign themselves - if signer_address != tx_sender { + if signer_address != request.sender { return Err(ApiError::SignaturePubkeyMismatch { - expected: tx_sender.to_string(), + expected: request.sender.to_string(), got: signer_address.to_string(), }); } diff --git a/bolt-sidecar/src/primitives/commitment.rs b/bolt-sidecar/src/primitives/commitment.rs index 03a37da6a..9db058198 100644 --- a/bolt-sidecar/src/primitives/commitment.rs +++ b/bolt-sidecar/src/primitives/commitment.rs @@ -1,7 +1,7 @@ use serde::{de, Deserialize, Deserializer, Serialize}; use std::str::FromStr; -use alloy_primitives::{keccak256, Signature, B256}; +use alloy_primitives::{keccak256, Address, Signature, B256}; use reth_primitives::PooledTransactionsElement; use super::TransactionExt; @@ -37,11 +37,12 @@ pub struct InclusionRequest { /// The signature over the "slot" and "tx" fields by the user. /// A valid signature is the only proof that the user actually requested /// this specific commitment to be included at the given slot. - #[serde( - deserialize_with = "deserialize_from_str", - serialize_with = "signature_as_str" - )] + #[serde(deserialize_with = "deserialize_sig", serialize_with = "serialize_sig")] pub signature: Signature, + /// The ec-recovered address of the signature, for internal use. + /// If not explicitly set, this defaults to `Address::ZERO`. + #[serde(skip)] + pub sender: Address, } impl InclusionRequest { @@ -79,7 +80,7 @@ where serializer.serialize_str(&format!("0x{}", hex::encode(&data))) } -fn deserialize_from_str<'de, D, T>(deserializer: D) -> Result +fn deserialize_sig<'de, D, T>(deserializer: D) -> Result where D: Deserializer<'de>, T: FromStr, @@ -89,10 +90,7 @@ where T::from_str(s.trim_start_matches("0x")).map_err(de::Error::custom) } -fn signature_as_str( - sig: &Signature, - serializer: S, -) -> Result { +fn serialize_sig(sig: &Signature, serializer: S) -> Result { let parity = sig.v(); // As bytes encodes the parity as 27/28, need to change that. let mut bytes = sig.as_bytes(); diff --git a/bolt-sidecar/src/primitives/constraint.rs b/bolt-sidecar/src/primitives/constraint.rs index 9281ed102..f1073ce53 100644 --- a/bolt-sidecar/src/primitives/constraint.rs +++ b/bolt-sidecar/src/primitives/constraint.rs @@ -55,8 +55,12 @@ pub struct ConstraintsMessage { impl ConstraintsMessage { /// Builds a constraints message from an inclusion request and metadata - pub fn build(validator_index: u64, request: InclusionRequest, sender: Address) -> Self { - let constraints = vec![Constraint::from_transaction(request.tx, None, sender)]; + pub fn build(validator_index: u64, request: InclusionRequest) -> Self { + let constraints = vec![Constraint::from_transaction( + request.tx, + None, + request.sender, + )]; Self { validator_index, slot: request.slot, diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 265de6ed9..d85047eab 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -1,5 +1,5 @@ use alloy_eips::eip4844::MAX_BLOBS_PER_BLOCK; -use alloy_primitives::{Address, SignatureError}; +use alloy_primitives::{Address, SignatureError, U256}; use alloy_transport::TransportError; use reth_primitives::{ revm_primitives::EnvKzgSettings, BlobTransactionValidationError, PooledTransactionsElement, @@ -200,7 +200,8 @@ impl ExecutionState { } // Check if there is room for more commitments - if let Some(template) = self.get_block_template(req.slot) { + let template = self.get_block_template(req.slot); + if let Some(template) = template { if template.transactions_len() >= self.max_commitments_per_slot.get() { return Err(ValidationError::MaxCommitmentsReachedForSlot( self.slot, @@ -235,10 +236,7 @@ impl ExecutionState { return Err(ValidationError::MaxPriorityFeePerGasTooHigh); } - let sender = req - .tx - .recover_signer() - .ok_or(ValidationError::RecoverSigner)?; + let sender = req.sender; tracing::debug!(%sender, target_slot = req.slot, "Trying to commit inclusion request to block template"); @@ -254,30 +252,40 @@ impl ExecutionState { return Err(ValidationError::BaseFeeTooLow(max_basefee)); } - // If we have the account state, use it here - if let Some(account_state) = self.account_state(&sender) { - // Validate the transaction against the account state - tracing::debug!(address = %sender, "Known account state: {account_state:?}"); - validate_transaction(&account_state, &req.tx)?; - } else { - tracing::debug!(address = %sender, "Unknown account state"); - // If we don't have the account state, we need to fetch it - let account_state = - self.client + // Retrieve the nonce and balance diffs from previous preconfirmations for this slot. + // If the template does not exist, or this is the first request for this sender, + // its diffs will be zero. + let (nonce_diff, balance_diff) = self + .block_templates + .get(&req.slot) + .and_then(|template| template.state_diff().get_diff(&sender)) + // TODO: should balance diff be signed? + .unwrap_or((0, U256::ZERO)); + + let account_state = match self.account_state(&sender) { + Some(account) => account, + None => { + let account = self + .client .get_account_state(&sender, None) .await .map_err(|e| { ValidationError::Internal(format!("Failed to fetch account state: {:?}", e)) })?; - tracing::debug!(address = %sender, "Fetched account state: {account_state:?}"); + self.account_states.insert(sender, account); + account + } + }; - // Record the account state for later - self.account_states.insert(sender, account_state); + let account_state_with_diffs = AccountState { + transaction_count: account_state.transaction_count + nonce_diff, + balance: account_state.balance - balance_diff, + has_code: account_state.has_code, + }; - // Validate the transaction against the account state - validate_transaction(&account_state, &req.tx)?; - } + // Validate the transaction against the account state with existing diffs + validate_transaction(&account_state_with_diffs, &req.tx)?; // Check EIP-4844-specific limits if let Some(transaction) = req.tx.as_eip4844() { diff --git a/bolt-sidecar/src/state/mod.rs b/bolt-sidecar/src/state/mod.rs index 767b4582f..f1967cb47 100644 --- a/bolt-sidecar/src/state/mod.rs +++ b/bolt-sidecar/src/state/mod.rs @@ -253,7 +253,7 @@ mod tests { assert!(state.validate_commitment_request(&request).await.is_ok()); let bls_signer = Signer::random(); - let message = ConstraintsMessage::build(0, inclusion_request, *sender); + let message = ConstraintsMessage::build(0, inclusion_request); let signature = bls_signer.sign(&message.digest()).unwrap().to_string(); let signed_constraints = SignedConstraints { message, signature }; @@ -317,7 +317,7 @@ mod tests { assert!(state.validate_commitment_request(&request).await.is_ok()); let bls_signer = Signer::random(); - let message = ConstraintsMessage::build(0, inclusion_request, *sender); + let message = ConstraintsMessage::build(0, inclusion_request); let signature = bls_signer.sign(&message.digest()).unwrap().to_string(); let signed_constraints = SignedConstraints { message, signature }; diff --git a/bolt-sidecar/src/test_util.rs b/bolt-sidecar/src/test_util.rs index a17ab1ea3..86b01d747 100644 --- a/bolt-sidecar/src/test_util.rs +++ b/bolt-sidecar/src/test_util.rs @@ -169,5 +169,6 @@ pub(crate) async fn create_signed_commitment_request( tx: tx_pooled, slot, signature, + sender: signer.address(), })) } From 8eae3311af12d0aabfba685d10af02017ad3e0a0 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Tue, 16 Jul 2024 17:51:51 +0200 Subject: [PATCH 36/48] fix(sidecar): use separate get_block_template and remove_block_template --- bolt-sidecar/bin/sidecar.rs | 2 +- bolt-sidecar/src/state/execution.rs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index fb9093eb3..2044b02ea 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -120,7 +120,7 @@ async fn main() -> eyre::Result<()> { Some(slot) = consensus_state.commitment_deadline.wait() => { tracing::info!(slot, "Commitment deadline reached, starting to build local block"); - let Some(template) = execution_state.get_block_template(slot) else { + let Some(template) = execution_state.remove_block_template(slot) else { tracing::warn!("No block template found for slot {slot} when requested"); continue; }; diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index d85047eab..a277fce88 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -401,9 +401,13 @@ impl ExecutionState { } } + pub fn get_block_template(&mut self, slot: u64) -> Option<&BlockTemplate> { + self.block_templates.get(&slot) + } + /// Gets the block template for the given slot number and removes it from the cache. /// This should be called when we need to propose a block for the given slot. - pub fn get_block_template(&mut self, slot: u64) -> Option { + pub fn remove_block_template(&mut self, slot: u64) -> Option { self.block_templates.remove(&slot) } } From 5d940ee3468547f76e92719e4f4fb664db8efeab Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Tue, 16 Jul 2024 17:54:11 +0200 Subject: [PATCH 37/48] chore(sidecar): docs, fmt --- bolt-sidecar/src/state/execution.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index a277fce88..067f3cbc9 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -343,7 +343,7 @@ impl ExecutionState { self.apply_state_update(update); // Remove any block templates that are no longer valid - self.block_templates.remove(&slot); + self.remove_block_template(slot); Ok(()) } @@ -406,7 +406,8 @@ impl ExecutionState { } /// Gets the block template for the given slot number and removes it from the cache. - /// This should be called when we need to propose a block for the given slot. + /// This should be called when we need to propose a block for the given slot, + /// or when a new head comes in which makes an older block template useless. pub fn remove_block_template(&mut self, slot: u64) -> Option { self.block_templates.remove(&slot) } From ef1d6cf6eea632c5b014a85abf152fb3b2a56982 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Tue, 16 Jul 2024 18:02:42 +0200 Subject: [PATCH 38/48] fix(sidecar): cumulated diffs check wip --- bolt-sidecar/bin/sidecar.rs | 1 - bolt-sidecar/src/state/execution.rs | 38 ++++++++++++++++++----------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index 2044b02ea..66d22d48d 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -68,7 +68,6 @@ async fn main() -> eyre::Result<()> { tokio::select! { Some(ApiEvent { request, response_tx }) = api_events_rx.recv() => { let start = std::time::Instant::now(); - tracing::info!("Received commitment request: {:?}", request); let validator_index = match consensus_state.validate_request(&request) { Ok(index) => index, diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 067f3cbc9..06fd407aa 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -253,25 +253,35 @@ impl ExecutionState { } // Retrieve the nonce and balance diffs from previous preconfirmations for this slot. - // If the template does not exist, or this is the first request for this sender, + // If the templates do not exist, or this is the first request for this sender, // its diffs will be zero. - let (nonce_diff, balance_diff) = self - .block_templates - .get(&req.slot) - .and_then(|template| template.state_diff().get_diff(&sender)) - // TODO: should balance diff be signed? - .unwrap_or((0, U256::ZERO)); + let (nonce_diff, balance_diff) = self.block_templates().values().fold( + (0, U256::ZERO), + |(nonce_diff_acc, balance_diff_acc), block_template| { + let (nonce_diff, balance_diff) = block_template + .state_diff() + .get_diff(&sender) + // TODO: should balance diff be signed? + .unwrap_or((0, U256::ZERO)); + + (nonce_diff_acc + nonce_diff, balance_diff_acc + balance_diff) + }, + ); + + tracing::debug!(%sender, nonce_diff, %balance_diff, "Applying diffs to account state"); let account_state = match self.account_state(&sender) { Some(account) => account, None => { - let account = self - .client - .get_account_state(&sender, None) - .await - .map_err(|e| { - ValidationError::Internal(format!("Failed to fetch account state: {:?}", e)) - })?; + let account = match self.client.get_account_state(&sender, None).await { + Ok(account) => account, + Err(err) => { + return Err(ValidationError::Internal(format!( + "Error fetching account state: {:?}", + err + ))) + } + }; self.account_states.insert(sender, account); account From 75893d9cbc1addac0f88d2de8ab0bf606e6ead15 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Wed, 17 Jul 2024 10:10:42 +0200 Subject: [PATCH 39/48] fix(sidecar): check against cumulated nonce and balance diff + highest slot for which I request a preconf Co-authored-by: merklefruit --- bolt-sidecar/src/state/execution.rs | 31 ++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 06fd407aa..ac43ec29d 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -55,6 +55,11 @@ pub enum ValidationError { #[error("Too many EIP-4844 transactions in target block")] Eip4844Limit, /// The maximum commitments have been reached for the slot. + #[error( + "Already requested a preconfirmation for slot {0}. Slot must be greater than or equal {0}" + )] + SlotTooLow(u64), + /// The maximum commitments have been reached for the slot. #[error("Max commitments reached for slot {0}: {1}")] MaxCommitmentsReachedForSlot(u64, usize), /// The signature is invalid. @@ -252,22 +257,34 @@ impl ExecutionState { return Err(ValidationError::BaseFeeTooLow(max_basefee)); } - // Retrieve the nonce and balance diffs from previous preconfirmations for this slot. + // From previous preconfirmations requests retrieve + // - the nonce difference from the account state. + // - the balance difference from the account state. + // - the highest slot number for which the user has requested a preconfirmation. // If the templates do not exist, or this is the first request for this sender, // its diffs will be zero. - let (nonce_diff, balance_diff) = self.block_templates().values().fold( - (0, U256::ZERO), - |(nonce_diff_acc, balance_diff_acc), block_template| { - let (nonce_diff, balance_diff) = block_template + let (nonce_diff, balance_diff, highest_slot) = self.block_templates().iter().fold( + (0, U256::ZERO, 0), + |(nonce_diff_acc, balance_diff_acc, highest_slot), (slot, block_template)| { + let (nonce_diff, balance_diff, slot) = block_template .state_diff() .get_diff(&sender) + .map(|d| (d.0, d.1, *slot)) // TODO: should balance diff be signed? - .unwrap_or((0, U256::ZERO)); + .unwrap_or((0, U256::ZERO, 0)); - (nonce_diff_acc + nonce_diff, balance_diff_acc + balance_diff) + ( + nonce_diff_acc + nonce_diff, + balance_diff_acc + balance_diff, + u64::max(highest_slot, slot), + ) }, ); + if req.slot < highest_slot { + return Err(ValidationError::SlotTooLow(highest_slot)); + } + tracing::debug!(%sender, nonce_diff, %balance_diff, "Applying diffs to account state"); let account_state = match self.account_state(&sender) { From a9e386a6af9a7e647fefda3262da8a8affa2cd37 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Wed, 17 Jul 2024 10:24:31 +0200 Subject: [PATCH 40/48] chore: minor fixes --- bolt-sidecar/src/builder/template.rs | 4 +-- bolt-sidecar/src/state/execution.rs | 40 ++++++++++++---------------- bolt-sidecar/src/state/mod.rs | 11 +++----- 3 files changed, 23 insertions(+), 32 deletions(-) diff --git a/bolt-sidecar/src/builder/template.rs b/bolt-sidecar/src/builder/template.rs index 7fe4eb95a..0fcf8b730 100644 --- a/bolt-sidecar/src/builder/template.rs +++ b/bolt-sidecar/src/builder/template.rs @@ -37,8 +37,8 @@ pub struct BlockTemplate { impl BlockTemplate { /// Return the state diff of the block template. - pub fn state_diff(&self) -> &StateDiff { - &self.state_diff + pub fn get_diff(&self, address: &Address) -> Option<(u64, U256)> { + self.state_diff.get_diff(address) } /// Returns the cloned list of transactions from the constraints. diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index ac43ec29d..bed69408d 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -55,9 +55,7 @@ pub enum ValidationError { #[error("Too many EIP-4844 transactions in target block")] Eip4844Limit, /// The maximum commitments have been reached for the slot. - #[error( - "Already requested a preconfirmation for slot {0}. Slot must be greater than or equal {0}" - )] + #[error("Already requested a preconfirmation for slot {0}. Slot must be >= {0}")] SlotTooLow(u64), /// The maximum commitments have been reached for the slot. #[error("Max commitments reached for slot {0}: {1}")] @@ -177,11 +175,6 @@ impl ExecutionState { self.basefee } - /// Returns the current block templates mapped by slot number - pub fn block_templates(&self) -> &HashMap { - &self.block_templates - } - /// Validates the commitment request against state (historical + intermediate). /// /// NOTE: This function only simulates against execution state, it does not consider @@ -199,14 +192,16 @@ impl ExecutionState { ) -> Result { let CommitmentRequest::Inclusion(req) = request; + let sender = req.sender; + let target_slot = req.slot; + // Validate the chain ID if !req.validate_chain_id(self.chain_id) { return Err(ValidationError::ChainIdMismatch); } // Check if there is room for more commitments - let template = self.get_block_template(req.slot); - if let Some(template) = template { + if let Some(template) = self.get_block_template(target_slot) { if template.transactions_len() >= self.max_commitments_per_slot.get() { return Err(ValidationError::MaxCommitmentsReachedForSlot( self.slot, @@ -241,12 +236,10 @@ impl ExecutionState { return Err(ValidationError::MaxPriorityFeePerGasTooHigh); } - let sender = req.sender; - - tracing::debug!(%sender, target_slot = req.slot, "Trying to commit inclusion request to block template"); + tracing::debug!(%sender, target_slot, "Trying to commit inclusion request to block template"); // Check if the max_fee_per_gas would cover the maximum possible basefee. - let slot_diff = req.slot.saturating_sub(self.slot); + let slot_diff = target_slot.saturating_sub(self.slot); // Calculate the max possible basefee given the slot diff let max_basefee = calculate_max_basefee(self.basefee, slot_diff) @@ -261,16 +254,15 @@ impl ExecutionState { // - the nonce difference from the account state. // - the balance difference from the account state. // - the highest slot number for which the user has requested a preconfirmation. + // // If the templates do not exist, or this is the first request for this sender, // its diffs will be zero. - let (nonce_diff, balance_diff, highest_slot) = self.block_templates().iter().fold( + let (nonce_diff, balance_diff, highest_slot) = self.block_templates.iter().fold( (0, U256::ZERO, 0), |(nonce_diff_acc, balance_diff_acc, highest_slot), (slot, block_template)| { let (nonce_diff, balance_diff, slot) = block_template - .state_diff() .get_diff(&sender) - .map(|d| (d.0, d.1, *slot)) - // TODO: should balance diff be signed? + .map(|(nonce, balance)| (nonce, balance, *slot)) .unwrap_or((0, U256::ZERO, 0)); ( @@ -281,15 +273,16 @@ impl ExecutionState { }, ); - if req.slot < highest_slot { + if target_slot < highest_slot { return Err(ValidationError::SlotTooLow(highest_slot)); } - tracing::debug!(%sender, nonce_diff, %balance_diff, "Applying diffs to account state"); + tracing::trace!(%sender, nonce_diff, %balance_diff, "Applying diffs to account state"); let account_state = match self.account_state(&sender) { Some(account) => account, None => { + // Fetch the account state from the client if it does not exist let account = match self.client.get_account_state(&sender, None).await { Ok(account) => account, Err(err) => { @@ -316,7 +309,7 @@ impl ExecutionState { // Check EIP-4844-specific limits if let Some(transaction) = req.tx.as_eip4844() { - if let Some(template) = self.block_templates.get(&req.slot) { + if let Some(template) = self.block_templates.get(&target_slot) { if template.blob_count() >= MAX_BLOBS_PER_BLOCK { return Err(ValidationError::Eip4844Limit); } @@ -397,7 +390,7 @@ impl ExecutionState { template.retain(*address, *account_state); // Update the account state with the remaining state diff for the next iteration. - if let Some((nonce_diff, balance_diff)) = template.state_diff().get_diff(address) { + if let Some((nonce_diff, balance_diff)) = template.get_diff(address) { // Nonce will always be increased account_state.transaction_count += nonce_diff; // Balance will always be decreased @@ -414,7 +407,7 @@ impl ExecutionState { if let Some(mut account_state) = account_state { // Iterate over all block templates and apply the state diff for (_, template) in self.block_templates.iter() { - if let Some((nonce_diff, balance_diff)) = template.state_diff().get_diff(address) { + if let Some((nonce_diff, balance_diff)) = template.get_diff(address) { // Nonce will always be increased account_state.transaction_count += nonce_diff; // Balance will always be decreased @@ -428,6 +421,7 @@ impl ExecutionState { } } + /// Gets the block template for the given slot number. pub fn get_block_template(&mut self, slot: u64) -> Option<&BlockTemplate> { self.block_templates.get(&slot) } diff --git a/bolt-sidecar/src/state/mod.rs b/bolt-sidecar/src/state/mod.rs index f1967cb47..50d52f284 100644 --- a/bolt-sidecar/src/state/mod.rs +++ b/bolt-sidecar/src/state/mod.rs @@ -261,8 +261,7 @@ mod tests { assert!( state - .block_templates() - .get(&target_slot) + .get_block_template(target_slot) .unwrap() .transactions_len() == 1 @@ -281,8 +280,7 @@ mod tests { .await?; let transactions_len = state - .block_templates() - .get(&target_slot) + .get_block_template(target_slot) .unwrap() .transactions_len(); @@ -325,8 +323,7 @@ mod tests { assert!( state - .block_templates() - .get(&target_slot) + .get_block_template(target_slot) .unwrap() .transactions_len() == 1 @@ -336,7 +333,7 @@ mod tests { // because it's now stale state.update_head(None, target_slot).await?; - assert!(state.block_templates().get(&target_slot).is_none()); + assert!(state.get_block_template(target_slot).is_none()); Ok(()) } From 10969d5a676a1cb5f1b9b75e6e22b43c7d5a5c9f Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Wed, 17 Jul 2024 10:16:39 +0200 Subject: [PATCH 41/48] chore(sidecar): expected and actual values in nonce validation errors --- bolt-sidecar/src/common.rs | 10 ++++++++-- bolt-sidecar/src/state/execution.rs | 6 +++--- bolt-sidecar/src/state/mod.rs | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/bolt-sidecar/src/common.rs b/bolt-sidecar/src/common.rs index 73bed1016..e73c8dbd4 100644 --- a/bolt-sidecar/src/common.rs +++ b/bolt-sidecar/src/common.rs @@ -47,11 +47,17 @@ pub fn validate_transaction( ) -> Result<(), ValidationError> { // Check if the nonce is correct (should be the same as the transaction count) if transaction.nonce() < account_state.transaction_count { - return Err(ValidationError::NonceTooLow); + return Err(ValidationError::NonceTooLow( + account_state.transaction_count, + transaction.nonce(), + )); } if transaction.nonce() > account_state.transaction_count { - return Err(ValidationError::NonceTooHigh); + return Err(ValidationError::NonceTooHigh( + account_state.transaction_count, + transaction.nonce(), + )); } // Check if the balance is enough diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index bed69408d..84d8929b5 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -31,11 +31,11 @@ pub enum ValidationError { #[error("Invalid max basefee calculation: overflow")] MaxBaseFeeCalcOverflow, /// The transaction nonce is too low. - #[error("Transaction nonce too low")] - NonceTooLow, + #[error("Transaction nonce too low. Expected {0}, got {1}")] + NonceTooLow(u64, u64), /// The transaction nonce is too high. #[error("Transaction nonce too high")] - NonceTooHigh, + NonceTooHigh(u64, u64), /// The sender account is a smart contract and has code. #[error("Account has code")] AccountHasCode, diff --git a/bolt-sidecar/src/state/mod.rs b/bolt-sidecar/src/state/mod.rs index 50d52f284..1c0eabcbf 100644 --- a/bolt-sidecar/src/state/mod.rs +++ b/bolt-sidecar/src/state/mod.rs @@ -152,7 +152,7 @@ mod tests { assert!(matches!( state.validate_commitment_request(&request).await, - Err(ValidationError::NonceTooHigh) + Err(ValidationError::NonceTooHigh(_, _)) )); Ok(()) From 7ddb67a0f197f44c24b585a2333905cf0dcf1604 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Wed, 17 Jul 2024 10:37:14 +0200 Subject: [PATCH 42/48] chore(sidecar): move tests --- bolt-sidecar/src/state/execution.rs | 275 ++++++++++++++++++++++++++++ bolt-sidecar/src/state/mod.rs | 273 --------------------------- 2 files changed, 275 insertions(+), 273 deletions(-) diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 84d8929b5..b29468487 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -441,3 +441,278 @@ pub struct StateUpdate { pub min_blob_basefee: u128, pub block_number: u64, } + +#[cfg(test)] +mod tests { + use crate::state::CommitmentDeadline; + use crate::state::Duration; + use std::num::NonZero; + + use alloy_consensus::constants::ETH_TO_WEI; + use alloy_eips::eip2718::Encodable2718; + use alloy_network::EthereumWallet; + use alloy_primitives::{uint, Uint}; + use alloy_provider::{network::TransactionBuilder, Provider, ProviderBuilder}; + use alloy_signer_local::PrivateKeySigner; + use fetcher::{StateClient, StateFetcher}; + + use crate::{ + crypto::{bls::Signer, SignableBLS, SignerBLS}, + primitives::{ConstraintsMessage, SignedConstraints}, + state::fetcher, + test_util::{create_signed_commitment_request, default_test_transaction, launch_anvil}, + }; + + use super::*; + + #[tokio::test] + async fn test_commitment_deadline() { + let time = std::time::Instant::now(); + let mut deadline = CommitmentDeadline::new(0, Duration::from_secs(1)); + + let slot = deadline.wait().await; + println!("Deadline reached. Passed {:?}", time.elapsed()); + assert_eq!(slot, Some(0)); + + let time = std::time::Instant::now(); + let slot = deadline.wait().await; + println!("Deadline reached. Passed {:?}", time.elapsed()); + assert_eq!(slot, None); + } + + #[tokio::test] + async fn test_valid_inclusion_request() -> eyre::Result<()> { + let _ = tracing_subscriber::fmt::try_init(); + + let anvil = launch_anvil(); + let client = StateClient::new(anvil.endpoint_url()); + + let max_comms = NonZero::new(10).unwrap(); + let mut state = ExecutionState::new(client.clone(), max_comms).await?; + + let sender = anvil.addresses().first().unwrap(); + let sender_pk = anvil.keys().first().unwrap(); + + // initialize the state by updating the head once + let slot = client.get_head().await?; + state.update_head(None, slot).await?; + + let tx = default_test_transaction(*sender, None); + + let request = create_signed_commitment_request(tx, sender_pk, 10).await?; + + assert!(state.validate_commitment_request(&request).await.is_ok()); + + Ok(()) + } + + #[tokio::test] + async fn test_invalid_inclusion_request_nonce() -> eyre::Result<()> { + let _ = tracing_subscriber::fmt::try_init(); + + let anvil = launch_anvil(); + let client = StateClient::new(anvil.endpoint_url()); + + let max_comms = NonZero::new(10).unwrap(); + let mut state = ExecutionState::new(client.clone(), max_comms).await?; + + let sender = anvil.addresses().first().unwrap(); + let sender_pk = anvil.keys().first().unwrap(); + + // initialize the state by updating the head once + let slot = client.get_head().await?; + state.update_head(None, slot).await?; + + // Create a transaction with a nonce that is too high + let tx = default_test_transaction(*sender, Some(1)); + + let request = create_signed_commitment_request(tx, sender_pk, 10).await?; + + assert!(matches!( + state.validate_commitment_request(&request).await, + Err(ValidationError::NonceTooHigh(0, 1)) + )); + + Ok(()) + } + + #[tokio::test] + async fn test_invalid_inclusion_request_balance() -> eyre::Result<()> { + let _ = tracing_subscriber::fmt::try_init(); + + let anvil = launch_anvil(); + let client = StateClient::new(anvil.endpoint_url()); + + let max_comms = NonZero::new(10).unwrap(); + let mut state = ExecutionState::new(client.clone(), max_comms).await?; + + let sender = anvil.addresses().first().unwrap(); + let sender_pk = anvil.keys().first().unwrap(); + + // initialize the state by updating the head once + let slot = client.get_head().await?; + state.update_head(None, slot).await?; + + // Create a transaction with a value that is too high + let tx = default_test_transaction(*sender, None) + .with_value(uint!(11_000_U256 * Uint::from(ETH_TO_WEI))); + + let request = create_signed_commitment_request(tx, sender_pk, 10).await?; + + assert!(matches!( + state.validate_commitment_request(&request).await, + Err(ValidationError::InsufficientBalance) + )); + + Ok(()) + } + + #[tokio::test] + async fn test_invalid_inclusion_request_basefee() -> eyre::Result<()> { + let _ = tracing_subscriber::fmt::try_init(); + + let anvil = launch_anvil(); + let client = StateClient::new(anvil.endpoint_url()); + + let max_comms = NonZero::new(10).unwrap(); + let mut state = ExecutionState::new(client.clone(), max_comms).await?; + + let basefee = state.basefee(); + + let sender = anvil.addresses().first().unwrap(); + let sender_pk = anvil.keys().first().unwrap(); + + // initialize the state by updating the head once + let slot = client.get_head().await?; + state.update_head(None, slot).await?; + + // Create a transaction with a basefee that is too low + let tx = default_test_transaction(*sender, None).with_max_fee_per_gas(basefee - 1); + + let request = create_signed_commitment_request(tx, sender_pk, 10).await?; + + assert!(matches!( + state.validate_commitment_request(&request).await, + Err(ValidationError::BaseFeeTooLow(_)) + )); + + Ok(()) + } + + #[tokio::test] + async fn test_invalidate_inclusion_request() -> eyre::Result<()> { + let _ = tracing_subscriber::fmt::try_init(); + + let anvil = launch_anvil(); + let client = StateClient::new(anvil.endpoint_url()); + let provider = ProviderBuilder::new().on_http(anvil.endpoint_url()); + + let max_comms = NonZero::new(10).unwrap(); + let mut state = ExecutionState::new(client.clone(), max_comms).await?; + + let sender = anvil.addresses().first().unwrap(); + let sender_pk = anvil.keys().first().unwrap(); + + // initialize the state by updating the head once + let slot = client.get_head().await?; + state.update_head(None, slot).await?; + + let tx = default_test_transaction(*sender, None); + + // build the signed transaction for submission later + let wallet: PrivateKeySigner = anvil.keys()[0].clone().into(); + let signer: EthereumWallet = wallet.into(); + let signed = tx.clone().build(&signer).await?; + + let target_slot = 10; + let request = create_signed_commitment_request(tx, sender_pk, target_slot).await?; + let inclusion_request = request.as_inclusion_request().unwrap().clone(); + + assert!(state.validate_commitment_request(&request).await.is_ok()); + + let bls_signer = Signer::random(); + let message = ConstraintsMessage::build(0, inclusion_request); + let signature = bls_signer.sign(&message.digest()).unwrap().to_string(); + let signed_constraints = SignedConstraints { message, signature }; + + state.add_constraint(target_slot, signed_constraints); + + assert!( + state + .get_block_template(target_slot) + .unwrap() + .transactions_len() + == 1 + ); + + let notif = provider + .send_raw_transaction(&signed.encoded_2718()) + .await?; + + // Wait for confirmation + let receipt = notif.get_receipt().await?; + + // Update the head, which should invalidate the transaction due to a nonce conflict + state + .update_head(receipt.block_number, receipt.block_number.unwrap()) + .await?; + + let transactions_len = state + .get_block_template(target_slot) + .unwrap() + .transactions_len(); + + assert!(transactions_len == 0); + + Ok(()) + } + + #[tokio::test] + async fn test_invalidate_stale_template() -> eyre::Result<()> { + let _ = tracing_subscriber::fmt::try_init(); + + let anvil = launch_anvil(); + let client = StateClient::new(anvil.endpoint_url()); + + let max_comms = NonZero::new(10).unwrap(); + let mut state = ExecutionState::new(client.clone(), max_comms).await?; + + let sender = anvil.addresses().first().unwrap(); + let sender_pk = anvil.keys().first().unwrap(); + + // initialize the state by updating the head once + let slot = client.get_head().await?; + state.update_head(None, slot).await?; + + let tx = default_test_transaction(*sender, None); + + let target_slot = 10; + let request = create_signed_commitment_request(tx, sender_pk, target_slot).await?; + let inclusion_request = request.as_inclusion_request().unwrap().clone(); + + assert!(state.validate_commitment_request(&request).await.is_ok()); + + let bls_signer = Signer::random(); + let message = ConstraintsMessage::build(0, inclusion_request); + let signature = bls_signer.sign(&message.digest()).unwrap().to_string(); + let signed_constraints = SignedConstraints { message, signature }; + + state.add_constraint(target_slot, signed_constraints); + + assert!( + state + .get_block_template(target_slot) + .unwrap() + .transactions_len() + == 1 + ); + + // fast-forward the head to the target slot, which should invalidate the entire template + // because it's now stale + state.update_head(None, target_slot).await?; + + assert!(state.get_block_template(target_slot).is_none()); + + Ok(()) + } +} diff --git a/bolt-sidecar/src/state/mod.rs b/bolt-sidecar/src/state/mod.rs index 1c0eabcbf..84a349734 100644 --- a/bolt-sidecar/src/state/mod.rs +++ b/bolt-sidecar/src/state/mod.rs @@ -65,276 +65,3 @@ impl Future for CommitmentDeadline { } } } - -#[cfg(test)] -mod tests { - use std::num::NonZero; - - use alloy_consensus::constants::ETH_TO_WEI; - use alloy_eips::eip2718::Encodable2718; - use alloy_network::EthereumWallet; - use alloy_primitives::{uint, Uint}; - use alloy_provider::{network::TransactionBuilder, Provider, ProviderBuilder}; - use alloy_signer_local::PrivateKeySigner; - use execution::{ExecutionState, ValidationError}; - use fetcher::{StateClient, StateFetcher}; - - use crate::{ - crypto::{bls::Signer, SignableBLS, SignerBLS}, - primitives::{ConstraintsMessage, SignedConstraints}, - test_util::{create_signed_commitment_request, default_test_transaction, launch_anvil}, - }; - - use super::*; - - #[tokio::test] - async fn test_commitment_deadline() { - let time = std::time::Instant::now(); - let mut deadline = CommitmentDeadline::new(0, Duration::from_secs(1)); - - let slot = deadline.wait().await; - println!("Deadline reached. Passed {:?}", time.elapsed()); - assert_eq!(slot, Some(0)); - - let time = std::time::Instant::now(); - let slot = deadline.wait().await; - println!("Deadline reached. Passed {:?}", time.elapsed()); - assert_eq!(slot, None); - } - - #[tokio::test] - async fn test_valid_inclusion_request() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let max_comms = NonZero::new(10).unwrap(); - let mut state = ExecutionState::new(client.clone(), max_comms).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - let tx = default_test_transaction(*sender, None); - - let request = create_signed_commitment_request(tx, sender_pk, 10).await?; - - assert!(state.validate_commitment_request(&request).await.is_ok()); - - Ok(()) - } - - #[tokio::test] - async fn test_invalid_inclusion_request_nonce() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let max_comms = NonZero::new(10).unwrap(); - let mut state = ExecutionState::new(client.clone(), max_comms).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - // Create a transaction with a nonce that is too high - let tx = default_test_transaction(*sender, Some(1)); - - let request = create_signed_commitment_request(tx, sender_pk, 10).await?; - - assert!(matches!( - state.validate_commitment_request(&request).await, - Err(ValidationError::NonceTooHigh(_, _)) - )); - - Ok(()) - } - - #[tokio::test] - async fn test_invalid_inclusion_request_balance() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let max_comms = NonZero::new(10).unwrap(); - let mut state = ExecutionState::new(client.clone(), max_comms).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - // Create a transaction with a value that is too high - let tx = default_test_transaction(*sender, None) - .with_value(uint!(11_000_U256 * Uint::from(ETH_TO_WEI))); - - let request = create_signed_commitment_request(tx, sender_pk, 10).await?; - - assert!(matches!( - state.validate_commitment_request(&request).await, - Err(ValidationError::InsufficientBalance) - )); - - Ok(()) - } - - #[tokio::test] - async fn test_invalid_inclusion_request_basefee() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let max_comms = NonZero::new(10).unwrap(); - let mut state = ExecutionState::new(client.clone(), max_comms).await?; - - let basefee = state.basefee(); - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - // Create a transaction with a basefee that is too low - let tx = default_test_transaction(*sender, None).with_max_fee_per_gas(basefee - 1); - - let request = create_signed_commitment_request(tx, sender_pk, 10).await?; - - assert!(matches!( - state.validate_commitment_request(&request).await, - Err(ValidationError::BaseFeeTooLow(_)) - )); - - Ok(()) - } - - #[tokio::test] - async fn test_invalidate_inclusion_request() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - let provider = ProviderBuilder::new().on_http(anvil.endpoint_url()); - - let max_comms = NonZero::new(10).unwrap(); - let mut state = ExecutionState::new(client.clone(), max_comms).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - let tx = default_test_transaction(*sender, None); - - // build the signed transaction for submission later - let wallet: PrivateKeySigner = anvil.keys()[0].clone().into(); - let signer: EthereumWallet = wallet.into(); - let signed = tx.clone().build(&signer).await?; - - let target_slot = 10; - let request = create_signed_commitment_request(tx, sender_pk, target_slot).await?; - let inclusion_request = request.as_inclusion_request().unwrap().clone(); - - assert!(state.validate_commitment_request(&request).await.is_ok()); - - let bls_signer = Signer::random(); - let message = ConstraintsMessage::build(0, inclusion_request); - let signature = bls_signer.sign(&message.digest()).unwrap().to_string(); - let signed_constraints = SignedConstraints { message, signature }; - - state.add_constraint(target_slot, signed_constraints); - - assert!( - state - .get_block_template(target_slot) - .unwrap() - .transactions_len() - == 1 - ); - - let notif = provider - .send_raw_transaction(&signed.encoded_2718()) - .await?; - - // Wait for confirmation - let receipt = notif.get_receipt().await?; - - // Update the head, which should invalidate the transaction due to a nonce conflict - state - .update_head(receipt.block_number, receipt.block_number.unwrap()) - .await?; - - let transactions_len = state - .get_block_template(target_slot) - .unwrap() - .transactions_len(); - - assert!(transactions_len == 0); - - Ok(()) - } - - #[tokio::test] - async fn test_invalidate_stale_template() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let max_comms = NonZero::new(10).unwrap(); - let mut state = ExecutionState::new(client.clone(), max_comms).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - let tx = default_test_transaction(*sender, None); - - let target_slot = 10; - let request = create_signed_commitment_request(tx, sender_pk, target_slot).await?; - let inclusion_request = request.as_inclusion_request().unwrap().clone(); - - assert!(state.validate_commitment_request(&request).await.is_ok()); - - let bls_signer = Signer::random(); - let message = ConstraintsMessage::build(0, inclusion_request); - let signature = bls_signer.sign(&message.digest()).unwrap().to_string(); - let signed_constraints = SignedConstraints { message, signature }; - - state.add_constraint(target_slot, signed_constraints); - - assert!( - state - .get_block_template(target_slot) - .unwrap() - .transactions_len() - == 1 - ); - - // fast-forward the head to the target slot, which should invalidate the entire template - // because it's now stale - state.update_head(None, target_slot).await?; - - assert!(state.get_block_template(target_slot).is_none()); - - Ok(()) - } -} From 5cbf43466cab301daade71b8cffd4c31a48b5418 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Wed, 17 Jul 2024 10:52:19 +0200 Subject: [PATCH 43/48] test(sidecar): invalid inclusion slot --- bolt-sidecar/src/builder/template.rs | 4 +-- bolt-sidecar/src/state/execution.rs | 42 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/bolt-sidecar/src/builder/template.rs b/bolt-sidecar/src/builder/template.rs index 0fcf8b730..f424c431d 100644 --- a/bolt-sidecar/src/builder/template.rs +++ b/bolt-sidecar/src/builder/template.rs @@ -30,7 +30,7 @@ use crate::{ #[derive(Debug, Default)] pub struct BlockTemplate { /// The state diffs per address given the list of commitments. - state_diff: StateDiff, + pub(crate) state_diff: StateDiff, /// The signed constraints associated to the block pub signed_constraints_list: Vec, } @@ -206,7 +206,7 @@ impl BlockTemplate { pub struct StateDiff { /// Map of diffs per address. Each diff is a tuple of the nonce and balance diff /// that should be applied to the current state. - diffs: HashMap, + pub(crate) diffs: HashMap, } impl StateDiff { diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index b29468487..5b100aee2 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -444,6 +444,7 @@ pub struct StateUpdate { #[cfg(test)] mod tests { + use crate::builder::template::StateDiff; use crate::state::CommitmentDeadline; use crate::state::Duration; use std::num::NonZero; @@ -506,6 +507,47 @@ mod tests { Ok(()) } + #[tokio::test] + async fn test_invalid_inclusion_slot() -> eyre::Result<()> { + let _ = tracing_subscriber::fmt::try_init(); + + let anvil = launch_anvil(); + let client = StateClient::new(anvil.endpoint_url()); + + let max_comms = NonZero::new(10).unwrap(); + let mut state = ExecutionState::new(client.clone(), max_comms).await?; + + let sender = anvil.addresses().first().unwrap(); + let sender_pk = anvil.keys().first().unwrap(); + + // initialize the state by updating the head once + let slot = client.get_head().await?; + state.update_head(None, slot).await?; + + // Create a transaction with a nonce that is too high + let tx = default_test_transaction(*sender, Some(1)); + + let request = create_signed_commitment_request(tx, sender_pk, 10).await?; + + // Insert a constraint diff for slot 11 + let mut diffs = HashMap::new(); + diffs.insert(*sender, (1, U256::ZERO)); + state.block_templates.insert( + 11, + BlockTemplate { + state_diff: StateDiff { diffs }, + signed_constraints_list: vec![], + }, + ); + + assert!(matches!( + state.validate_commitment_request(&request).await, + Err(ValidationError::SlotTooLow(11)) + )); + + Ok(()) + } + #[tokio::test] async fn test_invalid_inclusion_request_nonce() -> eyre::Result<()> { let _ = tracing_subscriber::fmt::try_init(); From 1862cc40be6810685bb7f07e2ad2e34c489f27b2 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Wed, 17 Jul 2024 11:10:31 +0200 Subject: [PATCH 44/48] chore: added commitment balance validation multiple test --- bolt-sidecar/src/client/rpc.rs | 5 ++ bolt-sidecar/src/state/execution.rs | 89 ++++++++++++++++++++++------- bolt-sidecar/src/state/fetcher.rs | 7 +++ bolt-sidecar/src/state/mod.rs | 21 +++++++ 4 files changed, 101 insertions(+), 21 deletions(-) diff --git a/bolt-sidecar/src/client/rpc.rs b/bolt-sidecar/src/client/rpc.rs index d116ba211..75f23ee6a 100644 --- a/bolt-sidecar/src/client/rpc.rs +++ b/bolt-sidecar/src/client/rpc.rs @@ -193,6 +193,11 @@ impl RpcClient { self.0.request("debug_traceCall", params).await } + + /// Send a raw transaction to the network. + pub async fn send_raw_transaction(&self, raw: Bytes) -> TransportResult { + self.0.request("eth_sendRawTransaction", [raw]).await + } } impl Deref for RpcClient { diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 5b100aee2..c71ae88a3 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -267,7 +267,7 @@ impl ExecutionState { ( nonce_diff_acc + nonce_diff, - balance_diff_acc + balance_diff, + balance_diff_acc.saturating_add(balance_diff), u64::max(highest_slot, slot), ) }, @@ -299,8 +299,8 @@ impl ExecutionState { }; let account_state_with_diffs = AccountState { - transaction_count: account_state.transaction_count + nonce_diff, - balance: account_state.balance - balance_diff, + transaction_count: account_state.transaction_count.saturating_add(nonce_diff), + balance: account_state.balance.saturating_sub(balance_diff), has_code: account_state.has_code, }; @@ -445,9 +445,8 @@ pub struct StateUpdate { #[cfg(test)] mod tests { use crate::builder::template::StateDiff; - use crate::state::CommitmentDeadline; - use crate::state::Duration; - use std::num::NonZero; + use std::str::FromStr; + use std::{num::NonZero, time::Duration}; use alloy_consensus::constants::ETH_TO_WEI; use alloy_eips::eip2718::Encodable2718; @@ -466,21 +465,6 @@ mod tests { use super::*; - #[tokio::test] - async fn test_commitment_deadline() { - let time = std::time::Instant::now(); - let mut deadline = CommitmentDeadline::new(0, Duration::from_secs(1)); - - let slot = deadline.wait().await; - println!("Deadline reached. Passed {:?}", time.elapsed()); - assert_eq!(slot, Some(0)); - - let time = std::time::Instant::now(); - let slot = deadline.wait().await; - println!("Deadline reached. Passed {:?}", time.elapsed()); - assert_eq!(slot, None); - } - #[tokio::test] async fn test_valid_inclusion_request() -> eyre::Result<()> { let _ = tracing_subscriber::fmt::try_init(); @@ -609,6 +593,69 @@ mod tests { Ok(()) } + #[tokio::test] + async fn test_invalid_inclusion_request_balance_multiple() -> eyre::Result<()> { + let _ = tracing_subscriber::fmt::try_init(); + + let anvil = launch_anvil(); + let client = StateClient::new(anvil.endpoint_url()); + + let max_comms = NonZero::new(10).unwrap(); + let mut state = ExecutionState::new(client.clone(), max_comms).await?; + + let sender = anvil.addresses().first().unwrap(); + let sender_pk = anvil.keys().first().unwrap(); + let signer = Signer::random(); + + // initialize the state by updating the head once + let slot = client.get_head().await?; + state.update_head(None, slot).await?; + + // Set the sender balance to just enough to pay for 1 transaction + let balance = U256::from_str("500000000000000").unwrap(); // leave just 0.0005 ETH + let sender_account = client.get_account_state(sender, None).await.unwrap(); + let balance_to_burn = sender_account.balance - balance; + + // burn the balance + let tx = default_test_transaction(*sender, Some(0)).with_value(uint!(balance_to_burn)); + let request = create_signed_commitment_request(tx, sender_pk, 10).await?; + let tx_bytes = request + .as_inclusion_request() + .unwrap() + .tx + .envelope_encoded(); + let _ = client.inner().send_raw_transaction(tx_bytes).await?; + + // wait for the transaction to be included to update the sender balance + tokio::time::sleep(Duration::from_secs(2)).await; + let slot = client.get_head().await?; + state.update_head(None, slot).await?; + + // create a new transaction and request a preconfirmation for it + let tx = default_test_transaction(*sender, Some(1)); + let request = create_signed_commitment_request(tx, sender_pk, 10).await?; + + assert!(state.validate_commitment_request(&request).await.is_ok()); + + let message = ConstraintsMessage::build(0, request.as_inclusion_request().unwrap().clone()); + let signature = signer.sign(&message.digest())?.to_string(); + let signed_constraints = SignedConstraints { message, signature }; + state.add_constraint(10, signed_constraints); + + // create a new transaction and request a preconfirmation for it + let tx = default_test_transaction(*sender, Some(3)); + let request = create_signed_commitment_request(tx, sender_pk, 10).await?; + + // this should fail because the balance is insufficient as we spent + // all of it on the previous preconfirmation + assert!(matches!( + state.validate_commitment_request(&request).await, + Err(ValidationError::InsufficientBalance) + )); + + Ok(()) + } + #[tokio::test] async fn test_invalid_inclusion_request_basefee() -> eyre::Result<()> { let _ = tracing_subscriber::fmt::try_init(); diff --git a/bolt-sidecar/src/state/fetcher.rs b/bolt-sidecar/src/state/fetcher.rs index cebf5b021..2513c383c 100644 --- a/bolt-sidecar/src/state/fetcher.rs +++ b/bolt-sidecar/src/state/fetcher.rs @@ -217,6 +217,13 @@ impl StateFetcher for StateClient { } } +#[cfg(test)] +impl StateClient { + pub fn inner(&self) -> &RpcClient { + &self.client + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/bolt-sidecar/src/state/mod.rs b/bolt-sidecar/src/state/mod.rs index 84a349734..02dfa0237 100644 --- a/bolt-sidecar/src/state/mod.rs +++ b/bolt-sidecar/src/state/mod.rs @@ -65,3 +65,24 @@ impl Future for CommitmentDeadline { } } } + +#[cfg(test)] +mod tests { + + use super::*; + + #[tokio::test] + async fn test_commitment_deadline() { + let time = std::time::Instant::now(); + let mut deadline = CommitmentDeadline::new(0, Duration::from_secs(1)); + + let slot = deadline.wait().await; + println!("Deadline reached. Passed {:?}", time.elapsed()); + assert_eq!(slot, Some(0)); + + let time = std::time::Instant::now(); + let slot = deadline.wait().await; + println!("Deadline reached. Passed {:?}", time.elapsed()); + assert_eq!(slot, None); + } +} From 9351357b537112969d4d1dd49ec3cb122175fa90 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Wed, 17 Jul 2024 11:24:50 +0200 Subject: [PATCH 45/48] chore: rm duplicated logic of checking intermediate diffs --- bolt-sidecar/src/state/execution.rs | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index c71ae88a3..02587b84e 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -279,7 +279,7 @@ impl ExecutionState { tracing::trace!(%sender, nonce_diff, %balance_diff, "Applying diffs to account state"); - let account_state = match self.account_state(&sender) { + let account_state = match self.account_state(&sender).copied() { Some(account) => account, None => { // Fetch the account state from the client if it does not exist @@ -400,25 +400,9 @@ impl ExecutionState { } } - /// Returns the account state for the given address INCLUDING any intermediate block templates state. - fn account_state(&self, address: &Address) -> Option { - let account_state = self.account_states.get(address).copied(); - - if let Some(mut account_state) = account_state { - // Iterate over all block templates and apply the state diff - for (_, template) in self.block_templates.iter() { - if let Some((nonce_diff, balance_diff)) = template.get_diff(address) { - // Nonce will always be increased - account_state.transaction_count += nonce_diff; - // Balance will always be decreased - account_state.balance -= balance_diff; - } - } - - Some(account_state) - } else { - None - } + /// Returns the cached account state for the given address + fn account_state(&self, address: &Address) -> Option<&AccountState> { + self.account_states.get(address) } /// Gets the block template for the given slot number. @@ -643,7 +627,7 @@ mod tests { state.add_constraint(10, signed_constraints); // create a new transaction and request a preconfirmation for it - let tx = default_test_transaction(*sender, Some(3)); + let tx = default_test_transaction(*sender, Some(2)); let request = create_signed_commitment_request(tx, sender_pk, 10).await?; // this should fail because the balance is insufficient as we spent From 2f9afcd98fac5725f456b11ea840ef52644cf4cb Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Wed, 17 Jul 2024 11:32:18 +0200 Subject: [PATCH 46/48] test(sidecar): nonce too high and too low with diffs --- bolt-sidecar/src/state/execution.rs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 02587b84e..0d53997d9 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -533,14 +533,37 @@ mod tests { let slot = client.get_head().await?; state.update_head(None, slot).await?; + // Insert a constraint diff for slot 9 to simulate nonce increment + let mut diffs = HashMap::new(); + diffs.insert(*sender, (1, U256::ZERO)); + state.block_templates.insert( + 9, + BlockTemplate { + state_diff: StateDiff { diffs }, + signed_constraints_list: vec![], + }, + ); + + // Create a transaction with a nonce that is too low + let tx = default_test_transaction(*sender, Some(0)); + + let request = create_signed_commitment_request(tx, sender_pk, 10).await?; + + assert!(matches!( + state.validate_commitment_request(&request).await, + Err(ValidationError::NonceTooLow(1, 0)) + )); + + assert!(state.account_states.get(sender).unwrap().transaction_count == 0); + // Create a transaction with a nonce that is too high - let tx = default_test_transaction(*sender, Some(1)); + let tx = default_test_transaction(*sender, Some(2)); let request = create_signed_commitment_request(tx, sender_pk, 10).await?; assert!(matches!( state.validate_commitment_request(&request).await, - Err(ValidationError::NonceTooHigh(0, 1)) + Err(ValidationError::NonceTooHigh(1, 2)) )); Ok(()) From 17d77523b9f7c4b15622067e436f64999c2617d6 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Wed, 17 Jul 2024 12:01:27 +0200 Subject: [PATCH 47/48] test(sidecar): fix test base fee too low --- bolt-sidecar/src/state/execution.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 0d53997d9..84db76e1c 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -683,7 +683,9 @@ mod tests { state.update_head(None, slot).await?; // Create a transaction with a basefee that is too low - let tx = default_test_transaction(*sender, None).with_max_fee_per_gas(basefee - 1); + let tx = default_test_transaction(*sender, None) + .with_max_fee_per_gas(basefee - 1) + .with_max_priority_fee_per_gas(basefee / 2); let request = create_signed_commitment_request(tx, sender_pk, 10).await?; From 0d1ce4ac09af0a94d427b480ed696600494634dd Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Wed, 17 Jul 2024 12:28:05 +0200 Subject: [PATCH 48/48] test --- bolt-sidecar/src/state/execution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 84db76e1c..bec286b5c 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -806,7 +806,7 @@ mod tests { ); // fast-forward the head to the target slot, which should invalidate the entire template - // because it's now stale + // because it's now stale. state.update_head(None, target_slot).await?; assert!(state.get_block_template(target_slot).is_none());