Skip to content

Commit

Permalink
Refactor Transaction Building (#426)
Browse files Browse the repository at this point in the history
  • Loading branch information
briancorbin authored Aug 17, 2022
1 parent fec71df commit 074d2b0
Show file tree
Hide file tree
Showing 12 changed files with 232 additions and 506 deletions.
53 changes: 33 additions & 20 deletions full-service/src/db/transaction_log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@ use mc_crypto_digestible::{Digestible, MerlinTranscript};
use mc_transaction_core::{tx::Tx, Amount, TokenId};
use std::fmt;

use crate::db::{
account::{AccountID, AccountModel},
models::{
Account, NewTransactionInputTxo, NewTransactionLog, TransactionInputTxo, TransactionLog,
TransactionOutputTxo, Txo,
use crate::{
db::{
account::{AccountID, AccountModel},
models::{
Account, NewTransactionInputTxo, NewTransactionLog, TransactionInputTxo,
TransactionLog, TransactionOutputTxo, Txo,
},
txo::{TxoID, TxoModel},
Conn, WalletDbError,
},
txo::{TxoID, TxoModel},
Conn, WalletDbError,
service::models::tx_proposal::TxProposal,
};

use crate::service::models::tx_proposal::TxProposal;

#[derive(Debug)]
pub struct TransactionID(pub String);

Expand Down Expand Up @@ -582,7 +583,10 @@ mod tests {

use crate::{
db::{account::AccountID, transaction_log::TransactionID, txo::TxoStatus},
service::{sync::SyncThread, transaction_builder::WalletTransactionBuilder},
service::{
sync::SyncThread, transaction::TransactionMemo,
transaction_builder::WalletTransactionBuilder,
},
test_utils::{
add_block_from_transaction_log, add_block_with_tx_outs, builder_for_random_recipient,
get_resolver_factory, get_test_ledger, manually_sync_account,
Expand Down Expand Up @@ -625,13 +629,15 @@ mod tests {
// Build a transaction
let conn = wallet_db.get_conn().unwrap();
let (recipient, mut builder) =
builder_for_random_recipient(&account_key, &ledger_db, &mut rng, &logger);
builder_for_random_recipient(&account_key, &ledger_db, &mut rng);
builder
.add_recipient(recipient.clone(), 50 * MOB, Mob::ID)
.unwrap();
builder.set_tombstone(0).unwrap();
builder.select_txos(&conn, None).unwrap();
let tx_proposal = builder.build(None, &conn).unwrap();
let unsigned_tx = builder.build(TransactionMemo::RTH).unwrap();
let fog_resolver = builder.get_fs_fog_resolver(&conn).unwrap();
let tx_proposal = unsigned_tx.sign(&account_key, fog_resolver).unwrap();

// Log submitted transaction from tx_proposal
let tx_log = TransactionLog::log_submitted(
Expand Down Expand Up @@ -781,7 +787,7 @@ mod tests {
// Build a transaction
let conn = wallet_db.get_conn().unwrap();
let (recipient, mut builder) =
builder_for_random_recipient(&account_key, &ledger_db, &mut rng, &logger);
builder_for_random_recipient(&account_key, &ledger_db, &mut rng);
// Add outlays all to the same recipient, so that we exceed u64::MAX in this tx
let value = 100 * MOB - Mob::MINIMUM_FEE;
builder
Expand All @@ -790,7 +796,9 @@ mod tests {

builder.set_tombstone(0).unwrap();
builder.select_txos(&conn, None).unwrap();
let tx_proposal = builder.build(None, &conn).unwrap();
let unsigned_tx = builder.build(TransactionMemo::RTH).unwrap();
let fog_resolver = builder.get_fs_fog_resolver(&conn).unwrap();
let tx_proposal = unsigned_tx.sign(&account_key, fog_resolver).unwrap();

let tx_log = TransactionLog::log_submitted(
&tx_proposal,
Expand Down Expand Up @@ -862,13 +870,15 @@ mod tests {
// Build a transaction
let conn = wallet_db.get_conn().unwrap();
let (recipient, mut builder) =
builder_for_random_recipient(&account_key, &ledger_db, &mut rng, &logger);
builder_for_random_recipient(&account_key, &ledger_db, &mut rng);
builder
.add_recipient(recipient.clone(), 50 * MOB, Mob::ID)
.unwrap();
builder.set_tombstone(0).unwrap();
builder.select_txos(&conn, None).unwrap();
let tx_proposal = builder.build(None, &conn).unwrap();
let unsigned_tx = builder.build(TransactionMemo::RTH).unwrap();
let fog_resolver = builder.get_fs_fog_resolver(&conn).unwrap();
let tx_proposal = unsigned_tx.sign(&account_key, fog_resolver).unwrap();

// Log submitted transaction from tx_proposal
TransactionLog::log_submitted(
Expand Down Expand Up @@ -959,13 +969,15 @@ mod tests {
// Build a transaction for > i64::Max
let conn = wallet_db.get_conn().unwrap();
let (recipient, mut builder) =
builder_for_random_recipient(&account_key, &ledger_db, &mut rng, &logger);
builder_for_random_recipient(&account_key, &ledger_db, &mut rng);
builder
.add_recipient(recipient.clone(), 10_000_000 * MOB, Mob::ID)
.unwrap();
builder.set_tombstone(0).unwrap();
builder.select_txos(&conn, None).unwrap();
let tx_proposal = builder.build(None, &conn).unwrap();
let unsigned_tx = builder.build(TransactionMemo::RTH).unwrap();
let fog_resolver = builder.get_fs_fog_resolver(&conn).unwrap();
let tx_proposal = unsigned_tx.sign(&account_key, fog_resolver).unwrap();

assert_eq!(
tx_proposal.payload_txos[0].amount.value,
Expand Down Expand Up @@ -1024,15 +1036,16 @@ mod tests {
AccountID::from(&account_key).to_string(),
ledger_db.clone(),
get_resolver_factory(&mut rng).unwrap(),
logger.clone(),
);
// Add self at main subaddress as the recipient
builder
.add_recipient(account_key.subaddress(0), 12 * MOB, Mob::ID)
.unwrap();
builder.set_tombstone(0).unwrap();
builder.select_txos(&conn, None).unwrap();
let tx_proposal = builder.build(None, &conn).unwrap();
let unsigned_tx = builder.build(TransactionMemo::RTH).unwrap();
let fog_resolver = builder.get_fs_fog_resolver(&conn).unwrap();
let tx_proposal = unsigned_tx.sign(&account_key, fog_resolver).unwrap();

// Log submitted transaction from tx_proposal
let tx_log = TransactionLog::log_submitted(
Expand Down
9 changes: 4 additions & 5 deletions full-service/src/db/txo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1408,6 +1408,7 @@ mod tests {
},
service::{
sync::{sync_account, SyncThread},
transaction::TransactionMemo,
transaction_builder::WalletTransactionBuilder,
},
test_utils::{
Expand Down Expand Up @@ -1525,7 +1526,6 @@ mod tests {
33 * MOB,
wallet_db.clone(),
ledger_db.clone(),
logger.clone(),
);

let associated_txos = transaction_log
Expand Down Expand Up @@ -1742,7 +1742,6 @@ mod tests {
72 * MOB,
wallet_db.clone(),
ledger_db.clone(),
logger.clone(),
);

let associated_txos = transaction_log
Expand Down Expand Up @@ -2082,7 +2081,6 @@ mod tests {
1 * MOB,
wallet_db.clone(),
ledger_db,
logger,
);

let associated_txos = transaction_log
Expand Down Expand Up @@ -2151,7 +2149,6 @@ mod tests {
AccountID::from(&sender_account_key).to_string(),
ledger_db.clone(),
get_resolver_factory(&mut rng).unwrap(),
logger.clone(),
);
builder
.add_recipient(
Expand All @@ -2162,7 +2159,9 @@ mod tests {
.unwrap();
builder.select_txos(&conn, None).unwrap();
builder.set_tombstone(0).unwrap();
let proposal = builder.build(None, &conn).unwrap();
let unsigned_tx = builder.build(TransactionMemo::RTH).unwrap();
let fog_resolver = builder.get_fs_fog_resolver(&conn).unwrap();
let proposal = unsigned_tx.sign(&sender_account_key, fog_resolver).unwrap();

// Sleep to make sure that the foreign keys exist
std::thread::sleep(Duration::from_secs(3));
Expand Down
10 changes: 6 additions & 4 deletions full-service/src/json_rpc/v1/api/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,9 @@ where
)
})
.collect();
let (transaction_log, associated_txos, _value_map, tx_proposal) = service
.build_and_submit(

let (transaction_log, associated_txos, _, tx_proposal) = service
.build_sign_and_submit_transaction(
&account_id,
&addresses_and_amounts,
input_txo_ids.as_ref(),
Expand All @@ -167,8 +168,10 @@ where
tombstone_block,
max_spendable_value,
comment,
TransactionMemo::RTH,
)
.map_err(format_error)?;

JsonCommandResponse::build_and_submit_transaction {
transaction_log: json_rpc::v1::models::transaction_log::TransactionLog::new(
&transaction_log,
Expand Down Expand Up @@ -267,15 +270,14 @@ where
.collect();

let tx_proposal = service
.build_transaction(
.build_and_sign_transaction(
&account_id,
&addresses_and_amounts,
input_txo_ids.as_ref(),
fee,
Some(Mob::ID.to_string()),
tombstone_block,
max_spendable_value,
None,
TransactionMemo::RTH,
)
.map_err(format_error)?;
Expand Down
1 change: 0 additions & 1 deletion full-service/src/json_rpc/v2/api/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ pub fn setup_with_api_key(
pub fn dispatch(client: &Client, request_body: JsonValue, logger: &Logger) -> JsonValue {
log::info!(logger, "Attempting dispatch of\n{:?}\n", request_body,);
let request_body = request_body.to_string();
log::info!(logger, "Attempting dispatch of\n{}\n", request_body,);

let mut res = client
.post("/wallet/v2")
Expand Down
15 changes: 8 additions & 7 deletions full-service/src/json_rpc/v2/api/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ where
}

let (transaction_log, associated_txos, value_map, tx_proposal) = service
.build_and_submit(
.build_sign_and_submit_transaction(
&account_id,
&addresses_and_amounts,
input_txo_ids.as_ref(),
Expand All @@ -154,8 +154,10 @@ where
tombstone_block,
max_spendable_value,
comment,
TransactionMemo::RTH,
)
.map_err(format_error)?;

JsonCommandResponse::build_and_submit_transaction {
transaction_log: TransactionLog::new(
&transaction_log,
Expand Down Expand Up @@ -188,7 +190,7 @@ where
}

let tx_proposal = service
.build_transaction(
.build_and_sign_transaction(
&account_id,
&[(
b58_encode_public_address(&burn_address()).map_err(format_error)?,
Expand All @@ -199,7 +201,6 @@ where
fee_token_id,
tombstone_block,
max_spendable_value,
None,
TransactionMemo::BurnRedemption(memo_data),
)
.map_err(format_error)?;
Expand Down Expand Up @@ -228,18 +229,18 @@ where
}

let tx_proposal = service
.build_transaction(
.build_and_sign_transaction(
&account_id,
&addresses_and_amounts,
input_txo_ids.as_ref(),
fee_value,
fee_token_id,
tombstone_block,
max_spendable_value,
None,
TransactionMemo::RTH,
)
.map_err(format_error)?;

JsonCommandResponse::build_transaction {
tx_proposal: TxProposalJSON::try_from(&tx_proposal).map_err(format_error)?,
transaction_log_id: TransactionID::from(&tx_proposal.tx).to_string(),
Expand Down Expand Up @@ -268,7 +269,7 @@ where
}

let (unsigned_tx, fog_resolver) = service
.build_unsigned_transaction(
.build_transaction(
&account_id,
&[(
b58_encode_public_address(&burn_address()).map_err(format_error)?,
Expand Down Expand Up @@ -305,7 +306,7 @@ where
addresses_and_amounts.push((address, amount));
}
let (unsigned_tx, fog_resolver) = service
.build_unsigned_transaction(
.build_transaction(
&account_id,
&addresses_and_amounts,
input_txo_ids.as_ref(),
Expand Down
16 changes: 14 additions & 2 deletions full-service/src/service/gift_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{
models::{Account, GiftCode},
transaction, WalletDbError,
},
error::WalletTransactionBuilderError,
service::{
account::AccountServiceError,
address::{AddressService, AddressServiceError},
Expand Down Expand Up @@ -154,6 +155,9 @@ pub enum GiftCodeServiceError {

/// Amount Error: {0}
Amount(mc_transaction_core::AmountError),

/// Wallet Transaction Builder Error: {0}
WalletTransactionBuilder(WalletTransactionBuilderError),
}

impl From<WalletDbError> for GiftCodeServiceError {
Expand Down Expand Up @@ -252,6 +256,12 @@ impl From<mc_transaction_core::AmountError> for GiftCodeServiceError {
}
}

impl From<WalletTransactionBuilderError> for GiftCodeServiceError {
fn from(src: WalletTransactionBuilderError) -> Self {
Self::WalletTransactionBuilder(src)
}
}

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct EncodedGiftCode(pub String);

Expand Down Expand Up @@ -421,7 +431,7 @@ where

let fee_value = fee.map(|f| f.to_string());

let tx_proposal = self.build_transaction(
let (unsigned_tx, fog_resolver) = self.build_transaction(
&from_account.id,
&[(
gift_code_account_main_subaddress_b58,
Expand All @@ -435,10 +445,12 @@ where
None,
tombstone_block.map(|t| t.to_string()),
max_spendable_value.map(|f| f.to_string()),
None,
TransactionMemo::RTH,
)?;

let account_key: AccountKey = mc_util_serial::decode(&from_account.account_key)?;
let tx_proposal = unsigned_tx.sign(&account_key, fog_resolver)?;

if tx_proposal.payload_txos.len() != 1 {
return Err(GiftCodeServiceError::UnexpectedTxProposalFormat);
}
Expand Down
Loading

0 comments on commit 074d2b0

Please sign in to comment.