this code is a hot mess of confusion with transfer_details and public_keys being scattered to the four winds. this code is NOT safe to use in its current format
This commit is contained in:
@@ -1074,6 +1074,8 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tx.type == cryptonote::transaction_type::CONVERT || tx.type == cryptonote::transaction_type::BURN) {
|
if (tx.type == cryptonote::transaction_type::CONVERT || tx.type == cryptonote::transaction_type::BURN) {
|
||||||
|
|
||||||
|
/*
|
||||||
// Conversion TX - update our records
|
// Conversion TX - update our records
|
||||||
circ_supply cs;
|
circ_supply cs;
|
||||||
cs.tx_hash = tx_hash;
|
cs.tx_hash = tx_hash;
|
||||||
@@ -1085,12 +1087,12 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons
|
|||||||
result = mdb_cursor_put(m_cur_circ_supply, &val_tx_id, &val_circ_supply, MDB_APPEND);
|
result = mdb_cursor_put(m_cur_circ_supply, &val_tx_id, &val_circ_supply, MDB_APPEND);
|
||||||
if (result)
|
if (result)
|
||||||
throw0(DB_ERROR( lmdb_error("Failed to add tx circulating supply to db transaction: ", result).c_str() ));
|
throw0(DB_ERROR( lmdb_error("Failed to add tx circulating supply to db transaction: ", result).c_str() ));
|
||||||
|
*/
|
||||||
// Get the current tally value for the source currency type
|
// Get the current tally value for the source currency type
|
||||||
MDB_val_copy<uint64_t> source_idx(cs.asset_type);
|
MDB_val_copy<uint64_t> source_idx(cryptonote::asset_id_from_type(tx.source_asset_type));
|
||||||
boost::multiprecision::int128_t source_tally = 0;
|
boost::multiprecision::int128_t source_tally = 0;
|
||||||
result = read_circulating_supply_data(m_cur_circ_supply_tally, source_idx, source_tally);
|
result = read_circulating_supply_data(m_cur_circ_supply_tally, source_idx, source_tally);
|
||||||
boost::multiprecision::int128_t final_source_tally = source_tally - cs.amount_burnt;
|
boost::multiprecision::int128_t final_source_tally = source_tally - tx.amount_burnt;
|
||||||
boost::multiprecision::int128_t coinbase = get_block_already_generated_coins(m_height-1);
|
boost::multiprecision::int128_t coinbase = get_block_already_generated_coins(m_height-1);
|
||||||
if (source_tally == 0 && result == MDB_NOTFOUND) {
|
if (source_tally == 0 && result == MDB_NOTFOUND) {
|
||||||
if (tx.source_asset_type == "FULM") {
|
if (tx.source_asset_type == "FULM") {
|
||||||
@@ -1114,19 +1116,20 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons
|
|||||||
bool ok = cryptonote::get_output_asset_type(out, asset_type);
|
bool ok = cryptonote::get_output_asset_type(out, asset_type);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
throw0(DB_ERROR("failed to get output asset type (needed to update the circulating supply data for the PROTOCOL_TX)"));
|
throw0(DB_ERROR("failed to get output asset type (needed to update the circulating supply data for the PROTOCOL_TX)"));
|
||||||
|
/*
|
||||||
circ_supply cs;
|
circ_supply cs;
|
||||||
cs.tx_hash = tx_hash;
|
cs.tx_hash = tx_hash;
|
||||||
cs.asset_type = cryptonote::asset_id_from_type(asset_type);
|
cs.asset_type = cryptonote::asset_id_from_type(asset_type);
|
||||||
cs.amount_burnt = 0;
|
cs.amount_burnt = 0;
|
||||||
cs.amount_minted = out.amount;
|
cs.amount_minted = out.amount;
|
||||||
|
*/
|
||||||
minted_amounts[cs.asset_type] += out.amount;
|
minted_amounts[cryptonote::asset_id_from_type(asset_type)] += out.amount;
|
||||||
|
/*
|
||||||
MDB_val_set(val_circ_supply, cs);
|
MDB_val_set(val_circ_supply, cs);
|
||||||
result = mdb_cursor_put(m_cur_circ_supply, &val_tx_id, &val_circ_supply, MDB_APPEND);
|
result = mdb_cursor_put(m_cur_circ_supply, &val_tx_id, &val_circ_supply, MDB_APPENDDUP);
|
||||||
if (result)
|
if (result)
|
||||||
throw0(DB_ERROR( lmdb_error("Failed to add tx circulating supply to db transaction: ", result).c_str() ));
|
throw0(DB_ERROR( lmdb_error("Failed to add tx circulating supply to db transaction: ", result).c_str() ));
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now update the overall tally entries
|
// Now update the overall tally entries
|
||||||
@@ -1273,7 +1276,7 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const
|
|||||||
LOG_PRINT_L1("tx ID " << tip->data.tx_id << "\n\tAsset Type = " << cryptonote::asset_type_from_id(asset.first) << "\n\tTally before undoing mint =" << source_tally.str() << "\n\tTally after undoing mint =" << final_source_tally.str());
|
LOG_PRINT_L1("tx ID " << tip->data.tx_id << "\n\tAsset Type = " << cryptonote::asset_type_from_id(asset.first) << "\n\tTally before undoing mint =" << source_tally.str() << "\n\tTally after undoing mint =" << final_source_tally.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
// Update the circ_supply table by deleting all entries for this TX
|
// Update the circ_supply table by deleting all entries for this TX
|
||||||
if ((result = mdb_cursor_get(m_cur_circ_supply, &val_tx_id, NULL, MDB_SET))) {
|
if ((result = mdb_cursor_get(m_cur_circ_supply, &val_tx_id, NULL, MDB_SET))) {
|
||||||
if (result == MDB_NOTFOUND) {
|
if (result == MDB_NOTFOUND) {
|
||||||
@@ -1286,6 +1289,7 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const
|
|||||||
if (result)
|
if (result)
|
||||||
throw1(DB_ERROR(lmdb_error("Failed to add removal of circulating supply to db transaction: ", result).c_str()));
|
throw1(DB_ERROR(lmdb_error("Failed to add removal of circulating supply to db transaction: ", result).c_str()));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
remove_tx_outputs(tip->data.tx_id, tx);
|
remove_tx_outputs(tip->data.tx_id, tx);
|
||||||
|
|
||||||
result = mdb_cursor_get(m_cur_tx_outputs, &val_tx_id, NULL, MDB_SET);
|
result = mdb_cursor_get(m_cur_tx_outputs, &val_tx_id, NULL, MDB_SET);
|
||||||
@@ -1818,6 +1822,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
|
|||||||
mdb_set_compare(txn, m_properties, compare_string);
|
mdb_set_compare(txn, m_properties, compare_string);
|
||||||
|
|
||||||
mdb_set_compare(txn, m_circ_supply, compare_uint64);
|
mdb_set_compare(txn, m_circ_supply, compare_uint64);
|
||||||
|
mdb_set_dupsort(txn, m_circ_supply, compare_uint64);
|
||||||
mdb_set_compare(txn, m_circ_supply_tally, compare_uint64);
|
mdb_set_compare(txn, m_circ_supply_tally, compare_uint64);
|
||||||
|
|
||||||
mdb_set_dupsort(txn, m_yield_txs, compare_uint64);
|
mdb_set_dupsort(txn, m_yield_txs, compare_uint64);
|
||||||
|
|||||||
@@ -212,6 +212,7 @@ namespace crypto {
|
|||||||
tools::write_varint(end, output_index);
|
tools::write_varint(end, output_index);
|
||||||
assert(end <= buf.output_index + sizeof buf.output_index);
|
assert(end <= buf.output_index + sizeof buf.output_index);
|
||||||
hash_to_scalar(&buf, end - reinterpret_cast<char *>(&buf), res);
|
hash_to_scalar(&buf, end - reinterpret_cast<char *>(&buf), res);
|
||||||
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool crypto_ops::derive_public_key(const key_derivation &derivation, size_t output_index,
|
bool crypto_ops::derive_public_key(const key_derivation &derivation, size_t output_index,
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ namespace cryptonote
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<subaddress_receive_info> subaddr_recv_info = is_out_to_acc_precomp(subaddresses, out_key, recv_derivation, additional_recv_derivations, real_output_index,hwdev);
|
boost::optional<subaddress_receive_info> subaddr_recv_info = is_out_to_acc_precomp(subaddresses, out_key, recv_derivation, additional_recv_derivations, uniqueness,hwdev);
|
||||||
CHECK_AND_ASSERT_MES(subaddr_recv_info, false, "key image helper: given output pubkey doesn't seem to belong to this address");
|
CHECK_AND_ASSERT_MES(subaddr_recv_info, false, "key image helper: given output pubkey doesn't seem to belong to this address");
|
||||||
|
|
||||||
return generate_key_image_helper_precomp(ack, out_key, subaddr_recv_info->derivation, real_output_index, uniqueness, subaddr_recv_info->index, in_ephemeral, ki, hwdev);
|
return generate_key_image_helper_precomp(ack, out_key, subaddr_recv_info->derivation, real_output_index, uniqueness, subaddr_recv_info->index, in_ephemeral, ki, hwdev);
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ namespace cryptonote
|
|||||||
crypto::key_derivation derivation;
|
crypto::key_derivation derivation;
|
||||||
};
|
};
|
||||||
boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, size_t output_index, hw::device &hwdev, const boost::optional<crypto::view_tag>& view_tag_opt = boost::optional<crypto::view_tag>());
|
boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, size_t output_index, hw::device &hwdev, const boost::optional<crypto::view_tag>& view_tag_opt = boost::optional<crypto::view_tag>());
|
||||||
|
boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, const crypto::hash& uniqueness, hw::device &hwdev, const boost::optional<crypto::view_tag>& view_tag_opt = boost::optional<crypto::view_tag>());
|
||||||
boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, const crypto::key_image& ki, hw::device &hwdev, const boost::optional<crypto::view_tag>& view_tag_opt = boost::optional<crypto::view_tag>());
|
boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, const crypto::key_image& ki, hw::device &hwdev, const boost::optional<crypto::view_tag>& view_tag_opt = boost::optional<crypto::view_tag>());
|
||||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_public_keys, std::vector<size_t>& outs, uint64_t& money_transfered);
|
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_public_keys, std::vector<size_t>& outs, uint64_t& money_transfered);
|
||||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered);
|
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered);
|
||||||
|
|||||||
@@ -260,8 +260,8 @@ namespace config
|
|||||||
0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x10
|
0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x10
|
||||||
} }; // Bender's nightmare
|
} }; // Bender's nightmare
|
||||||
|
|
||||||
std::string const GENESIS_TX = "023c01ff000180c09e90acbb1402ba4fcfcff0d4a91441c87615e514be3938e173179ac34a7fc98c0286e7320fdc0446554c4d3c0000000000000021019e809607ceda9ae7ae6755e05bcdc9c555acc8e95dcaede402eca1166a032e1a0100000000000000000000000000000000000000000000000000000000000000000000000000";
|
//std::string const GENESIS_TX = "023c01ff000180c09e90acbb1402ba4fcfcff0d4a91441c87615e514be3938e173179ac34a7fc98c0286e7320fdc0446554c4d3c0000000000000021019e809607ceda9ae7ae6755e05bcdc9c555acc8e95dcaede402eca1166a032e1a0100000000000000000000000000000000000000000000000000000000000000000000000000";
|
||||||
|
std::string const GENESIS_TX = "023c01ff000180c09e90acbb1402ae6cfc932cab508d92455942efbb2ec5a8632e33ff6bcac04a8e31be271efb8c0446554c4d3c0000000000000021015a71ac0441d4ee3f321df5ffd4bd3d0f04755152e7e6485a3b6c965356cb92ed0100000000000000000000000000000000000000000000000000000000000000000000000000";
|
||||||
uint32_t const GENESIS_NONCE = 10000;
|
uint32_t const GENESIS_NONCE = 10000;
|
||||||
|
|
||||||
// Hash domain separators
|
// Hash domain separators
|
||||||
|
|||||||
@@ -1386,7 +1386,6 @@ bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
MDEBUG("Miner tx hash: " << get_transaction_hash(b.miner_tx));
|
MDEBUG("Miner tx hash: " << get_transaction_hash(b.miner_tx));
|
||||||
CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "coinbase transaction transaction has the wrong unlock time=" << b.miner_tx.unlock_time << ", expected " << height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW);
|
|
||||||
|
|
||||||
//check outs overflow
|
//check outs overflow
|
||||||
if(!check_outs_overflow(b.miner_tx))
|
if(!check_outs_overflow(b.miner_tx))
|
||||||
@@ -2483,6 +2482,36 @@ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMA
|
|||||||
res.outs.clear();
|
res.outs.clear();
|
||||||
res.outs.reserve(req.outputs.size());
|
res.outs.reserve(req.outputs.size());
|
||||||
|
|
||||||
|
// if an asset type is provided in the request, most indexes provided in the request are asset type output id's.
|
||||||
|
// need to use the asset type output id's provided to retrieve the respective global output id's
|
||||||
|
std::map<uint64_t, uint64_t> global_outs_by_asset_type_output_id;
|
||||||
|
if (!req.asset_type.empty())
|
||||||
|
{
|
||||||
|
std::vector<uint64_t> asset_type_output_indices;
|
||||||
|
for (const auto &i: req.outputs)
|
||||||
|
{
|
||||||
|
// some inputs in the request have already been used in attempted rings in the past. These inputs will
|
||||||
|
// have the is_global_out flag set to true, since they already have the global output id saved
|
||||||
|
if (!i.is_global_out)
|
||||||
|
asset_type_output_indices.push_back(i.index);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint64_t> global_out_ids;
|
||||||
|
global_out_ids.reserve(asset_type_output_indices.size());
|
||||||
|
|
||||||
|
m_db->get_output_id_from_asset_type_output_index(req.asset_type, asset_type_output_indices, global_out_ids);
|
||||||
|
|
||||||
|
uint64_t global_outs = 0;
|
||||||
|
for (const auto &i: req.outputs)
|
||||||
|
{
|
||||||
|
if (!i.is_global_out)
|
||||||
|
{
|
||||||
|
global_outs_by_asset_type_output_id[i.index] = global_out_ids[global_outs];
|
||||||
|
++global_outs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<cryptonote::output_data_t> data;
|
std::vector<cryptonote::output_data_t> data;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -2492,7 +2521,11 @@ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMA
|
|||||||
for (const auto &i: req.outputs)
|
for (const auto &i: req.outputs)
|
||||||
{
|
{
|
||||||
amounts.push_back(i.amount);
|
amounts.push_back(i.amount);
|
||||||
|
// if no asset type provided, the offsets provided are already global output id's unless specifically set
|
||||||
|
if (req.asset_type.empty() || i.is_global_out)
|
||||||
offsets.push_back(i.index);
|
offsets.push_back(i.index);
|
||||||
|
else
|
||||||
|
offsets.push_back(global_outs_by_asset_type_output_id[i.index]);
|
||||||
}
|
}
|
||||||
m_db->get_output_key(epee::span<const uint64_t>(amounts.data(), amounts.size()), offsets, data);
|
m_db->get_output_key(epee::span<const uint64_t>(amounts.data(), amounts.size()), offsets, data);
|
||||||
if (data.size() != req.outputs.size())
|
if (data.size() != req.outputs.size())
|
||||||
@@ -2512,6 +2545,11 @@ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMA
|
|||||||
res.outs[i].txid = toi.first;
|
res.outs[i].txid = toi.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!req.asset_type.empty())
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < req.outputs.size(); ++i)
|
||||||
|
res.outs[i].output_id = offsets[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception &e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ namespace cryptonote
|
|||||||
tx.version = 2;
|
tx.version = 2;
|
||||||
|
|
||||||
//lock
|
//lock
|
||||||
tx.unlock_time = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
|
tx.unlock_time = 0;//height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
|
||||||
tx.vin.push_back(in);
|
tx.vin.push_back(in);
|
||||||
|
|
||||||
tx.invalidate_hashes();
|
tx.invalidate_hashes();
|
||||||
@@ -436,7 +436,7 @@ namespace cryptonote
|
|||||||
} else {
|
} else {
|
||||||
tx.version = 2;
|
tx.version = 2;
|
||||||
}
|
}
|
||||||
tx.unlock_time = unlock_time;
|
tx.unlock_time = 0;//unlock_time;
|
||||||
|
|
||||||
tx.extra = extra;
|
tx.extra = extra;
|
||||||
crypto::public_key txkey_pub;
|
crypto::public_key txkey_pub;
|
||||||
@@ -552,7 +552,7 @@ namespace cryptonote
|
|||||||
crypto::hash uniqueness = cn_fast_hash(reinterpret_cast<void*>(&output_index_wrapper), sizeof(size_t));
|
crypto::hash uniqueness = cn_fast_hash(reinterpret_cast<void*>(&output_index_wrapper), sizeof(size_t));
|
||||||
|
|
||||||
const auto& out_key = reinterpret_cast<const crypto::public_key&>(src_entr.outputs[src_entr.real_output].second.dest);
|
const auto& out_key = reinterpret_cast<const crypto::public_key&>(src_entr.outputs[src_entr.real_output].second.dest);
|
||||||
if(!generate_key_image_helper(sender_account_keys, subaddresses, out_key, src_entr.real_out_tx_key, src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index, uniqueness, in_ephemeral,img, hwdev))
|
if(!generate_key_image_helper(sender_account_keys, subaddresses, out_key, src_entr.real_out_tx_key, src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index, src_entr.uniqueness, in_ephemeral,img, hwdev))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Key image generation failed!");
|
LOG_ERROR("Key image generation failed!");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ namespace cryptonote
|
|||||||
rct::multisig_kLRki multisig_kLRki; //multisig info
|
rct::multisig_kLRki multisig_kLRki; //multisig info
|
||||||
oracle::pricing_record pr;
|
oracle::pricing_record pr;
|
||||||
std::string asset_type;
|
std::string asset_type;
|
||||||
|
crypto::hash uniqueness; //the uniqueness needed to prove ownership of the consumed output
|
||||||
|
|
||||||
void push_output(uint64_t idx, const crypto::public_key &k, uint64_t amount) { outputs.push_back(std::make_pair(idx, rct::ctkey({rct::pk2rct(k), rct::zeroCommit(amount)}))); }
|
void push_output(uint64_t idx, const crypto::public_key &k, uint64_t amount) { outputs.push_back(std::make_pair(idx, rct::ctkey({rct::pk2rct(k), rct::zeroCommit(amount)}))); }
|
||||||
|
|
||||||
|
|||||||
@@ -847,6 +847,7 @@ namespace cryptonote
|
|||||||
cryptonote::COMMAND_RPC_GET_OUTPUTS_BIN::request req_bin;
|
cryptonote::COMMAND_RPC_GET_OUTPUTS_BIN::request req_bin;
|
||||||
req_bin.outputs = req.outputs;
|
req_bin.outputs = req.outputs;
|
||||||
req_bin.get_txid = req.get_txid;
|
req_bin.get_txid = req.get_txid;
|
||||||
|
req_bin.asset_type = req.asset_type;
|
||||||
cryptonote::COMMAND_RPC_GET_OUTPUTS_BIN::response res_bin;
|
cryptonote::COMMAND_RPC_GET_OUTPUTS_BIN::response res_bin;
|
||||||
if(!m_core.get_outs(req_bin, res_bin))
|
if(!m_core.get_outs(req_bin, res_bin))
|
||||||
{
|
{
|
||||||
|
|||||||
+127
-42
@@ -1799,6 +1799,7 @@ void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivatio
|
|||||||
if(tx_scan_info.received)
|
if(tx_scan_info.received)
|
||||||
{
|
{
|
||||||
tx_scan_info.money_transfered = o.amount; // may be 0 for ringct outputs
|
tx_scan_info.money_transfered = o.amount; // may be 0 for ringct outputs
|
||||||
|
tx_scan_info.uniqueness = cn_fast_hash(reinterpret_cast<void*>(&i), sizeof(size_t));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -4126,6 +4127,7 @@ bool wallet2::clear()
|
|||||||
{
|
{
|
||||||
m_blockchain.clear();
|
m_blockchain.clear();
|
||||||
m_transfers.clear();
|
m_transfers.clear();
|
||||||
|
m_transfers_indices.clear();
|
||||||
m_key_images.clear();
|
m_key_images.clear();
|
||||||
m_pub_keys.clear();
|
m_pub_keys.clear();
|
||||||
m_unconfirmed_txs.clear();
|
m_unconfirmed_txs.clear();
|
||||||
@@ -4148,6 +4150,7 @@ void wallet2::clear_soft(bool keep_key_images)
|
|||||||
{
|
{
|
||||||
m_blockchain.clear();
|
m_blockchain.clear();
|
||||||
m_transfers.clear();
|
m_transfers.clear();
|
||||||
|
m_transfers_indices.clear();
|
||||||
if (!keep_key_images)
|
if (!keep_key_images)
|
||||||
m_key_images.clear();
|
m_key_images.clear();
|
||||||
m_pub_keys.clear();
|
m_pub_keys.clear();
|
||||||
@@ -6585,21 +6588,9 @@ bool wallet2::is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t block_heig
|
|||||||
if(unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER)
|
if(unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER)
|
||||||
{
|
{
|
||||||
//interpret as block index
|
//interpret as block index
|
||||||
if(get_blockchain_current_height()-1 + CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS >= unlock_time)
|
uint64_t min_unlock_blocks = CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE;
|
||||||
return true;
|
uint64_t unlock_height = block_height + std::max(min_unlock_blocks, unlock_time);
|
||||||
else
|
if(get_blockchain_current_height()-1 + CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS >= unlock_height)
|
||||||
return false;
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
//interpret as time
|
|
||||||
uint64_t adjusted_time;
|
|
||||||
try { adjusted_time = get_daemon_adjusted_time(); }
|
|
||||||
catch(...) { adjusted_time = time(NULL); } // use local time if no daemon to report blockchain time
|
|
||||||
// XXX: this needs to be fast, so we'd need to get the starting heights
|
|
||||||
// from the daemon to be correct once voting kicks in
|
|
||||||
uint64_t v2height = m_nettype == TESTNET ? 624634 : m_nettype == STAGENET ? 32000 : 1009827;
|
|
||||||
uint64_t leeway = block_height < v2height ? CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 : CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V2;
|
|
||||||
if(adjusted_time + leeway >= unlock_time)
|
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
@@ -6853,7 +6844,7 @@ void wallet2::commit_tx(pending_tx& ptx)
|
|||||||
{
|
{
|
||||||
THROW_WALLET_EXCEPTION_IF(idx >= m_transfers.size(), error::wallet_internal_error,
|
THROW_WALLET_EXCEPTION_IF(idx >= m_transfers.size(), error::wallet_internal_error,
|
||||||
"Bad output index in selected transfers: " + boost::lexical_cast<std::string>(idx));
|
"Bad output index in selected transfers: " + boost::lexical_cast<std::string>(idx));
|
||||||
THROW_WALLET_EXCEPTION_IF(m_transfers[idx].asset_type >= source_asset, error::wallet_internal_error,
|
THROW_WALLET_EXCEPTION_IF(m_transfers[idx].asset_type != source_asset, error::wallet_internal_error,
|
||||||
"Bad output asset_type in selected transfers: " + boost::lexical_cast<std::string>(idx));
|
"Bad output asset_type in selected transfers: " + boost::lexical_cast<std::string>(idx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8449,6 +8440,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
|||||||
req_t.amounts.resize(std::distance(req_t.amounts.begin(), end));
|
req_t.amounts.resize(std::distance(req_t.amounts.begin(), end));
|
||||||
req_t.from_height = std::max<uint64_t>(segregation_fork_height, RECENT_OUTPUT_BLOCKS) - RECENT_OUTPUT_BLOCKS;
|
req_t.from_height = std::max<uint64_t>(segregation_fork_height, RECENT_OUTPUT_BLOCKS) - RECENT_OUTPUT_BLOCKS;
|
||||||
req_t.to_height = segregation_fork_height + 1;
|
req_t.to_height = segregation_fork_height + 1;
|
||||||
|
req_t.rct_asset_type = rct_asset_type;
|
||||||
req_t.cumulative = true;
|
req_t.cumulative = true;
|
||||||
req_t.binary = true;
|
req_t.binary = true;
|
||||||
|
|
||||||
@@ -8836,6 +8828,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
|||||||
COMMAND_RPC_GET_OUTPUTS_BIN::request chunk_req = AUTO_VAL_INIT(chunk_req);
|
COMMAND_RPC_GET_OUTPUTS_BIN::request chunk_req = AUTO_VAL_INIT(chunk_req);
|
||||||
COMMAND_RPC_GET_OUTPUTS_BIN::response chunk_daemon_resp = AUTO_VAL_INIT(chunk_daemon_resp);
|
COMMAND_RPC_GET_OUTPUTS_BIN::response chunk_daemon_resp = AUTO_VAL_INIT(chunk_daemon_resp);
|
||||||
chunk_req.get_txid = false;
|
chunk_req.get_txid = false;
|
||||||
|
chunk_req.asset_type = rct_asset_type;
|
||||||
const size_t this_chunk_size = std::min<size_t>(req.outputs.size() - offset, chunk_size);
|
const size_t this_chunk_size = std::min<size_t>(req.outputs.size() - offset, chunk_size);
|
||||||
chunk_req.outputs.reserve(this_chunk_size);
|
chunk_req.outputs.reserve(this_chunk_size);
|
||||||
for (size_t i = 0; i < this_chunk_size; ++i)
|
for (size_t i = 0; i < this_chunk_size; ++i)
|
||||||
@@ -8893,7 +8886,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
|||||||
for (size_t n = 0; n < requested_outputs_count; ++n)
|
for (size_t n = 0; n < requested_outputs_count; ++n)
|
||||||
{
|
{
|
||||||
size_t i = base + n;
|
size_t i = base + n;
|
||||||
if (req.outputs[i].index == td.m_global_output_index)
|
if (daemon_resp.outs[i].output_id == td.m_global_output_index)
|
||||||
if (daemon_resp.outs[i].key == td.get_public_key())
|
if (daemon_resp.outs[i].key == td.get_public_key())
|
||||||
if (daemon_resp.outs[i].mask == mask)
|
if (daemon_resp.outs[i].mask == mask)
|
||||||
if (daemon_resp.outs[i].unlocked)
|
if (daemon_resp.outs[i].unlocked)
|
||||||
@@ -9080,6 +9073,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
|
|||||||
src.real_output = it_to_replace - src.outputs.begin();
|
src.real_output = it_to_replace - src.outputs.begin();
|
||||||
src.real_output_in_tx_index = td.m_internal_output_index;
|
src.real_output_in_tx_index = td.m_internal_output_index;
|
||||||
src.multisig_kLRki = rct::multisig_kLRki({rct::zero(), rct::zero(), rct::zero(), rct::zero()});
|
src.multisig_kLRki = rct::multisig_kLRki({rct::zero(), rct::zero(), rct::zero(), rct::zero()});
|
||||||
|
|
||||||
detail::print_source_entry(src);
|
detail::print_source_entry(src);
|
||||||
++out_index;
|
++out_index;
|
||||||
}
|
}
|
||||||
@@ -9298,6 +9292,42 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
|
|||||||
src.amount = td.amount();
|
src.amount = td.amount();
|
||||||
src.rct = td.is_rct();
|
src.rct = td.is_rct();
|
||||||
src.asset_type = td.asset_type;
|
src.asset_type = td.asset_type;
|
||||||
|
|
||||||
|
// check to see if the tx_source_entry was a payout from a protocol_tx
|
||||||
|
if (td.m_tx.type == cryptonote::transaction_type::PROTOCOL) {
|
||||||
|
|
||||||
|
// Parse the uniqueness from the originating TX key image
|
||||||
|
crypto::public_key output_public_key = td.get_public_key();
|
||||||
|
auto search = m_protocol_txs.find(output_public_key);
|
||||||
|
THROW_WALLET_EXCEPTION_IF(search == m_protocol_txs.end(), error::wallet_internal_error, "failed to locate protocol_tx entry to permit source usage");
|
||||||
|
size_t idx = search->second;
|
||||||
|
THROW_WALLET_EXCEPTION_IF(idx >= get_num_transfer_details(), error::wallet_internal_error, "cannot locate protocol_txs index in m_transfers");
|
||||||
|
const transfer_details& td2 = get_transfer_details(idx);
|
||||||
|
THROW_WALLET_EXCEPTION_IF(td2.m_tx.type != cryptonote::transaction_type::CONVERT && td2.m_tx.type != cryptonote::transaction_type::YIELD, error::wallet_internal_error, "incorrect TX type for protocol_tx origin in m_transfers");
|
||||||
|
|
||||||
|
// We now have access to the sorted tx.vin vector - we need the key_image from the first entry to decode the public_key
|
||||||
|
THROW_WALLET_EXCEPTION_IF(td2.m_tx.vin[0].type() != typeid(cryptonote::txin_to_key), error::wallet_internal_error, "incorrect TX vin[0] type for protocol_tx origin in m_transfers");
|
||||||
|
|
||||||
|
const txin_to_key &in = boost::get<txin_to_key>(td2.m_tx.vin[0]);
|
||||||
|
crypto::key_image ki = in.k_image;
|
||||||
|
|
||||||
|
crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(td2.m_tx);
|
||||||
|
THROW_WALLET_EXCEPTION_IF(tx_pub_key == null_pkey, error::wallet_internal_error, "Tx pubkey was not found");
|
||||||
|
|
||||||
|
// Generate a derivation using the _correct_ TX pubkey
|
||||||
|
crypto::key_derivation convert_tx_derivation;
|
||||||
|
THROW_WALLET_EXCEPTION_IF(!generate_key_derivation(tx_pub_key, get_account().get_keys().m_view_secret_key, convert_tx_derivation), error::wallet_internal_error, "Failed to generate a derivation image");
|
||||||
|
|
||||||
|
// Derive a public key now, using the information we have
|
||||||
|
crypto::hash uniqueness = cn_fast_hash(&ki.data[0], 32);
|
||||||
|
crypto::public_key pk = crypto::null_pkey;
|
||||||
|
THROW_WALLET_EXCEPTION_IF(!m_account.get_device().derive_public_key(convert_tx_derivation, uniqueness, get_account().get_keys().m_account_address.m_spend_public_key, pk), error::wallet_internal_error, "Failed to derive a public key given the necessary key image");
|
||||||
|
THROW_WALLET_EXCEPTION_IF(pk != output_public_key, error::wallet_internal_error, "public key derived from CONVERT_TX uniqueness does not match");
|
||||||
|
src.uniqueness = uniqueness;
|
||||||
|
} else {
|
||||||
|
size_t output_index_wrapper = td.m_internal_output_index;
|
||||||
|
src.uniqueness = cn_fast_hash(reinterpret_cast<void*>(&output_index_wrapper), sizeof(size_t));
|
||||||
|
}
|
||||||
//paste mixin transaction
|
//paste mixin transaction
|
||||||
|
|
||||||
THROW_WALLET_EXCEPTION_IF(outs.size() < out_index + 1 , error::wallet_internal_error, "outs.size() < out_index + 1");
|
THROW_WALLET_EXCEPTION_IF(outs.size() < out_index + 1 , error::wallet_internal_error, "outs.size() < out_index + 1");
|
||||||
@@ -9337,6 +9367,23 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
|
|||||||
src.multisig_kLRki = {.k = {}, .L = {}, .R = {}, .ki = rct::ki2rct(td.m_key_image)};
|
src.multisig_kLRki = {.k = {}, .L = {}, .R = {}, .ki = rct::ki2rct(td.m_key_image)};
|
||||||
else
|
else
|
||||||
src.multisig_kLRki = rct::multisig_kLRki({rct::zero(), rct::zero(), rct::zero(), rct::zero()});
|
src.multisig_kLRki = rct::multisig_kLRki({rct::zero(), rct::zero(), rct::zero(), rct::zero()});
|
||||||
|
|
||||||
|
if (td.m_tx.type == cryptonote::transaction_type::PROTOCOL) {
|
||||||
|
|
||||||
|
LOG_ERROR("****************************** TD IS FROM A PROTOCOL_TX ******************************");
|
||||||
|
|
||||||
|
// Get the necessary information from the originating CONVERT / YIELD tx
|
||||||
|
auto search = m_protocol_txs.find(td.get_public_key());
|
||||||
|
THROW_WALLET_EXCEPTION_IF(search == m_protocol_txs.end(), error::wallet_internal_error, "failed to locate protocol_tx entry to permit source usage");
|
||||||
|
size_t idx = search->second;
|
||||||
|
THROW_WALLET_EXCEPTION_IF(idx >= get_num_transfer_details(), error::wallet_internal_error, "cannot locate protocol_txs index in m_transfers");
|
||||||
|
const transfer_details& td2 = get_transfer_details(idx);
|
||||||
|
THROW_WALLET_EXCEPTION_IF(td2.m_tx.type != cryptonote::transaction_type::CONVERT && td2.m_tx.type != cryptonote::transaction_type::YIELD, error::wallet_internal_error, "incorrect TX type for protocol_tx origin in m_transfers");
|
||||||
|
real_oe.second.dest = rct::pk2rct(td2.get_public_key());
|
||||||
|
src.real_out_tx_key = get_tx_pub_key_from_extra(td2.m_tx, td.m_pk_index);
|
||||||
|
src.real_out_additional_tx_keys = get_additional_tx_pub_keys_from_extra(td2.m_tx);
|
||||||
|
}
|
||||||
|
|
||||||
detail::print_source_entry(src);
|
detail::print_source_entry(src);
|
||||||
++out_index;
|
++out_index;
|
||||||
}
|
}
|
||||||
@@ -9346,6 +9393,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
|
|||||||
std::vector<cryptonote::tx_destination_entry> splitted_dsts = dsts;
|
std::vector<cryptonote::tx_destination_entry> splitted_dsts = dsts;
|
||||||
cryptonote::tx_destination_entry change_dts = AUTO_VAL_INIT(change_dts);
|
cryptonote::tx_destination_entry change_dts = AUTO_VAL_INIT(change_dts);
|
||||||
change_dts.amount = found_money - needed_money;
|
change_dts.amount = found_money - needed_money;
|
||||||
|
change_dts.asset_type = source_asset;
|
||||||
change_dts.is_change = true;
|
change_dts.is_change = true;
|
||||||
if (change_dts.amount == 0)
|
if (change_dts.amount == 0)
|
||||||
{
|
{
|
||||||
@@ -9549,15 +9597,21 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
|
|||||||
LOG_PRINT_L2("transfer_selected_rct done");
|
LOG_PRINT_L2("transfer_selected_rct done");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices)
|
std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices, const std::string& asset_type)
|
||||||
{
|
{
|
||||||
std::vector<size_t> picks;
|
std::vector<size_t> picks;
|
||||||
float current_output_relatdness = 1.0f;
|
float current_output_relatdness = 1.0f;
|
||||||
|
|
||||||
LOG_PRINT_L2("pick_preferred_rct_inputs: needed_money " << print_money(needed_money));
|
LOG_PRINT_L2("pick_preferred_rct_inputs: needed_money " << print_money(needed_money) << " " << asset_type);
|
||||||
|
|
||||||
|
// Make sure we have transfer indices for the specified asset_type
|
||||||
|
if (m_transfers_indices.count(asset_type) == 0) {
|
||||||
|
LOG_ERROR("Failed to find list of indices for '" << asset_type << "' - aborting");
|
||||||
|
return picks;
|
||||||
|
}
|
||||||
|
|
||||||
// try to find a rct input of enough size
|
// try to find a rct input of enough size
|
||||||
for (size_t i = 0; i < m_transfers.size(); ++i)
|
for (size_t& i: m_transfers_indices[asset_type])
|
||||||
{
|
{
|
||||||
const transfer_details& td = m_transfers[i];
|
const transfer_details& td = m_transfers[i];
|
||||||
if (!is_spent(td, false) && !td.m_frozen && td.is_rct() && td.amount() >= needed_money && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
|
if (!is_spent(td, false) && !td.m_frozen && td.is_rct() && td.amount() >= needed_money && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
|
||||||
@@ -9577,23 +9631,25 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
|
|||||||
// this could be made better by picking one of the outputs to be a small one, since those
|
// this could be made better by picking one of the outputs to be a small one, since those
|
||||||
// are less useful since often below the needed money, so if one can be used in a pair,
|
// are less useful since often below the needed money, so if one can be used in a pair,
|
||||||
// it gets rid of it for the future
|
// it gets rid of it for the future
|
||||||
for (size_t i = 0; i < m_transfers.size(); ++i)
|
for (size_t i = 0; i < m_transfers_indices[asset_type].size(); i++)
|
||||||
{
|
{
|
||||||
const transfer_details& td = m_transfers[i];
|
size_t idx = m_transfers_indices[asset_type][i];
|
||||||
|
const transfer_details& td = m_transfers[idx];
|
||||||
if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && td.is_rct() && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
|
if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && td.is_rct() && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
|
||||||
{
|
{
|
||||||
if (td.amount() > m_ignore_outputs_above || td.amount() < m_ignore_outputs_below)
|
if (td.amount() > m_ignore_outputs_above || td.amount() < m_ignore_outputs_below)
|
||||||
{
|
{
|
||||||
MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]");
|
MDEBUG("Ignoring output " << idx << " of amount " << print_money(td.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
LOG_PRINT_L2("Considering input " << i << ", " << print_money(td.amount()));
|
LOG_PRINT_L2("Considering input " << idx << ", " << print_money(td.amount()));
|
||||||
for (size_t j = i + 1; j < m_transfers.size(); ++j)
|
for (size_t j = i + 1; j < m_transfers_indices[asset_type].size(); ++j)
|
||||||
{
|
{
|
||||||
const transfer_details& td2 = m_transfers[j];
|
size_t idx2 = m_transfers_indices[asset_type][j];
|
||||||
|
const transfer_details& td2 = m_transfers[idx2];
|
||||||
if (td2.amount() > m_ignore_outputs_above || td2.amount() < m_ignore_outputs_below)
|
if (td2.amount() > m_ignore_outputs_above || td2.amount() < m_ignore_outputs_below)
|
||||||
{
|
{
|
||||||
MDEBUG("Ignoring output " << j << " of amount " << print_money(td2.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]");
|
MDEBUG("Ignoring output " << idx2 << " of amount " << print_money(td2.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!is_spent(td2, false) && !td2.m_frozen && !td2.m_key_image_partial && td2.is_rct() && td.amount() + td2.amount() >= needed_money && is_transfer_unlocked(td2) && td2.m_subaddr_index == td.m_subaddr_index)
|
if (!is_spent(td2, false) && !td2.m_frozen && !td2.m_key_image_partial && td2.is_rct() && td.amount() + td2.amount() >= needed_money && is_transfer_unlocked(td2) && td2.m_subaddr_index == td.m_subaddr_index)
|
||||||
@@ -9602,7 +9658,7 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
|
|||||||
// already found. If the same, don't update, and oldest suitable outputs
|
// already found. If the same, don't update, and oldest suitable outputs
|
||||||
// will be used in preference.
|
// will be used in preference.
|
||||||
float relatedness = get_output_relatedness(td, td2);
|
float relatedness = get_output_relatedness(td, td2);
|
||||||
LOG_PRINT_L2(" with input " << j << ", " << print_money(td2.amount()) << ", relatedness " << relatedness);
|
LOG_PRINT_L2(" with input " << idx2 << ", " << print_money(td2.amount()) << ", relatedness " << relatedness);
|
||||||
if (relatedness < current_output_relatdness)
|
if (relatedness < current_output_relatdness)
|
||||||
{
|
{
|
||||||
// reset the current picks with those, and return them directly
|
// reset the current picks with those, and return them directly
|
||||||
@@ -9611,7 +9667,7 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
|
|||||||
picks.clear();
|
picks.clear();
|
||||||
picks.push_back(i);
|
picks.push_back(i);
|
||||||
picks.push_back(j);
|
picks.push_back(j);
|
||||||
LOG_PRINT_L0("we could use " << i << " and " << j);
|
LOG_PRINT_L0("we could use " << idx << " and " << idx2);
|
||||||
if (relatedness == 0.0f)
|
if (relatedness == 0.0f)
|
||||||
return picks;
|
return picks;
|
||||||
current_output_relatdness = relatedness;
|
current_output_relatdness = relatedness;
|
||||||
@@ -9866,7 +9922,11 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(
|
|||||||
// gather all dust and non-dust outputs belonging to specified subaddresses
|
// gather all dust and non-dust outputs belonging to specified subaddresses
|
||||||
size_t num_nondust_outputs = 0;
|
size_t num_nondust_outputs = 0;
|
||||||
size_t num_dust_outputs = 0;
|
size_t num_dust_outputs = 0;
|
||||||
for (size_t i = 0; i < m_transfers.size(); ++i)
|
|
||||||
|
// Verify that we have outputs in our wallet for the correct asset_type
|
||||||
|
THROW_WALLET_EXCEPTION_IF(!m_transfers_indices.count(source_asset), error::wallet_internal_error, "Cannot find outputs with correct asset_type to pay for TX");
|
||||||
|
|
||||||
|
for (size_t& i: m_transfers_indices[source_asset])
|
||||||
{
|
{
|
||||||
const transfer_details& td = m_transfers[i];
|
const transfer_details& td = m_transfers[i];
|
||||||
if (m_ignore_fractional_outputs && td.amount() < fractional_threshold)
|
if (m_ignore_fractional_outputs && td.amount() < fractional_threshold)
|
||||||
@@ -9953,7 +10013,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(
|
|||||||
// this is used to build a tx that's 1 or 2 inputs, and 2 outputs, which
|
// this is used to build a tx that's 1 or 2 inputs, and 2 outputs, which
|
||||||
// will get us a known fee.
|
// will get us a known fee.
|
||||||
uint64_t estimated_fee = estimate_fee(use_per_byte_fee, use_rct, 2, fake_outs_count, 2, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags, base_fee, fee_quantization_mask);
|
uint64_t estimated_fee = estimate_fee(use_per_byte_fee, use_rct, 2, fake_outs_count, 2, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags, base_fee, fee_quantization_mask);
|
||||||
preferred_inputs = pick_preferred_rct_inputs(needed_money + estimated_fee, subaddr_account, subaddr_indices);
|
preferred_inputs = pick_preferred_rct_inputs(needed_money + estimated_fee, subaddr_account, subaddr_indices, source_asset);
|
||||||
if (!preferred_inputs.empty())
|
if (!preferred_inputs.empty())
|
||||||
{
|
{
|
||||||
string s;
|
string s;
|
||||||
@@ -10371,13 +10431,13 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
|
|||||||
{
|
{
|
||||||
std::vector<size_t> unused_transfers_indices;
|
std::vector<size_t> unused_transfers_indices;
|
||||||
std::vector<size_t> unused_dust_indices;
|
std::vector<size_t> unused_dust_indices;
|
||||||
const bool use_rct = use_fork_rules(4, 0);
|
|
||||||
|
|
||||||
// determine threshold for fractional amount
|
// determine threshold for fractional amount
|
||||||
const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE, 0);
|
const bool use_per_byte_fee = true;
|
||||||
const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
|
const bool use_rct = true;
|
||||||
const bool bulletproof_plus = use_fork_rules(get_bulletproof_plus_fork(), 0);
|
const bool bulletproof = true;
|
||||||
const bool clsag = use_fork_rules(get_clsag_fork(), 0);
|
const bool bulletproof_plus = true;
|
||||||
|
const bool clsag = true;
|
||||||
const bool use_view_tags = use_fork_rules(get_view_tag_fork(), 0);
|
const bool use_view_tags = use_fork_rules(get_view_tag_fork(), 0);
|
||||||
const uint64_t base_fee = get_base_fee(priority);
|
const uint64_t base_fee = get_base_fee(priority);
|
||||||
const size_t tx_weight_one_ring = estimate_tx_weight(use_rct, 1, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus, use_view_tags);
|
const size_t tx_weight_one_ring = estimate_tx_weight(use_rct, 1, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus, use_view_tags);
|
||||||
@@ -10391,6 +10451,9 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
|
|||||||
|
|
||||||
std::map<uint32_t, std::pair<std::vector<size_t>, std::vector<size_t>>> unused_transfer_dust_indices_per_subaddr;
|
std::map<uint32_t, std::pair<std::vector<size_t>, std::vector<size_t>>> unused_transfer_dust_indices_per_subaddr;
|
||||||
|
|
||||||
|
// Verify that we have outputs in our wallet for the correct asset_type
|
||||||
|
THROW_WALLET_EXCEPTION_IF(!m_transfers_indices.count(asset_type), error::wallet_internal_error, "Cannot find outputs with correct asset_type to pay for TX");
|
||||||
|
|
||||||
// gather all dust and non-dust outputs of specified subaddress (if any) and below specified threshold (if any)
|
// gather all dust and non-dust outputs of specified subaddress (if any) and below specified threshold (if any)
|
||||||
bool fund_found = false;
|
bool fund_found = false;
|
||||||
for (size_t& i: m_transfers_indices[asset_type])
|
for (size_t& i: m_transfers_indices[asset_type])
|
||||||
@@ -10446,6 +10509,10 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypt
|
|||||||
std::vector<size_t> unused_dust_indices;
|
std::vector<size_t> unused_dust_indices;
|
||||||
const bool use_rct = use_fork_rules(4, 0);
|
const bool use_rct = use_fork_rules(4, 0);
|
||||||
std::string asset_type = "FULM";
|
std::string asset_type = "FULM";
|
||||||
|
|
||||||
|
// Verify that we have outputs in our wallet for the correct asset_type
|
||||||
|
THROW_WALLET_EXCEPTION_IF(!m_transfers_indices.count(asset_type), error::wallet_internal_error, "Cannot find outputs with correct asset_type to pay for TX");
|
||||||
|
|
||||||
// find output with the given key image
|
// find output with the given key image
|
||||||
for (size_t i = 0; i < m_transfers.size(); ++i)
|
for (size_t i = 0; i < m_transfers.size(); ++i)
|
||||||
{
|
{
|
||||||
@@ -10488,11 +10555,11 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||||||
uint64_t upper_transaction_weight_limit = get_upper_transaction_weight_limit();
|
uint64_t upper_transaction_weight_limit = get_upper_transaction_weight_limit();
|
||||||
std::vector<std::vector<get_outs_entry>> outs;
|
std::vector<std::vector<get_outs_entry>> outs;
|
||||||
|
|
||||||
const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE);
|
const bool use_per_byte_fee = true;
|
||||||
const bool use_rct = fake_outs_count > 0 && use_fork_rules(4, 0);
|
const bool use_rct = true;
|
||||||
const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
|
const bool bulletproof = true;
|
||||||
const bool bulletproof_plus = use_fork_rules(get_bulletproof_plus_fork(), 0);
|
const bool bulletproof_plus = true;
|
||||||
const bool clsag = use_fork_rules(get_clsag_fork(), 0);
|
const bool clsag = true;
|
||||||
const rct::RCTConfig rct_config {
|
const rct::RCTConfig rct_config {
|
||||||
rct::RangeProofPaddedBulletproof,
|
rct::RangeProofPaddedBulletproof,
|
||||||
bulletproof_plus ? 4 : 3
|
bulletproof_plus ? 4 : 3
|
||||||
@@ -11413,7 +11480,8 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
crypto::secret_key scalar1;
|
crypto::secret_key scalar1;
|
||||||
crypto::derivation_to_scalar(found_derivation, n, scalar1);
|
crypto::hash uniqueness = cn_fast_hash(reinterpret_cast<void*>(&n), sizeof(size_t));
|
||||||
|
crypto::derivation_to_scalar(found_derivation, uniqueness, scalar1);
|
||||||
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n];
|
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n];
|
||||||
rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus);
|
rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus);
|
||||||
const rct::key C = tx.rct_signatures.outPk[n].mask;
|
const rct::key C = tx.rct_signatures.outPk[n].mask;
|
||||||
@@ -11503,6 +11571,7 @@ bool wallet2::is_out_to_acc(const cryptonote::account_public_address &address, c
|
|||||||
// first run quick check if output has matching view tag, otherwise output should not belong to account
|
// first run quick check if output has matching view tag, otherwise output should not belong to account
|
||||||
if (out_can_be_to_acc(view_tag_opt, derivation, output_index))
|
if (out_can_be_to_acc(view_tag_opt, derivation, output_index))
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
// if view tag match, run slower check deriving output pub key and comparing to expected
|
// if view tag match, run slower check deriving output pub key and comparing to expected
|
||||||
r = crypto::derive_public_key(derivation, output_index, address.m_spend_public_key, derived_out_key);
|
r = crypto::derive_public_key(derivation, output_index, address.m_spend_public_key, derived_out_key);
|
||||||
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key");
|
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key");
|
||||||
@@ -11511,6 +11580,22 @@ bool wallet2::is_out_to_acc(const cryptonote::account_public_address &address, c
|
|||||||
found = true;
|
found = true;
|
||||||
found_derivation = derivation;
|
found_derivation = derivation;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
if (!found) {
|
||||||
|
// SRCG: We KNOW it's a txin_to_key, so it's an RCT transaction, NOT a PROTOCOL transaction.
|
||||||
|
// The uniqueness value will therefore ALWAYS be a hash of the output_index
|
||||||
|
size_t output_index_wrapper = output_index;
|
||||||
|
crypto::hash uniqueness = cn_fast_hash(reinterpret_cast<void*>(&output_index_wrapper), sizeof(size_t));
|
||||||
|
|
||||||
|
// if view tag match, run slower check deriving output pub key and comparing to expected
|
||||||
|
r = crypto::derive_public_key(derivation, uniqueness, address.m_spend_public_key, derived_out_key);
|
||||||
|
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key");
|
||||||
|
if (out_key == derived_out_key)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
found_derivation = derivation;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found && !additional_derivations.empty())
|
if (!found && !additional_derivations.empty())
|
||||||
|
|||||||
@@ -602,7 +602,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<transfer_details> transfer_container;
|
typedef std::vector<transfer_details> transfer_container;
|
||||||
typedef std::map<std::string, std::vector<size_t>> transfer_details_indices;
|
typedef serializable_unordered_map<std::string, std::vector<size_t>> transfer_details_indices;
|
||||||
typedef serializable_unordered_multimap<crypto::hash, payment_details> payment_container;
|
typedef serializable_unordered_multimap<crypto::hash, payment_details> payment_container;
|
||||||
|
|
||||||
struct multisig_sig
|
struct multisig_sig
|
||||||
@@ -1265,6 +1265,7 @@ private:
|
|||||||
VERSION_FIELD(1)
|
VERSION_FIELD(1)
|
||||||
FIELD(m_blockchain)
|
FIELD(m_blockchain)
|
||||||
FIELD(m_transfers)
|
FIELD(m_transfers)
|
||||||
|
FIELD(m_transfers_indices)
|
||||||
FIELD(m_account_public_address)
|
FIELD(m_account_public_address)
|
||||||
FIELD(m_key_images)
|
FIELD(m_key_images)
|
||||||
FIELD(m_unconfirmed_txs)
|
FIELD(m_unconfirmed_txs)
|
||||||
@@ -1733,7 +1734,7 @@ private:
|
|||||||
std::vector<uint64_t> get_unspent_amounts_vector(bool strict);
|
std::vector<uint64_t> get_unspent_amounts_vector(bool strict);
|
||||||
uint64_t get_dynamic_base_fee_estimate();
|
uint64_t get_dynamic_base_fee_estimate();
|
||||||
float get_output_relatedness(const transfer_details &td0, const transfer_details &td1) const;
|
float get_output_relatedness(const transfer_details &td0, const transfer_details &td1) const;
|
||||||
std::vector<size_t> pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices);
|
std::vector<size_t> pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices, const std::string& asset_type);
|
||||||
void set_spent(size_t idx, uint64_t height);
|
void set_spent(size_t idx, uint64_t height);
|
||||||
void set_unspent(size_t idx);
|
void set_unspent(size_t idx);
|
||||||
bool is_spent(const transfer_details &td, bool strict = true) const;
|
bool is_spent(const transfer_details &td, bool strict = true) const;
|
||||||
|
|||||||
Reference in New Issue
Block a user