Fix issue in polling for transaction signatures (#4923)
- Specifically if multiple confirmation for the signature is requested
This commit is contained in:
parent
55b8ff72d0
commit
f551b34725
|
@ -443,10 +443,9 @@ impl RpcClient {
|
|||
&self,
|
||||
signature: &Signature,
|
||||
min_confirmed_blocks: usize,
|
||||
) -> io::Result<()> {
|
||||
) -> io::Result<usize> {
|
||||
let mut now = Instant::now();
|
||||
let mut confirmed_blocks = 0;
|
||||
let mut wait_time = 15;
|
||||
loop {
|
||||
let response = self.get_num_blocks_since_signature_confirmation(signature);
|
||||
match response {
|
||||
|
@ -461,12 +460,6 @@ impl RpcClient {
|
|||
);
|
||||
now = Instant::now();
|
||||
confirmed_blocks = count;
|
||||
// If the signature has been confirmed once, wait extra while reconfirming it
|
||||
// One confirmation means the transaction has been seen by the network, so
|
||||
// next confirmation (for a higher block count) should come through.
|
||||
// Returning an error prematurely will cause a valid transaction to be deemed
|
||||
// as failure.
|
||||
wait_time = 30;
|
||||
}
|
||||
if count >= min_confirmed_blocks {
|
||||
break;
|
||||
|
@ -476,7 +469,7 @@ impl RpcClient {
|
|||
debug!("check_confirmations request failed: {:?}", err);
|
||||
}
|
||||
};
|
||||
if now.elapsed().as_secs() > wait_time {
|
||||
if now.elapsed().as_secs() > 15 {
|
||||
info!(
|
||||
"signature {} confirmed {} out of {} failed after {} ms",
|
||||
signature,
|
||||
|
@ -484,12 +477,16 @@ impl RpcClient {
|
|||
min_confirmed_blocks,
|
||||
now.elapsed().as_millis()
|
||||
);
|
||||
// TODO: Return a better error.
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "signature not found"));
|
||||
if confirmed_blocks > 0 {
|
||||
return Ok(confirmed_blocks);
|
||||
} else {
|
||||
// TODO: Return a better error.
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "signature not found"));
|
||||
}
|
||||
}
|
||||
sleep(Duration::from_secs(1));
|
||||
}
|
||||
Ok(())
|
||||
Ok(confirmed_blocks)
|
||||
}
|
||||
|
||||
pub fn get_num_blocks_since_signature_confirmation(
|
||||
|
|
|
@ -203,26 +203,38 @@ impl ThinClient {
|
|||
keypairs: &[&Keypair],
|
||||
transaction: &mut Transaction,
|
||||
tries: usize,
|
||||
min_confirmed_blocks: usize,
|
||||
pending_confirmations: usize,
|
||||
) -> io::Result<Signature> {
|
||||
for x in 0..tries {
|
||||
let now = Instant::now();
|
||||
let mut buf = vec![0; serialized_size(&transaction).unwrap() as usize];
|
||||
let mut wr = std::io::Cursor::new(&mut buf[..]);
|
||||
let mut num_confirmed = 0;
|
||||
let mut wait_time = MAX_PROCESSING_AGE;
|
||||
serialize_into(&mut wr, &transaction)
|
||||
.expect("serialize Transaction in pub fn transfer_signed");
|
||||
// resend the same transaction until the transaction has no chance of succeeding
|
||||
while now.elapsed().as_secs() < MAX_PROCESSING_AGE as u64 {
|
||||
self.transactions_socket
|
||||
.send_to(&buf[..], &self.transactions_addr())?;
|
||||
if self
|
||||
.poll_for_signature_confirmation(
|
||||
&transaction.signatures[0],
|
||||
min_confirmed_blocks,
|
||||
)
|
||||
.is_ok()
|
||||
{
|
||||
return Ok(transaction.signatures[0]);
|
||||
while now.elapsed().as_secs() < wait_time as u64 {
|
||||
if num_confirmed == 0 {
|
||||
// Send the transaction if there has been no confirmation (e.g. the first time)
|
||||
self.transactions_socket
|
||||
.send_to(&buf[..], &self.transactions_addr())?;
|
||||
}
|
||||
|
||||
if let Ok(confirmed_blocks) = self.poll_for_signature_confirmation(
|
||||
&transaction.signatures[0],
|
||||
pending_confirmations,
|
||||
) {
|
||||
num_confirmed = confirmed_blocks;
|
||||
if confirmed_blocks >= pending_confirmations {
|
||||
return Ok(transaction.signatures[0]);
|
||||
}
|
||||
// Since network has seen the transaction, wait longer to receive
|
||||
// all pending confirmations. Resending the transaction could result into
|
||||
// extra transaction fees
|
||||
wait_time = wait_time.max(
|
||||
MAX_PROCESSING_AGE * pending_confirmations.saturating_sub(num_confirmed),
|
||||
);
|
||||
}
|
||||
}
|
||||
info!(
|
||||
|
@ -385,7 +397,7 @@ impl SyncClient for ThinClient {
|
|||
&self,
|
||||
signature: &Signature,
|
||||
min_confirmed_blocks: usize,
|
||||
) -> TransportResult<()> {
|
||||
) -> TransportResult<usize> {
|
||||
Ok(self
|
||||
.rpc_client()
|
||||
.poll_for_signature_confirmation(signature, min_confirmed_blocks)?)
|
||||
|
|
|
@ -127,7 +127,7 @@ impl SyncClient for BankClient {
|
|||
&self,
|
||||
signature: &Signature,
|
||||
min_confirmed_blocks: usize,
|
||||
) -> Result<()> {
|
||||
) -> Result<usize> {
|
||||
let mut now = Instant::now();
|
||||
let mut confirmed_blocks = 0;
|
||||
loop {
|
||||
|
@ -152,7 +152,7 @@ impl SyncClient for BankClient {
|
|||
}
|
||||
sleep(Duration::from_millis(250));
|
||||
}
|
||||
Ok(())
|
||||
Ok(confirmed_blocks)
|
||||
}
|
||||
|
||||
fn poll_for_signature(&self, signature: &Signature) -> Result<()> {
|
||||
|
|
|
@ -64,7 +64,7 @@ pub trait SyncClient {
|
|||
&self,
|
||||
signature: &Signature,
|
||||
min_confirmed_blocks: usize,
|
||||
) -> Result<()>;
|
||||
) -> Result<usize>;
|
||||
|
||||
/// Poll to confirm a transaction.
|
||||
fn poll_for_signature(&self, signature: &Signature) -> Result<()>;
|
||||
|
|
Loading…
Reference in New Issue