Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

501 fix occassional horizonresponse decodeerror #502

Merged
merged 16 commits into from
Apr 8, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Replace fee-bump transaction with normal transaction
ebma committed Mar 27, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit bf20c68a0a9cc4a536f3af83fd01b9380020753f
6 changes: 3 additions & 3 deletions clients/wallet/src/horizon/responses.rs
Original file line number Diff line number Diff line change
@@ -181,8 +181,8 @@ pub struct TransactionResponse {
pub fee_account: Vec<u8>,
#[serde(deserialize_with = "de_str_to_u64")]
pub fee_charged: u64,
#[serde(deserialize_with = "de_str_to_bytes")]
pub max_fee: Vec<u8>,
#[serde(deserialize_with = "de_str_to_u64")]
pub max_fee: u64,
operation_count: u32,
#[serde(deserialize_with = "de_str_to_bytes")]
pub envelope_xdr: Vec<u8>,
@@ -219,7 +219,7 @@ impl Debug for TransactionResponse {
.field("source_account_sequence", &debug_str_or_vec_u8!(&self.source_account_sequence))
.field("fee_account", &debug_str_or_vec_u8!(&self.fee_account))
.field("fee_charged", &self.fee_charged)
.field("max_fee", &debug_str_or_vec_u8!(&self.max_fee))
.field("max_fee", &self.max_fee)
.field("operation_count", &self.operation_count)
.field("envelope_xdr", &debug_str_or_vec_u8!(&self.envelope_xdr))
.field("result_xdr", &debug_str_or_vec_u8!(&self.result_xdr))
43 changes: 27 additions & 16 deletions clients/wallet/src/resubmissions.rs
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ use tokio::time::sleep;
use crate::horizon::responses::TransactionsResponseIter;
#[cfg(test)]
use mocktopus::macros::mockable;
use primitives::stellar::{types::SequenceNumber, FeeBumpTransaction, PublicKey, StroopAmount};
use primitives::stellar::{types::SequenceNumber, PublicKey};
use reqwest::Client;

pub const RESUBMISSION_INTERVAL_IN_SECS: u64 = 1800;
@@ -194,28 +194,31 @@ impl StellarWallet {
self.submit_transaction(envelope).await
}

// We encountered an error due to insufficient fee and try submitting the transaction again
// wrapped in a FeeBumpTransaction with a higher fee. The new fee has to be at least 10x the
// original fee, see [here](https://developers.stellar.org/docs/learn/encyclopedia/fees-surge-pricing-fee-strategies#fee-bumps-on-past-transactions).
// We encountered an insufficient fee error and try submitting the transaction again with a
// higher fee. We'll bump the fee by 10x the original fee. We don't use a FeeBumpTransaction
// because this operation is not supported by the stellar-relay pallet yet.
async fn handle_tx_insufficient_fee_error(
&self,
envelope_xdr_as_str_opt: &Option<String>,
) -> Result<TransactionResponse, Error> {
let envelope = decode_to_envelope(envelope_xdr_as_str_opt)?;
let tx_envelope = decode_to_envelope(envelope_xdr_as_str_opt)?;
let mut tx = tx_envelope.get_transaction().ok_or(DecodeError)?;

let source = self.public_key();
// The new fee has to be at least 10x the original fee
let prev_fee = envelope.get_transaction().map(|tx| tx.fee).ok_or(DecodeError)?;
let new_fee: i64 = (prev_fee * 10) as i64;
let new_fee = StroopAmount(new_fee);
// Check if we already submitted this transaction
if !self.is_transaction_already_submitted(&tx).await {
// Remove original transaction.
// The same envelope will be saved again using a different sequence number
self.remove_tx_envelope_from_cache(&tx_envelope);

let mut fee_bump_envelope = FeeBumpTransaction::new(source, new_fee, envelope)
.map_err(|_| DecodeError)?
.into_transaction_envelope();
// Bump the fee by 10x
tx.fee = tx.fee * 10;

self.sign_envelope(&mut fee_bump_envelope)?;
return self.bump_sequence_number_and_submit(tx).await
}

tracing::error!("handle_tx_bad_seq_error_with_envelope(): Similar transaction already submitted. Skipping {:?}", tx);

self.submit_transaction(fee_bump_envelope).await
Err(ResubmissionError("Transaction already submitted".to_string()))
}
}

@@ -715,12 +718,17 @@ mod test {
.clone();
let wallet = wallet.write().await;

// This is the fee we will bump by 10x
let base_fee = 100;
// This is the new maximum fee we expect to be charged
let bumped_fee = base_fee * 10;

let sequence = wallet.get_sequence().await.expect("return a sequence");
let envelope = wallet
.create_payment_envelope(
default_destination(),
StellarAsset::native(),
13,
10,
rand::random(),
100,
sequence + 1,
@@ -735,6 +743,9 @@ mod test {
let result = wallet.handle_tx_insufficient_fee_error(&envelope_xdr).await;

assert!(result.is_ok());
let response = result.unwrap();
assert!(response.successful);
assert_eq!(response.max_fee, bumped_fee);

wallet.remove_cache_dir();
}