Fix issue in polling for transaction signatures (#4923)

- Specifically if multiple confirmation for the signature is requested
This commit is contained in:
Pankaj Garg 2019-07-02 20:56:10 -07:00 committed by GitHub
parent 55b8ff72d0
commit f551b34725
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 28 deletions

View File

@ -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(

View File

@ -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)?)

View File

@ -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<()> {

View File

@ -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<()>;