wallet2: fix mishandling rct outputs in coinbase tx
Reported by cutcoin
This commit is contained in:
parent
31bdf7bd11
commit
fa2fbc3917
@ -1426,7 +1426,7 @@ static uint64_t decodeRct(const rct::rctSig & rv, const crypto::key_derivation &
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::scan_output(const cryptonote::transaction &tx, const crypto::public_key &tx_pub_key, size_t i, tx_scan_info_t &tx_scan_info, int &num_vouts_received, std::unordered_map<cryptonote::subaddress_index, uint64_t> &tx_money_got_in_outs, std::vector<size_t> &outs, bool pool)
|
void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, const crypto::public_key &tx_pub_key, size_t i, tx_scan_info_t &tx_scan_info, int &num_vouts_received, std::unordered_map<cryptonote::subaddress_index, uint64_t> &tx_money_got_in_outs, std::vector<size_t> &outs, bool pool)
|
||||||
{
|
{
|
||||||
THROW_WALLET_EXCEPTION_IF(i >= tx.vout.size(), error::wallet_internal_error, "Invalid vout index");
|
THROW_WALLET_EXCEPTION_IF(i >= tx.vout.size(), error::wallet_internal_error, "Invalid vout index");
|
||||||
|
|
||||||
@ -1459,11 +1459,14 @@ void wallet2::scan_output(const cryptonote::transaction &tx, const crypto::publi
|
|||||||
error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key");
|
error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
THROW_WALLET_EXCEPTION_IF(std::find(outs.begin(), outs.end(), i) != outs.end(), error::wallet_internal_error, "Same output cannot be added twice");
|
||||||
outs.push_back(i);
|
outs.push_back(i);
|
||||||
if (tx_scan_info.money_transfered == 0)
|
if (tx_scan_info.money_transfered == 0 && !miner_tx)
|
||||||
{
|
{
|
||||||
tx_scan_info.money_transfered = tools::decodeRct(tx.rct_signatures, tx_scan_info.received->derivation, i, tx_scan_info.mask, m_account.get_device());
|
tx_scan_info.money_transfered = tools::decodeRct(tx.rct_signatures, tx_scan_info.received->derivation, i, tx_scan_info.mask, m_account.get_device());
|
||||||
}
|
}
|
||||||
|
THROW_WALLET_EXCEPTION_IF(tx_money_got_in_outs[tx_scan_info.received->index] >= std::numeric_limits<uint64_t>::max() - tx_scan_info.money_transfered,
|
||||||
|
error::wallet_internal_error, "Overflow in received amounts");
|
||||||
tx_money_got_in_outs[tx_scan_info.received->index] += tx_scan_info.money_transfered;
|
tx_money_got_in_outs[tx_scan_info.received->index] += tx_scan_info.money_transfered;
|
||||||
tx_scan_info.amount = tx_scan_info.money_transfered;
|
tx_scan_info.amount = tx_scan_info.money_transfered;
|
||||||
++num_vouts_received;
|
++num_vouts_received;
|
||||||
@ -1641,7 +1644,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
|||||||
if (tx_scan_info[i].received)
|
if (tx_scan_info[i].received)
|
||||||
{
|
{
|
||||||
hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys.data, derivation, additional_derivations);
|
hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys.data, derivation, additional_derivations);
|
||||||
scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool);
|
scan_output(tx, miner_tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1664,7 +1667,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
|||||||
if (tx_scan_info[i].received)
|
if (tx_scan_info[i].received)
|
||||||
{
|
{
|
||||||
hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys.data, derivation, additional_derivations);
|
hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys.data, derivation, additional_derivations);
|
||||||
scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool);
|
scan_output(tx, miner_tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1680,7 +1683,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
|||||||
boost::unique_lock<hw::device> hwdev_lock (hwdev);
|
boost::unique_lock<hw::device> hwdev_lock (hwdev);
|
||||||
hwdev.set_mode(hw::device::NONE);
|
hwdev.set_mode(hw::device::NONE);
|
||||||
hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys.data, derivation, additional_derivations);
|
hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys.data, derivation, additional_derivations);
|
||||||
scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool);
|
scan_output(tx, miner_tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -11308,6 +11311,7 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
|
|||||||
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
|
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
|
||||||
}
|
}
|
||||||
size_t output_index = 0;
|
size_t output_index = 0;
|
||||||
|
bool miner_tx = cryptonote::is_coinbase(spent_tx);
|
||||||
for (const cryptonote::tx_out& out : spent_tx.vout)
|
for (const cryptonote::tx_out& out : spent_tx.vout)
|
||||||
{
|
{
|
||||||
tx_scan_info_t tx_scan_info;
|
tx_scan_info_t tx_scan_info;
|
||||||
@ -11315,11 +11319,13 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
|
|||||||
THROW_WALLET_EXCEPTION_IF(tx_scan_info.error, error::wallet_internal_error, "check_acc_out_precomp failed");
|
THROW_WALLET_EXCEPTION_IF(tx_scan_info.error, error::wallet_internal_error, "check_acc_out_precomp failed");
|
||||||
if (tx_scan_info.received)
|
if (tx_scan_info.received)
|
||||||
{
|
{
|
||||||
if (tx_scan_info.money_transfered == 0)
|
if (tx_scan_info.money_transfered == 0 && !miner_tx)
|
||||||
{
|
{
|
||||||
rct::key mask;
|
rct::key mask;
|
||||||
tx_scan_info.money_transfered = tools::decodeRct(spent_tx.rct_signatures, tx_scan_info.received->derivation, output_index, mask, hwdev);
|
tx_scan_info.money_transfered = tools::decodeRct(spent_tx.rct_signatures, tx_scan_info.received->derivation, output_index, mask, hwdev);
|
||||||
}
|
}
|
||||||
|
THROW_WALLET_EXCEPTION_IF(tx_money_got_in_outs >= std::numeric_limits<uint64_t>::max() - tx_scan_info.money_transfered,
|
||||||
|
error::wallet_internal_error, "Overflow in received amounts");
|
||||||
tx_money_got_in_outs += tx_scan_info.money_transfered;
|
tx_money_got_in_outs += tx_scan_info.money_transfered;
|
||||||
}
|
}
|
||||||
++output_index;
|
++output_index;
|
||||||
|
@ -1292,7 +1292,7 @@ namespace tools
|
|||||||
bool tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, uint64_t global_index, const crypto::public_key& tx_public_key, const rct::key& mask, uint64_t real_index, bool unlocked) const;
|
bool tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, uint64_t global_index, const crypto::public_key& tx_public_key, const rct::key& mask, uint64_t real_index, bool unlocked) const;
|
||||||
bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector<size_t> &unused_transfers_indices, const std::vector<size_t> &unused_dust_indices) const;
|
bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector<size_t> &unused_transfers_indices, const std::vector<size_t> &unused_dust_indices) const;
|
||||||
std::vector<size_t> get_only_rct(const std::vector<size_t> &unused_dust_indices, const std::vector<size_t> &unused_transfers_indices) const;
|
std::vector<size_t> get_only_rct(const std::vector<size_t> &unused_dust_indices, const std::vector<size_t> &unused_transfers_indices) const;
|
||||||
void scan_output(const cryptonote::transaction &tx, const crypto::public_key &tx_pub_key, size_t i, tx_scan_info_t &tx_scan_info, int &num_vouts_received, std::unordered_map<cryptonote::subaddress_index, uint64_t> &tx_money_got_in_outs, std::vector<size_t> &outs, bool pool);
|
void scan_output(const cryptonote::transaction &tx, bool miner_tx, const crypto::public_key &tx_pub_key, size_t i, tx_scan_info_t &tx_scan_info, int &num_vouts_received, std::unordered_map<cryptonote::subaddress_index, uint64_t> &tx_money_got_in_outs, std::vector<size_t> &outs, bool pool);
|
||||||
void trim_hashchain();
|
void trim_hashchain();
|
||||||
crypto::key_image get_multisig_composite_key_image(size_t n) const;
|
crypto::key_image get_multisig_composite_key_image(size_t n) const;
|
||||||
rct::multisig_kLRki get_multisig_composite_kLRki(size_t n, const std::unordered_set<crypto::public_key> &ignore_set, std::unordered_set<rct::key> &used_L, std::unordered_set<rct::key> &new_used_L) const;
|
rct::multisig_kLRki get_multisig_composite_kLRki(size_t n, const std::unordered_set<crypto::public_key> &ignore_set, std::unordered_set<rct::key> &used_L, std::unordered_set<rct::key> &new_used_L) const;
|
||||||
|
Loading…
Reference in New Issue
Block a user