mirror of
https://github.com/0glabs/0g-storage-node.git
synced 2025-02-23 12:15:18 +00:00
add dynamic gas price adjustment when submitting pora (#324)
This commit is contained in:
parent
40d435597a
commit
9ce215b919
@ -1,9 +1,10 @@
|
|||||||
use contract_interface::PoraAnswer;
|
use contract_interface::PoraAnswer;
|
||||||
use contract_interface::{PoraMine, ZgsFlow};
|
use contract_interface::{PoraMine, ZgsFlow};
|
||||||
use ethereum_types::U256;
|
use ethereum_types::U256;
|
||||||
|
use ethers::abi::Detokenize;
|
||||||
use ethers::contract::ContractCall;
|
use ethers::contract::ContractCall;
|
||||||
use ethers::prelude::{Http, Provider, RetryClient};
|
use ethers::prelude::{Http, Provider, RetryClient};
|
||||||
use ethers::providers::PendingTransaction;
|
use ethers::providers::{Middleware, ProviderError};
|
||||||
use hex::ToHex;
|
use hex::ToHex;
|
||||||
use shared_types::FlowRangeProof;
|
use shared_types::FlowRangeProof;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -20,6 +21,7 @@ use crate::watcher::MineContextMessage;
|
|||||||
use zgs_spec::{BYTES_PER_SEAL, SECTORS_PER_SEAL};
|
use zgs_spec::{BYTES_PER_SEAL, SECTORS_PER_SEAL};
|
||||||
|
|
||||||
const SUBMISSION_RETRIES: usize = 15;
|
const SUBMISSION_RETRIES: usize = 15;
|
||||||
|
const ADJUST_GAS_RETRIES: usize = 20;
|
||||||
|
|
||||||
pub struct Submitter {
|
pub struct Submitter {
|
||||||
mine_answer_receiver: mpsc::UnboundedReceiver<AnswerWithoutProof>,
|
mine_answer_receiver: mpsc::UnboundedReceiver<AnswerWithoutProof>,
|
||||||
@ -28,6 +30,7 @@ pub struct Submitter {
|
|||||||
flow_contract: ZgsFlow<Provider<RetryClient<Http>>>,
|
flow_contract: ZgsFlow<Provider<RetryClient<Http>>>,
|
||||||
default_gas_limit: Option<U256>,
|
default_gas_limit: Option<U256>,
|
||||||
store: Arc<Store>,
|
store: Arc<Store>,
|
||||||
|
provider: Arc<Provider<RetryClient<Http>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Submitter {
|
impl Submitter {
|
||||||
@ -41,7 +44,7 @@ impl Submitter {
|
|||||||
config: &MinerConfig,
|
config: &MinerConfig,
|
||||||
) {
|
) {
|
||||||
let mine_contract = PoraMine::new(config.mine_address, signing_provider);
|
let mine_contract = PoraMine::new(config.mine_address, signing_provider);
|
||||||
let flow_contract = ZgsFlow::new(config.flow_address, provider);
|
let flow_contract = ZgsFlow::new(config.flow_address, provider.clone());
|
||||||
let default_gas_limit = config.submission_gas;
|
let default_gas_limit = config.submission_gas;
|
||||||
|
|
||||||
let submitter = Submitter {
|
let submitter = Submitter {
|
||||||
@ -51,6 +54,7 @@ impl Submitter {
|
|||||||
flow_contract,
|
flow_contract,
|
||||||
store,
|
store,
|
||||||
default_gas_limit,
|
default_gas_limit,
|
||||||
|
provider,
|
||||||
};
|
};
|
||||||
executor.spawn(
|
executor.spawn(
|
||||||
async move { Box::pin(submitter.start()).await },
|
async move { Box::pin(submitter.start()).await },
|
||||||
@ -153,29 +157,82 @@ impl Submitter {
|
|||||||
submission_call.estimate_gas().await
|
submission_call.estimate_gas().await
|
||||||
);
|
);
|
||||||
|
|
||||||
let pending_transaction: PendingTransaction<'_, _> = submission_call
|
self.submit_with_retry(submission_call).await
|
||||||
.send()
|
}
|
||||||
|
|
||||||
|
async fn submit_with_retry<M: Middleware, T: Detokenize>(
|
||||||
|
&self,
|
||||||
|
mut submission_call: ContractCall<M, T>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let mut gas_price = self
|
||||||
|
.provider
|
||||||
|
.get_gas_price()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| format!("Fail to send PoRA submission transaction: {:?}", e))?;
|
.map_err(|e| format!("Failed to get current gas price {:?}", e))?;
|
||||||
|
let mut n_retry = 0;
|
||||||
|
while n_retry < ADJUST_GAS_RETRIES {
|
||||||
|
n_retry += 1;
|
||||||
|
submission_call = submission_call.gas_price(gas_price);
|
||||||
|
let pending_transaction = match submission_call.send().await {
|
||||||
|
Ok(tx) => tx,
|
||||||
|
Err(e) => {
|
||||||
|
if e.to_string().contains("insufficient funds")
|
||||||
|
|| e.to_string().contains("out of gas")
|
||||||
|
{
|
||||||
|
return Err(format!(
|
||||||
|
"Fail to execute PoRA submission transaction: {:?}",
|
||||||
|
e
|
||||||
|
));
|
||||||
|
}
|
||||||
|
// Log the error and increase gas.
|
||||||
|
debug!("Error sending transaction: {:?}", e);
|
||||||
|
gas_price = next_gas_price(gas_price);
|
||||||
|
continue; // retry sending
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"Signed submission transaction hash: {:?}",
|
"Signed submission transaction hash: {:?}",
|
||||||
pending_transaction.tx_hash()
|
pending_transaction.tx_hash()
|
||||||
);
|
);
|
||||||
|
|
||||||
let receipt = pending_transaction
|
let receipt_result = pending_transaction
|
||||||
.retries(SUBMISSION_RETRIES)
|
.retries(SUBMISSION_RETRIES)
|
||||||
.interval(Duration::from_secs(2))
|
.interval(Duration::from_secs(2))
|
||||||
.await
|
.await;
|
||||||
.map_err(|e| format!("Fail to execute PoRA submission transaction: {:?}", e))?
|
|
||||||
.ok_or(format!(
|
|
||||||
"PoRA submission transaction dropped after {} retries",
|
|
||||||
SUBMISSION_RETRIES
|
|
||||||
))?;
|
|
||||||
|
|
||||||
info!("Submit PoRA success, receipt: {:?}", receipt);
|
match receipt_result {
|
||||||
|
Ok(Some(receipt)) => {
|
||||||
|
// Successfully executed the transaction.
|
||||||
|
info!("Submit PoRA success, receipt: {:?}", receipt);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Ok(None) => {
|
||||||
|
// The transaction did not complete within the specified waiting time.
|
||||||
|
debug!(
|
||||||
|
"Transaction dropped after {} retries; increasing gas and retrying",
|
||||||
|
SUBMISSION_RETRIES
|
||||||
|
);
|
||||||
|
gas_price = next_gas_price(gas_price);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Err(ProviderError::HTTPError(e)) => {
|
||||||
|
// For HTTP errors, increase gas and retry.
|
||||||
|
debug!("HTTP error retrieving receipt: {:?}", e);
|
||||||
|
gas_price = next_gas_price(gas_price);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
// For all other errors, return immediately.
|
||||||
|
return Err(format!(
|
||||||
|
"Fail to execute PoRA submission transaction: {:?}",
|
||||||
|
e
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Err("Submission failed after retries".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,3 +243,7 @@ fn flow_proof_to_pora_merkle_proof(flow_proof: FlowRangeProof) -> Vec<[u8; 32]>
|
|||||||
// Exclude `item`, the nodes in the sealed data subtree, and `root`.
|
// Exclude `item`, the nodes in the sealed data subtree, and `root`.
|
||||||
full_proof[depth_in_sealed_data + 1..full_proof.len() - 1].to_vec()
|
full_proof[depth_in_sealed_data + 1..full_proof.len() - 1].to_vec()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn next_gas_price(current_gas_price: U256) -> U256 {
|
||||||
|
current_gas_price * U256::from(11) / U256::from(10)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user