Skip to content

Commit

Permalink
API for generating burn txs in mobilecoind (#1872)
Browse files Browse the repository at this point in the history
* add and impl generate_burn_redemption_tx

* add tests

* support destination memos

* fmt

* Update mobilecoind/src/service.rs

Co-authored-by: Remoun Metyas <[email protected]>

* Update mobilecoind/src/service.rs

Co-authored-by: Remoun Metyas <[email protected]>

* Update mobilecoind/api/proto/mobilecoind_api.proto

Co-authored-by: Nick Santana <[email protected]>

* change test to exercise off by one scenario

Co-authored-by: Remoun Metyas <[email protected]>
Co-authored-by: Nick Santana <[email protected]>
  • Loading branch information
3 people authored Apr 29, 2022
1 parent e4038aa commit d991eee
Show file tree
Hide file tree
Showing 3 changed files with 349 additions and 14 deletions.
44 changes: 44 additions & 0 deletions mobilecoind/api/proto/mobilecoind_api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ service MobilecoindAPI {
rpc GenerateOptimizationTx (GenerateOptimizationTxRequest) returns (GenerateOptimizationTxResponse) {}
rpc GenerateTransferCodeTx (GenerateTransferCodeTxRequest) returns (GenerateTransferCodeTxResponse) {}
rpc GenerateTxFromTxOutList (GenerateTxFromTxOutListRequest) returns (GenerateTxFromTxOutListResponse) {}
rpc GenerateBurnRedemptionTx (GenerateBurnRedemptionTxRequest) returns (GenerateBurnRedemptionTxResponse) {}
rpc SubmitTx (SubmitTxRequest) returns (SubmitTxResponse) {}

// Databases
Expand Down Expand Up @@ -563,6 +564,49 @@ message GenerateTxFromTxOutListResponse {
TxProposal tx_proposal = 1;
}

// Generate a burn redemption transaction proposal object.
// Notes:
// - Sum of inputs needs to be greater than or equal to the burn amount and fee.
// - The set of inputs to use would be chosen automatically by mobilecoind.
// - The fee field could be set to zero, in which case mobilecoind would try and choose a fee.
message GenerateBurnRedemptionTxRequest {
// Monitor id sending the funds.
bytes sender_monitor_id = 1;

// Subaddress to return change to.
uint64 change_subaddress = 2;

// List of UnspentTxOuts to be spent by the transaction.
// All UnspentTxOuts must belong to the same sender_monitor_id.
// mobilecoind would choose a subset of these inputs to construct the transaction.
// Total input amount must be >= burn amount + fee.
repeated UnspentTxOut input_list = 3;

// Amount to be burnt. This excludes change and fee.
uint64 burn_amount = 4;

// Fee (setting to 0 causes mobilecoind to choose a value).
// The value used can be checked (but not changed) in tx_proposal.tx.prefix.fee
uint64 fee = 5;

// Tombstone block (setting to 0 causes mobilecoind to choose a value).
// The value used can be checked (but not changed) in tx_proposal.tx.prefix.tombstone_block
uint64 tombstone = 6;

// Token id to use for the transaction.
uint64 token_id = 7;

// Optional 64 bytes of data to include in the burn redemption memo that is attached to the burn TxOut.
// If not provided zeros will be used.
bytes redemption_memo = 8;

// Enable RTH destination memo.
bool enable_destination_memo = 9;
}
message GenerateBurnRedemptionTxResponse {
TxProposal tx_proposal = 1;
}

// Submits a transaction to the network.
message SubmitTxRequest {
TxProposal tx_proposal = 1;
Expand Down
28 changes: 18 additions & 10 deletions mobilecoind/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use mc_transaction_core::{
Amount, BlockIndex, BlockVersion, TokenId,
};
use mc_transaction_std::{
ChangeDestination, EmptyMemoBuilder, InputCredentials, TransactionBuilder,
ChangeDestination, EmptyMemoBuilder, InputCredentials, MemoBuilder, TransactionBuilder,
};
use mc_util_uri::FogUri;
use rand::Rng;
Expand Down Expand Up @@ -221,6 +221,8 @@ impl<T: BlockchainConnection + UserTxConnection + 'static, FPR: FogPubkeyResolve
/// * `outlays` - Output amounts and recipients.
/// * `opt_fee` - Transaction fee in picoMOB. If zero, defaults to MIN_FEE.
/// * `opt_tombstone` - Tombstone block. If zero, sets to default.
/// * `opt_memo_builder` - Optional memo builder to use instead of the
/// default one (EmptyMemoBuilder).
pub fn build_transaction(
&self,
sender_monitor_id: &MonitorId,
Expand All @@ -230,6 +232,7 @@ impl<T: BlockchainConnection + UserTxConnection + 'static, FPR: FogPubkeyResolve
outlays: &[Outlay],
opt_fee: u64,
opt_tombstone: u64,
opt_memo_builder: Option<Box<dyn MemoBuilder + 'static + Send + Sync>>,
) -> Result<TxProposal, Error> {
let logger = self.logger.new(o!("sender_monitor_id" => sender_monitor_id.to_string(), "outlays" => format!("{:?}", outlays)));
log::trace!(logger, "Building pending transaction...");
Expand Down Expand Up @@ -325,6 +328,7 @@ impl<T: BlockchainConnection + UserTxConnection + 'static, FPR: FogPubkeyResolve
outlays,
tombstone_block,
&self.fog_resolver_factory,
opt_memo_builder,
&mut rng,
&self.logger,
)?;
Expand Down Expand Up @@ -446,6 +450,7 @@ impl<T: BlockchainConnection + UserTxConnection + 'static, FPR: FogPubkeyResolve
&outlays,
tombstone_block,
&self.fog_resolver_factory,
None,
&mut rng,
&self.logger,
)?;
Expand Down Expand Up @@ -548,6 +553,7 @@ impl<T: BlockchainConnection + UserTxConnection + 'static, FPR: FogPubkeyResolve
&outlays,
tombstone_block,
&self.fog_resolver_factory,
None,
&mut rng,
&self.logger,
)?;
Expand Down Expand Up @@ -823,6 +829,8 @@ impl<T: BlockchainConnection + UserTxConnection + 'static, FPR: FogPubkeyResolve
/// * `destinations` - Outputs of the transaction.
/// * `tombstone_block` - Tombstone block of the transaciton.
/// * `fog_pubkey_resolver` - Provides Fog key report, when Fog is enabled.
/// * `opt_memo_builder` - Optional memo builder to use instead of the
/// default one (EmptyMemoBuilder).
/// * `rng` - randomness
/// * `logger` - Logger
fn build_tx_proposal(
Expand All @@ -836,6 +844,7 @@ impl<T: BlockchainConnection + UserTxConnection + 'static, FPR: FogPubkeyResolve
destinations: &[Outlay],
tombstone_block: BlockIndex,
fog_resolver_factory: &Arc<dyn Fn(&[FogUri]) -> Result<FPR, String> + Send + Sync>,
opt_memo_builder: Option<Box<dyn MemoBuilder + 'static + Send + Sync>>,
rng: &mut (impl RngCore + CryptoRng),
logger: &Logger,
) -> Result<TxProposal, Error> {
Expand Down Expand Up @@ -867,18 +876,17 @@ impl<T: BlockchainConnection + UserTxConnection + 'static, FPR: FogPubkeyResolve
fog_resolver_factory(&fog_uris).map_err(Error::Fog)?
};

// Create tx_builder.
// TODO (GH #1522): Use RTH memo builder, optionally?
let memo_builder: Box<dyn MemoBuilder + Send + Sync> =
opt_memo_builder.unwrap_or_else(|| Box::new(EmptyMemoBuilder::default()));

let fee_amount = Amount::new(fee, token_id);

// Create tx_builder.
let mut tx_builder = TransactionBuilder::new(
block_version,
fee_amount,
fog_resolver,
EmptyMemoBuilder::default(),
)
.map_err(|err| Error::TxBuild(format!("Error creating transaction builder: {}", err)))?;
let mut tx_builder =
TransactionBuilder::new_with_box(block_version, fee_amount, fog_resolver, memo_builder)
.map_err(|err| {
Error::TxBuild(format!("Error creating transaction builder: {}", err))
})?;

// Unzip each vec of tuples into a tuple of vecs.
let mut rings_and_proofs: Vec<(Vec<TxOut>, Vec<TxOutMembershipProof>)> = rings
Expand Down
Loading

0 comments on commit d991eee

Please sign in to comment.