Skip to content

Commit

Permalink
change tx additional info to handle orders
Browse files Browse the repository at this point in the history
  • Loading branch information
OBorce committed Jan 8, 2025
1 parent dc77e89 commit bb37cc0
Show file tree
Hide file tree
Showing 19 changed files with 549 additions and 465 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 17 additions & 1 deletion common/src/chain/transaction/output/output_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,14 @@ impl From<TokenIssuanceV0> for OutputValue {
}

#[derive(
Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, rpc_description::HasValueHint,
Debug,
Clone,
Copy,
PartialEq,
Eq,
serde::Serialize,
serde::Deserialize,
rpc_description::HasValueHint,
)]
#[serde(tag = "type", content = "content")]
pub enum RpcOutputValue {
Expand Down Expand Up @@ -107,3 +114,12 @@ impl RpcOutputValue {
}
}
}

impl From<RpcOutputValue> for OutputValue {
fn from(value: RpcOutputValue) -> Self {
match value {
RpcOutputValue::Coin { amount } => OutputValue::Coin(amount),
RpcOutputValue::Token { id, amount } => OutputValue::TokenV1(id, amount),
}
}
}
5 changes: 1 addition & 4 deletions wallet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ utils-networking = { path = "../utils/networking" }
utxo = { path = "../utxo" }
wallet-storage = { path = "./storage" }
wallet-types = { path = "./types" }
# trezor-client = { git = "https://github.com/mintlayer/mintlayer-trezor-firmware", branch = "feature/mintlayer-pk", features = ["bitcoin", "mintlayer"], optional = true }
trezor-client = { path = "../../trezor-firmware/rust/trezor-client", features = ["bitcoin", "mintlayer"], optional = true }
trezor-client = { git = "https://github.com/mintlayer/mintlayer-trezor-firmware", branch = "feature/mintlayer-pk", features = ["bitcoin", "mintlayer"], optional = true }

bip39 = { workspace = true, default-features = false, features = ["std", "zeroize"] }
hex.workspace = true
Expand All @@ -46,5 +45,3 @@ tempfile.workspace = true
[features]
trezor = ["dep:trezor-client", "wallet-types/trezor"]
trezor-emulator = []

default = ["trezor"]
9 changes: 5 additions & 4 deletions wallet/src/account/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ use utils::ensure;
pub use utxo_selector::UtxoSelectorError;
use wallet_types::account_id::AccountPrefixedId;
use wallet_types::account_info::{StandaloneAddressDetails, StandaloneAddresses};
use wallet_types::partially_signed_transaction::{PartiallySignedTransaction, UtxoAdditionalInfo};
use wallet_types::partially_signed_transaction::{
InfoId, PartiallySignedTransaction, TxAdditionalInfo,
};
use wallet_types::with_locked::WithLocked;

use crate::account::utxo_selector::{select_coins, OutputGroup};
Expand All @@ -47,8 +49,7 @@ use crate::key_chain::{AccountKeyChains, KeyChainError, VRFAccountKeyChains};
use crate::send_request::{
make_address_output, make_address_output_from_delegation, make_address_output_token,
make_decommission_stake_pool_output, make_mint_token_outputs, make_stake_output,
make_unmint_token_outputs, IssueNftArguments, PoolOrTokenId, SelectedInputs,
StakePoolDataArguments,
make_unmint_token_outputs, IssueNftArguments, SelectedInputs, StakePoolDataArguments,
};
use crate::wallet::WalletPoolsFilter;
use crate::wallet_events::{WalletEvents, WalletEventsNoOp};
Expand Down Expand Up @@ -633,7 +634,7 @@ impl<K: AccountKeyChains> Account<K> {
change_addresses: BTreeMap<Currency, Address<Destination>>,
median_time: BlockTimestamp,
fee_rate: CurrentFeeRate,
additional_utxo_infos: &BTreeMap<PoolOrTokenId, UtxoAdditionalInfo>,
additional_utxo_infos: BTreeMap<InfoId, TxAdditionalInfo>,
) -> WalletResult<(PartiallySignedTransaction, BTreeMap<Currency, Amount>)> {
let mut request = self.select_inputs_for_send_request(
request,
Expand Down
93 changes: 5 additions & 88 deletions wallet/src/send_request/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use common::address::Address;
use common::chain::output_value::OutputValue;
use common::chain::stakelock::StakePoolData;
use common::chain::timelock::OutputTimeLock::ForBlockCount;
use common::chain::tokens::{Metadata, NftIssuance, TokenId, TokenIssuance};
use common::chain::tokens::{Metadata, TokenId, TokenIssuance};
use common::chain::{
ChainConfig, Destination, PoolId, Transaction, TxInput, TxOutput, UtxoOutPoint,
};
Expand All @@ -30,19 +30,13 @@ use crypto::vrf::VRFPublicKey;
use utils::ensure;
use wallet_types::currency::Currency;
use wallet_types::partially_signed_transaction::{
PartiallySignedTransaction, TokenAdditionalInfo, UtxoAdditionalInfo, UtxoWithAdditionalInfo,
InfoId, PartiallySignedTransaction, TxAdditionalInfo,
};

use crate::account::PoolData;
use crate::destination_getters::{get_tx_output_destination, HtlcSpendingCondition};
use crate::{WalletError, WalletResult};

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum PoolOrTokenId {
PoolId(PoolId),
TokenId(TokenId),
}

/// The `SendRequest` struct provides the necessary information to the wallet
/// on the precise method of sending funds to a designated destination.
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -298,26 +292,11 @@ impl SendRequest {

pub fn into_partially_signed_tx(
self,
additional_info: &BTreeMap<PoolOrTokenId, UtxoAdditionalInfo>,
additional_info: BTreeMap<InfoId, TxAdditionalInfo>,
) -> WalletResult<PartiallySignedTransaction> {
let num_inputs = self.inputs.len();
let destinations = self.destinations.into_iter().map(Some).collect();
let utxos = self
.utxos
.into_iter()
.map(|utxo| {
utxo.map(|utxo| {
let additional_info = find_additional_info(&utxo, additional_info)?;
Ok(UtxoWithAdditionalInfo::new(utxo, additional_info))
})
.transpose()
})
.collect::<WalletResult<Vec<_>>>()?;
let output_additional_infos = self
.outputs
.iter()
.map(|utxo| find_additional_info(utxo, additional_info))
.collect::<WalletResult<Vec<_>>>()?;
let utxos = self.utxos;
let tx = Transaction::new(self.flags, self.inputs, self.outputs)?;

let ptx = PartiallySignedTransaction::new(
Expand All @@ -326,74 +305,12 @@ impl SendRequest {
utxos,
destinations,
None,
output_additional_infos,
additional_info,
)?;
Ok(ptx)
}
}

/// Find additional data for TxOutput, mainly for UI purposes
fn find_additional_info(
utxo: &TxOutput,
additional_info: &BTreeMap<PoolOrTokenId, UtxoAdditionalInfo>,
) -> Result<Option<UtxoAdditionalInfo>, WalletError> {
let additional_info = match utxo {
TxOutput::Burn(value)
| TxOutput::Htlc(value, _)
| TxOutput::Transfer(value, _)
| TxOutput::LockThenTransfer(value, _, _) => {
find_token_additional_info(value, additional_info)?.map(UtxoAdditionalInfo::TokenInfo)
}
TxOutput::CreateOrder(data) => {
let ask = find_token_additional_info(data.ask(), additional_info)?;
let give = find_token_additional_info(data.give(), additional_info)?;

Some(UtxoAdditionalInfo::CreateOrder { ask, give })
}
TxOutput::IssueNft(_, data, _) => {
Some(UtxoAdditionalInfo::TokenInfo(TokenAdditionalInfo {
num_decimals: 0,
ticker: match data.as_ref() {
NftIssuance::V0(data) => data.metadata.ticker().clone(),
},
}))
}
TxOutput::CreateStakePool(_, data) => Some(UtxoAdditionalInfo::PoolInfo {
staker_balance: data.pledge(),
}),
TxOutput::ProduceBlockFromStake(_, pool_id) => additional_info
.get(&PoolOrTokenId::PoolId(*pool_id))
.ok_or(WalletError::MissingPoolAdditionalData(*pool_id))
.map(Some)?
.cloned(),
TxOutput::DataDeposit(_)
| TxOutput::IssueFungibleToken(_)
| TxOutput::DelegateStaking(_, _)
| TxOutput::CreateDelegationId(_, _) => None,
};
Ok(additional_info)
}

fn find_token_additional_info(
value: &OutputValue,
additional_info: &BTreeMap<PoolOrTokenId, UtxoAdditionalInfo>,
) -> WalletResult<Option<TokenAdditionalInfo>> {
match value {
OutputValue::Coin(_) | OutputValue::TokenV0(_) => Ok(None),
OutputValue::TokenV1(token_id, _) => additional_info
.get(&PoolOrTokenId::TokenId(*token_id))
.ok_or(WalletError::MissingTokenAdditionalData(*token_id))
.cloned()
.map(|data| match data {
UtxoAdditionalInfo::TokenInfo(data) => Ok(Some(data.clone())),
UtxoAdditionalInfo::PoolInfo { staker_balance: _ }
| UtxoAdditionalInfo::CreateOrder { ask: _, give: _ } => {
Err(WalletError::MismatchedTokenAdditionalData(*token_id))
}
})?,
}
}

pub enum SelectedInputs {
Utxos(Vec<UtxoOutPoint>),
Inputs(Vec<(UtxoOutPoint, TxOutput)>),
Expand Down
6 changes: 4 additions & 2 deletions wallet/src/signer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ pub enum SignerError {
MissingDestinationInTransaction,
#[error("Partially signed tx is missing UTXO type input's UTXO")]
MissingUtxo,
#[error("Partially signed tx is missing extra info for UTXO")]
MissingUtxoExtraInfo,
#[error("Partially signed tx is missing extra info")]
MissingTxExtraInfo,
#[error("Tokens V0 are not supported")]
UnsupportedTokensV0,
#[error("Invalid TxOutput type as UTXO, cannot be spent")]
Expand All @@ -93,6 +93,8 @@ pub enum SignerError {
AddressError(#[from] AddressError),
#[error("Signature error: {0}")]
SignatureError(#[from] SignatureError),
#[error("Order was filled more than the available balance")]
OrderFillUnderflow,
}

type SignerResult<T> = Result<T, SignerError>;
Expand Down
3 changes: 1 addition & 2 deletions wallet/src/signer/software_signer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,7 @@ impl Signer for SoftwareSigner {
Vec<SignatureStatus>,
Vec<SignatureStatus>,
)> {
let inputs_utxo_refs: Vec<_> =
ptx.input_utxos().iter().map(|u| u.as_ref().map(|x| &x.utxo)).collect();
let inputs_utxo_refs: Vec<_> = ptx.input_utxos().iter().map(|u| u.as_ref()).collect();

let (witnesses, prev_statuses, new_statuses) = ptx
.witnesses()
Expand Down
4 changes: 2 additions & 2 deletions wallet/src/signer/software_signer/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ fn sign_transaction(#[case] seed: Seed) {
.with_outputs(outputs);
let destinations = req.destinations().to_vec();
let additional_info = BTreeMap::new();
let ptx = req.into_partially_signed_tx(&additional_info).unwrap();
let ptx = req.into_partially_signed_tx(additional_info).unwrap();

let mut signer = SoftwareSigner::new(chain_config.clone(), DEFAULT_ACCOUNT_INDEX);
let (ptx, _, _) = signer.sign_tx(ptx, account.key_chain(), &db_tx).unwrap();
Expand Down Expand Up @@ -688,7 +688,7 @@ fn fixed_signatures() {
.with_outputs(outputs);
let destinations = req.destinations().to_vec();
let additional_info = BTreeMap::new();
let ptx = req.into_partially_signed_tx(&additional_info).unwrap();
let ptx = req.into_partially_signed_tx(additional_info).unwrap();

let utxos_ref = utxos
.iter()
Expand Down
Loading

0 comments on commit bb37cc0

Please sign in to comment.