aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
authorluigi1111 <luigi1111w@gmail.com>2023-07-06 21:37:58 -0500
committerluigi1111 <luigi1111w@gmail.com>2023-07-06 21:37:58 -0500
commitd5c7d1743f217c87b13f17323483c8115890045f (patch)
tree0b50061c803fa09f49c405a957823e868f6a0637 /src/wallet
parentMerge pull request #8903 (diff)
parentwallet: respect frozen key images in multisig wallets (diff)
downloadmonero-d5c7d1743f217c87b13f17323483c8115890045f.tar.xz
Merge pull request #8904
369a5a8 wallet: respect frozen key images in multisig wallets (jeffro256)
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/wallet2.cpp41
-rw-r--r--src/wallet/wallet2.h1
2 files changed, 40 insertions, 2 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 0be3317b9..78c0f6328 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -1971,6 +1971,36 @@ bool wallet2::frozen(size_t idx) const
return td.m_frozen;
}
//----------------------------------------------------------------------------------------------------
+bool wallet2::frozen(const multisig_tx_set& txs) const
+{
+ // Each call to frozen(const key_image&) is O(N), so if we didn't use batching like we did here,
+ // this op would be O(M * N) instead of O(M + N). N = # wallet transfers, M = # key images in set.
+ // Step 1. Collect all key images from all pending txs into set
+ std::unordered_set<crypto::key_image> kis_to_sign;
+ for (const auto& ptx : txs.m_ptx)
+ {
+ const tools::wallet2::tx_construction_data& cd = ptx.construction_data;
+ CHECK_AND_ASSERT_THROW_MES(cd.sources.size() == ptx.tx.vin.size(), "mismatched multisg tx set source sizes");
+ for (size_t src_idx = 0; src_idx < cd.sources.size(); ++src_idx)
+ {
+ // Check that the key images are consistent between tx vin and construction data
+ const crypto::key_image multisig_ki = rct::rct2ki(cd.sources[src_idx].multisig_kLRki.ki);
+ CHECK_AND_ASSERT_THROW_MES(ptx.tx.vin[src_idx].type() == typeid(cryptonote::txin_to_key), "multisig tx cannot be miner");
+ const crypto::key_image vin_ki = boost::get<cryptonote::txin_to_key>(ptx.tx.vin[src_idx]).k_image;
+ CHECK_AND_ASSERT_THROW_MES(multisig_ki == vin_ki, "Mismatched key image b/t vin and construction data");
+
+ // Add key image to set
+ kis_to_sign.insert(multisig_ki);
+ }
+ }
+ // Step 2. Scan all transfers for frozen key images
+ for (const auto& td : m_transfers)
+ if (td.m_frozen && kis_to_sign.count(td.m_key_image))
+ return true;
+
+ return false;
+}
+//----------------------------------------------------------------------------------------------------
void wallet2::freeze(const crypto::key_image &ki)
{
freeze(get_transfer_details(ki));
@@ -1991,8 +2021,13 @@ size_t wallet2::get_transfer_details(const crypto::key_image &ki) const
for (size_t idx = 0; idx < m_transfers.size(); ++idx)
{
const transfer_details &td = m_transfers[idx];
- if (td.m_key_image_known && td.m_key_image == ki)
- return idx;
+ if (td.m_key_image == ki)
+ {
+ if (td.m_key_image_known)
+ return idx;
+ else if (td.m_key_image_partial)
+ CHECK_AND_ASSERT_THROW_MES(false, "Transfer detail lookups are not allowed for multisig partial key images");
+ }
}
CHECK_AND_ASSERT_THROW_MES(false, "Key image not found");
}
@@ -7646,6 +7681,8 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector<crypto
error::wallet_internal_error, "Transaction was signed by too many signers");
THROW_WALLET_EXCEPTION_IF(exported_txs.m_signers.size() == m_multisig_threshold,
error::wallet_internal_error, "Transaction is already fully signed");
+ THROW_WALLET_EXCEPTION_IF(frozen(exported_txs),
+ error::wallet_internal_error, "Will not sign multisig tx containing frozen outputs")
txids.clear();
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index e57163a73..9c310f692 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -1614,6 +1614,7 @@ private:
void thaw(const crypto::key_image &ki);
bool frozen(const crypto::key_image &ki) const;
bool frozen(const transfer_details &td) const;
+ bool frozen(const multisig_tx_set& txs) const; // does partially signed txset contain frozen enotes?
bool save_to_file(const std::string& path_to_file, const std::string& binary, bool is_printable = false) const;
static bool load_from_file(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000);