the premine now works and is spendable; transfers are now working correctly
This commit is contained in:
@@ -2345,21 +2345,9 @@ void Blockchain::get_output_key_mask_unlocked(const uint64_t& amount, const uint
|
||||
//------------------------------------------------------------------
|
||||
bool Blockchain::get_output_distribution(uint64_t amount, std::string asset_type, uint64_t from_height, uint64_t to_height, uint64_t &start_height, std::vector<uint64_t> &distribution, uint64_t &base, uint64_t &num_spendable_global_outs) const
|
||||
{
|
||||
// rct outputs don't exist before v4
|
||||
if (amount == 0)
|
||||
{
|
||||
switch (m_nettype)
|
||||
{
|
||||
case STAGENET: start_height = stagenet_hard_forks[3].height; break;
|
||||
case TESTNET: start_height = testnet_hard_forks[3].height; break;
|
||||
case MAINNET: start_height = mainnet_hard_forks[3].height; break;
|
||||
case FAKECHAIN: start_height = 0; break;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
start_height = 0;
|
||||
start_height = 0;
|
||||
base = 0;
|
||||
num_spendable_global_outs = 0;
|
||||
|
||||
if (to_height > 0 && to_height < from_height)
|
||||
return false;
|
||||
@@ -3451,7 +3439,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
||||
}
|
||||
|
||||
// min/max tx version based on HF, and we accept v1 txes if having a non mixable
|
||||
const size_t max_tx_version = 2;
|
||||
const size_t max_tx_version = (hf_version < HF_VERSION_SLIPPAGE_YIELD) ? 2 : CURRENT_TRANSACTION_VERSION;
|
||||
if (tx.version > max_tx_version)
|
||||
{
|
||||
MERROR_VER("transaction version " << (unsigned)tx.version << " is higher than max accepted version " << max_tx_version);
|
||||
|
||||
@@ -836,7 +836,7 @@ namespace cryptonote
|
||||
bad_semantics_txes_lock.unlock();
|
||||
|
||||
uint8_t version = m_blockchain_storage.get_current_hard_fork_version();
|
||||
const size_t max_tx_version = version == 1 ? 1 : 2;
|
||||
const size_t max_tx_version = (version < HF_VERSION_SLIPPAGE_YIELD) ? 2 : CURRENT_TRANSACTION_VERSION;
|
||||
if (tx.version == 0 || tx.version > max_tx_version)
|
||||
{
|
||||
// v2 is the latest one we know
|
||||
|
||||
@@ -226,7 +226,7 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, bool shuffle_outs, bool use_view_tags)
|
||||
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const uint8_t hf_version, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, bool shuffle_outs, bool use_view_tags)
|
||||
{
|
||||
hw::device &hwdev = sender_account_keys.get_device();
|
||||
|
||||
@@ -240,7 +240,11 @@ namespace cryptonote
|
||||
tx.set_null();
|
||||
amount_keys.clear();
|
||||
|
||||
tx.version = rct ? 2 : 1;
|
||||
if (hf_version >= HF_VERSION_SLIPPAGE_YIELD) {
|
||||
tx.version = 3;
|
||||
} else {
|
||||
tx.version = 2;
|
||||
}
|
||||
tx.unlock_time = unlock_time;
|
||||
|
||||
tx.extra = extra;
|
||||
@@ -367,6 +371,7 @@ namespace cryptonote
|
||||
txin_to_key input_to_key;
|
||||
input_to_key.amount = src_entr.amount;
|
||||
input_to_key.k_image = img;
|
||||
input_to_key.asset_type = src_entr.asset_type;
|
||||
|
||||
//fill outputs array and use relative offsets
|
||||
for(const tx_source_entry::output_entry& out_entry: src_entr.outputs)
|
||||
@@ -629,7 +634,7 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, bool use_view_tags)
|
||||
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const uint8_t hf_version, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, bool use_view_tags)
|
||||
{
|
||||
hw::device &hwdev = sender_account_keys.get_device();
|
||||
hwdev.open_tx(tx_key);
|
||||
@@ -650,7 +655,7 @@ namespace cryptonote
|
||||
}
|
||||
|
||||
bool shuffle_outs = true;
|
||||
bool r = construct_tx_with_tx_key(sender_account_keys, subaddresses, sources, destinations, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys, rct, rct_config, shuffle_outs, use_view_tags);
|
||||
bool r = construct_tx_with_tx_key(sender_account_keys, subaddresses, sources, destinations, hf_version, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys, rct, rct_config, shuffle_outs, use_view_tags);
|
||||
hwdev.close_tx();
|
||||
return r;
|
||||
} catch(...) {
|
||||
@@ -659,14 +664,14 @@ namespace cryptonote
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time)
|
||||
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const uint8_t hf_version, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time)
|
||||
{
|
||||
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
|
||||
subaddresses[sender_account_keys.m_account_address.m_spend_public_key] = {0,0};
|
||||
crypto::secret_key tx_key;
|
||||
std::vector<crypto::secret_key> additional_tx_keys;
|
||||
std::vector<tx_destination_entry> destinations_copy = destinations;
|
||||
return construct_tx_and_get_tx_key(sender_account_keys, subaddresses, sources, destinations_copy, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, { rct::RangeProofBorromean, 0});
|
||||
return construct_tx_and_get_tx_key(sender_account_keys, subaddresses, sources, destinations_copy, hf_version, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, { rct::RangeProofBorromean, 0});
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool generate_genesis_block(
|
||||
|
||||
@@ -125,9 +125,9 @@ namespace cryptonote
|
||||
|
||||
//---------------------------------------------------------------
|
||||
crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const boost::optional<cryptonote::account_public_address>& change_addr);
|
||||
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry> &sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time);
|
||||
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, bool shuffle_outs = true, bool use_view_tags = false);
|
||||
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, bool use_view_tags = false);
|
||||
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry> &sources, const std::vector<tx_destination_entry>& destinations, const uint8_t hf_version, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time);
|
||||
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const uint8_t hf_version, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, bool shuffle_outs = true, bool use_view_tags = false);
|
||||
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const uint8_t hf_version, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, bool use_view_tags = false);
|
||||
bool generate_output_ephemeral_keys(const size_t tx_version, const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key,
|
||||
const cryptonote::tx_destination_entry &dst_entr, const boost::optional<cryptonote::account_public_address> &change_addr, const size_t output_index,
|
||||
const bool &need_additional_txkeys, const std::vector<crypto::secret_key> &additional_tx_keys,
|
||||
|
||||
@@ -1275,12 +1275,15 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
|
||||
if (req.do_sanity_checks && !cryptonote::tx_sanity_check(tx_blob, m_core.get_blockchain_storage().get_num_mature_outputs(0)))
|
||||
{
|
||||
res.status = "Failed";
|
||||
res.reason = "Sanity check failed";
|
||||
res.sanity_check_failed = true;
|
||||
return true;
|
||||
uint64_t output_count = m_core.get_blockchain_storage().get_num_mature_outputs(req.source_asset_type);
|
||||
bool ok = cryptonote::tx_sanity_check(tx_blob, output_count);
|
||||
if (!ok) {
|
||||
if (req.do_sanity_checks && !cryptonote::tx_sanity_check(tx_blob, output_count)) {
|
||||
res.status = "Failed";
|
||||
res.reason = "Sanity check failed";
|
||||
res.sanity_check_failed = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
res.sanity_check_failed = false;
|
||||
|
||||
@@ -3359,7 +3362,7 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
|
||||
res.distributions.push_back({std::move(*data), amount, "", req.binary, req.compress});
|
||||
res.distributions.push_back({std::move(*data), amount, req.rct_asset_type, req.binary, req.compress});
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
|
||||
@@ -602,12 +602,14 @@ namespace cryptonote
|
||||
struct request_t: public rpc_access_request_base
|
||||
{
|
||||
std::string tx_as_hex;
|
||||
std::string source_asset_type;
|
||||
bool do_not_relay;
|
||||
bool do_sanity_checks;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_PARENT(rpc_access_request_base);
|
||||
KV_SERIALIZE(tx_as_hex)
|
||||
KV_SERIALIZE(source_asset_type)
|
||||
KV_SERIALIZE_OPT(do_not_relay, false)
|
||||
KV_SERIALIZE_OPT(do_sanity_checks, true)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
@@ -2493,6 +2495,7 @@ namespace cryptonote
|
||||
uint64_t from_height;
|
||||
uint64_t to_height;
|
||||
std::string rct_asset_type;
|
||||
|
||||
bool cumulative;
|
||||
bool binary;
|
||||
bool compress;
|
||||
|
||||
@@ -7219,6 +7219,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, const std::vector<std::string> &args_)
|
||||
{
|
||||
std::string asset_type = (args_.size() > 1) ? args_.back() : "FULM";
|
||||
auto print_usage = [this, account, below]()
|
||||
{
|
||||
if (below)
|
||||
@@ -7406,7 +7407,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co
|
||||
try
|
||||
{
|
||||
// figure out what tx will be necessary
|
||||
auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, outputs, fake_outs_count, unlock_block /* unlock_time */, priority, extra, account, subaddr_indices);
|
||||
auto ptx_vector = m_wallet->create_transactions_all(below, asset_type, info.address, info.is_subaddress, outputs, fake_outs_count, unlock_block /* unlock_time */, priority, extra, account, subaddr_indices);
|
||||
|
||||
if (ptx_vector.empty())
|
||||
{
|
||||
|
||||
+86
-28
@@ -3790,7 +3790,7 @@ bool wallet2::refresh(bool trusted_daemon, uint64_t & blocks_fetched, bool& rece
|
||||
return ok;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::get_rct_distribution(uint64_t &start_height, std::vector<uint64_t> &distribution)
|
||||
bool wallet2::get_rct_distribution(const std::string &rct_asset_type, uint64_t &start_height, std::vector<uint64_t> &distribution)
|
||||
{
|
||||
MDEBUG("Requesting rct distribution");
|
||||
|
||||
@@ -3801,6 +3801,7 @@ bool wallet2::get_rct_distribution(uint64_t &start_height, std::vector<uint64_t>
|
||||
req.cumulative = false;
|
||||
req.binary = true;
|
||||
req.compress = true;
|
||||
req.rct_asset_type = rct_asset_type;
|
||||
|
||||
bool r;
|
||||
try
|
||||
@@ -6606,6 +6607,11 @@ void wallet2::commit_tx(pending_tx& ptx)
|
||||
{
|
||||
using namespace cryptonote;
|
||||
|
||||
std::string source_asset;
|
||||
std::string dest_asset;
|
||||
bool r = cryptonote::get_tx_asset_types(ptx.tx, ptx.tx.hash, source_asset, dest_asset, false);
|
||||
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "failed to get TX asset types");
|
||||
|
||||
if(m_light_wallet)
|
||||
{
|
||||
cryptonote::COMMAND_RPC_SUBMIT_RAW_TX::request oreq;
|
||||
@@ -6628,6 +6634,7 @@ void wallet2::commit_tx(pending_tx& ptx)
|
||||
req.tx_as_hex = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(ptx.tx));
|
||||
req.do_not_relay = false;
|
||||
req.do_sanity_checks = true;
|
||||
req.source_asset_type = source_asset;
|
||||
COMMAND_RPC_SEND_RAW_TX::response daemon_send_resp;
|
||||
|
||||
{
|
||||
@@ -6871,7 +6878,12 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin
|
||||
rct::RCTConfig rct_config = sd.rct_config;
|
||||
crypto::secret_key tx_key;
|
||||
std::vector<crypto::secret_key> additional_tx_keys;
|
||||
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sd.sources, sd.splitted_dsts, sd.change_dts.addr, sd.extra, ptx.tx, sd.unlock_time, tx_key, additional_tx_keys, sd.use_rct, rct_config, sd.use_view_tags);
|
||||
|
||||
uint32_t hf_version = get_current_hard_fork();
|
||||
// Get the circulating supply data
|
||||
std::vector<std::pair<std::string, std::string>> circ_amounts;
|
||||
THROW_WALLET_EXCEPTION_IF(!get_circulating_supply(circ_amounts), error::wallet_internal_error, "Failed to get circulating supply");
|
||||
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sd.sources, sd.splitted_dsts, hf_version, sd.change_dts.addr, sd.extra, ptx.tx, sd.unlock_time, tx_key, additional_tx_keys, sd.use_rct, rct_config, sd.use_view_tags);
|
||||
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype);
|
||||
// we don't test tx size, because we don't know the current limit, due to not having a blockchain,
|
||||
// and it's a bit pointless to fail there anyway, since it'd be a (good) guess only. We sign anyway,
|
||||
@@ -8276,11 +8288,9 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
LOG_PRINT_L2("fake_outputs_count: " << fake_outputs_count);
|
||||
outs.clear();
|
||||
|
||||
if(m_light_wallet && fake_outputs_count > 0) {
|
||||
light_wallet_get_outs(outs, selected_transfers, fake_outputs_count);
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanity checks
|
||||
THROW_WALLET_EXCEPTION_IF(selected_transfers.empty(), error::wallet_internal_error, "No selected_transfers provided");
|
||||
|
||||
if (fake_outputs_count > 0)
|
||||
{
|
||||
uint64_t segregation_fork_height = get_segregation_fork_height();
|
||||
@@ -8295,15 +8305,19 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
uint64_t rct_start_height;
|
||||
bool has_rct = false;
|
||||
uint64_t max_rct_index = 0;
|
||||
for (size_t idx: selected_transfers)
|
||||
std::string rct_asset_type = m_transfers[selected_transfers[0]].asset_type;
|
||||
for (size_t idx: selected_transfers) {
|
||||
THROW_WALLET_EXCEPTION_IF(m_transfers.size() < idx, error::wallet_internal_error, "requesting too high an index from m_transfers");
|
||||
THROW_WALLET_EXCEPTION_IF(m_transfers[idx].asset_type != rct_asset_type, error::wallet_internal_error, "selected_transfer entry has wrong asset_type");
|
||||
if (m_transfers[idx].is_rct())
|
||||
{
|
||||
has_rct = true;
|
||||
max_rct_index = std::max(max_rct_index, m_transfers[idx].m_global_output_index);
|
||||
max_rct_index = std::max(max_rct_index, m_transfers[idx].m_asset_type_output_index);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (has_rct && rct_offsets.empty()) {
|
||||
THROW_WALLET_EXCEPTION_IF(!get_rct_distribution(rct_start_height, rct_offsets),
|
||||
THROW_WALLET_EXCEPTION_IF(!get_rct_distribution(rct_asset_type, rct_start_height, rct_offsets),
|
||||
error::get_output_distribution, "Could not obtain output distribution.");
|
||||
}
|
||||
|
||||
@@ -9015,8 +9029,14 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
|
||||
|
||||
crypto::secret_key tx_key;
|
||||
std::vector<crypto::secret_key> additional_tx_keys;
|
||||
// Get the circulating supply data
|
||||
std::vector<std::pair<std::string, std::string>> circ_amounts;
|
||||
THROW_WALLET_EXCEPTION_IF(!get_circulating_supply(circ_amounts), error::wallet_internal_error, "Failed to get circulating supply");
|
||||
|
||||
uint32_t hf_version = get_current_hard_fork();
|
||||
|
||||
LOG_PRINT_L2("constructing tx");
|
||||
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, {}, use_view_tags);
|
||||
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, hf_version, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, {}, use_view_tags);
|
||||
LOG_PRINT_L2("constructed tx, r="<<r);
|
||||
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_nettype);
|
||||
THROW_WALLET_EXCEPTION_IF(upper_transaction_weight_limit <= get_transaction_weight(tx), error::tx_too_big, tx, upper_transaction_weight_limit);
|
||||
@@ -9064,9 +9084,20 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
|
||||
LOG_PRINT_L2("transfer_selected done");
|
||||
}
|
||||
|
||||
void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry> dsts, const std::vector<size_t>& selected_transfers, size_t fake_outputs_count,
|
||||
std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, std::unordered_set<crypto::public_key> &valid_public_keys_cache,
|
||||
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx &ptx, const rct::RCTConfig &rct_config, bool use_view_tags)
|
||||
void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry> dsts,
|
||||
const std::vector<size_t>& selected_transfers,
|
||||
size_t fake_outputs_count,
|
||||
std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs,
|
||||
std::unordered_set<crypto::public_key> &valid_public_keys_cache,
|
||||
uint64_t unlock_time,
|
||||
uint64_t fee,
|
||||
const std::vector<uint8_t>& extra,
|
||||
cryptonote::transaction& tx, pending_tx &ptx,
|
||||
const rct::RCTConfig &rct_config,
|
||||
bool use_view_tags,
|
||||
const std::string& source_asset,
|
||||
const std::string& dest_asset,
|
||||
const oracle::pricing_record& pr)
|
||||
{
|
||||
using namespace cryptonote;
|
||||
// throw if attempting a transaction with no destinations
|
||||
@@ -9176,6 +9207,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
|
||||
const transfer_details& td = m_transfers[idx];
|
||||
src.amount = td.amount();
|
||||
src.rct = td.is_rct();
|
||||
src.asset_type = td.asset_type;
|
||||
//paste mixin transaction
|
||||
|
||||
THROW_WALLET_EXCEPTION_IF(outs.size() < out_index + 1 , error::wallet_internal_error, "outs.size() < out_index + 1");
|
||||
@@ -9281,8 +9313,12 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
|
||||
);
|
||||
}
|
||||
else {
|
||||
uint32_t hf_version = get_current_hard_fork();
|
||||
// Get the circulating supply data
|
||||
std::vector<std::pair<std::string, std::string>> circ_amounts;
|
||||
THROW_WALLET_EXCEPTION_IF(!get_circulating_supply(circ_amounts), error::wallet_internal_error, "Failed to get circulating supply");
|
||||
// make a normal tx
|
||||
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, true, rct_config, use_view_tags);
|
||||
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, hf_version, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, true, rct_config, use_view_tags);
|
||||
LOG_PRINT_L2("constructed tx, r="<<r);
|
||||
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, dsts, unlock_time, m_nettype);
|
||||
}
|
||||
@@ -10119,7 +10155,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(
|
||||
const bool bulletproof_plus = true;
|
||||
const bool clsag = true;
|
||||
const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 4 };
|
||||
const bool use_view_tags = true;
|
||||
const bool use_view_tags = use_fork_rules(get_view_tag_fork(), 0);
|
||||
std::unordered_set<crypto::public_key> valid_public_keys_cache;
|
||||
|
||||
const uint64_t base_fee = get_base_fee(priority);
|
||||
@@ -10128,6 +10164,23 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(
|
||||
// throw if attempting a transaction with no destinations
|
||||
THROW_WALLET_EXCEPTION_IF(dsts.empty(), error::zero_destination);
|
||||
|
||||
// get tx type
|
||||
tt tx_type;
|
||||
THROW_WALLET_EXCEPTION_IF(!get_tx_type(source_asset, dest_asset, tx_type), error::wallet_internal_error, "invalid tx type");
|
||||
const uint64_t current_height = get_blockchain_current_height()-1;
|
||||
uint32_t hf_version = get_current_hard_fork();
|
||||
//const auto specific_transfers = m_transfers.at(source_asset);
|
||||
oracle::pricing_record pricing_record;
|
||||
|
||||
if (source_asset != dest_asset) {
|
||||
bool b = get_pricing_record(pricing_record, current_height);
|
||||
THROW_WALLET_EXCEPTION_IF(!b, error::wallet_internal_error, "Failed to get pricing record");
|
||||
}
|
||||
|
||||
// Get the circulating supply data
|
||||
std::vector<std::pair<std::string, std::string>> circ_amounts;
|
||||
THROW_WALLET_EXCEPTION_IF(!get_circulating_supply(circ_amounts), error::wallet_internal_error, "Failed to get circulating supply");
|
||||
|
||||
// calculate total amount being sent to all destinations
|
||||
// throw if total amount overflows uint64_t
|
||||
needed_money = 0;
|
||||
@@ -10495,7 +10548,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(
|
||||
tx.selected_transfers.size() << " inputs");
|
||||
if (use_rct)
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
test_tx, test_ptx, rct_config, use_view_tags);
|
||||
test_tx, test_ptx, rct_config, use_view_tags, source_asset, dest_asset, pricing_record);
|
||||
else
|
||||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags);
|
||||
@@ -10520,7 +10573,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(
|
||||
while (needed_fee > test_ptx.fee) {
|
||||
if (use_rct)
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
test_tx, test_ptx, rct_config, use_view_tags);
|
||||
test_tx, test_ptx, rct_config, use_view_tags, source_asset, dest_asset, pricing_record);
|
||||
else
|
||||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags);
|
||||
@@ -10595,7 +10648,10 @@ skip_tx:
|
||||
test_tx, /* OUT cryptonote::transaction& tx, */
|
||||
test_ptx, /* OUT cryptonote::transaction& tx, */
|
||||
rct_config,
|
||||
use_view_tags); /* const bool use_view_tags */
|
||||
use_view_tags, /* const bool use_view_tags */
|
||||
source_asset,
|
||||
dest_asset,
|
||||
pricing_record);
|
||||
} else {
|
||||
transfer_selected(tx.dsts,
|
||||
tx.selected_transfers,
|
||||
@@ -10701,7 +10757,7 @@ bool wallet2::sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, s
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices)
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below, const std::string &asset_type, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices)
|
||||
{
|
||||
std::vector<size_t> unused_transfers_indices;
|
||||
std::vector<size_t> unused_dust_indices;
|
||||
@@ -10771,7 +10827,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
|
||||
}
|
||||
}
|
||||
|
||||
return create_transactions_from(address, is_subaddress, outputs, unused_transfers_indices, unused_dust_indices, fake_outs_count, unlock_time, priority, extra);
|
||||
return create_transactions_from(address, asset_type, is_subaddress, outputs, unused_transfers_indices, unused_dust_indices, fake_outs_count, unlock_time, priority, extra);
|
||||
}
|
||||
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypto::key_image &ki, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra)
|
||||
@@ -10779,12 +10835,14 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypt
|
||||
std::vector<size_t> unused_transfers_indices;
|
||||
std::vector<size_t> unused_dust_indices;
|
||||
const bool use_rct = use_fork_rules(4, 0);
|
||||
std::string asset_type = "FULM";
|
||||
// find output with the given key image
|
||||
for (size_t i = 0; i < m_transfers.size(); ++i)
|
||||
{
|
||||
const transfer_details& td = m_transfers[i];
|
||||
if (td.m_key_image_known && td.m_key_image == ki && !is_spent(td, false) && !td.m_frozen && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td))
|
||||
{
|
||||
asset_type = td.asset_type;
|
||||
if (td.is_rct() || is_valid_decomposed_amount(td.amount()))
|
||||
unused_transfers_indices.push_back(i);
|
||||
else
|
||||
@@ -10792,10 +10850,10 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypt
|
||||
break;
|
||||
}
|
||||
}
|
||||
return create_transactions_from(address, is_subaddress, outputs, unused_transfers_indices, unused_dust_indices, fake_outs_count, unlock_time, priority, extra);
|
||||
return create_transactions_from(address, asset_type, is_subaddress, outputs, unused_transfers_indices, unused_dust_indices, fake_outs_count, unlock_time, priority, extra);
|
||||
}
|
||||
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra)
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const cryptonote::account_public_address &address, const std::string &asset_type, bool is_subaddress, const size_t outputs, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra)
|
||||
{
|
||||
//ensure device is let in NONE mode in any case
|
||||
hw::device &hwdev = m_account.get_device();
|
||||
@@ -10905,7 +10963,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
||||
tx.selected_transfers.size() << " outputs");
|
||||
if (use_rct)
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
test_tx, test_ptx, rct_config, use_view_tags);
|
||||
test_tx, test_ptx, rct_config, use_view_tags, asset_type, asset_type, oracle::pricing_record());
|
||||
else
|
||||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags);
|
||||
@@ -10942,7 +11000,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
||||
}
|
||||
if (use_rct)
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
test_tx, test_ptx, rct_config, use_view_tags);
|
||||
test_tx, test_ptx, rct_config, use_view_tags, asset_type, asset_type, oracle::pricing_record());
|
||||
else
|
||||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags);
|
||||
@@ -10981,7 +11039,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
||||
pending_tx test_ptx;
|
||||
if (use_rct) {
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, valid_public_keys_cache, unlock_time, tx.needed_fee, extra,
|
||||
test_tx, test_ptx, rct_config, use_view_tags);
|
||||
test_tx, test_ptx, rct_config, use_view_tags, asset_type, asset_type, oracle::pricing_record());
|
||||
} else {
|
||||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, valid_public_keys_cache, unlock_time, tx.needed_fee, extra,
|
||||
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags);
|
||||
@@ -11295,7 +11353,7 @@ std::vector<wallet2::pending_tx> wallet2::create_unmixable_sweep_transactions()
|
||||
unmixable_transfer_outputs.push_back(n);
|
||||
}
|
||||
|
||||
return create_transactions_from(m_account_public_address, false, 1, unmixable_transfer_outputs, unmixable_dust_outputs, 0 /*fake_outs_count */, 0 /* unlock_time */, 1 /*priority */, std::vector<uint8_t>());
|
||||
return create_transactions_from(m_account_public_address, "FULM", false, 1, unmixable_transfer_outputs, unmixable_dust_outputs, 0 /*fake_outs_count */, 0 /* unlock_time */, 1 /*priority */, std::vector<uint8_t>());
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::discard_unmixable_outputs()
|
||||
|
||||
@@ -1064,7 +1064,10 @@ private:
|
||||
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, T destination_split_strategy, const tx_dust_policy& dust_policy, cryptonote::transaction& tx, pending_tx &ptx, const bool use_view_tags);
|
||||
void transfer_selected_rct(std::vector<cryptonote::tx_destination_entry> dsts, const std::vector<size_t>& selected_transfers, size_t fake_outputs_count,
|
||||
std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, std::unordered_set<crypto::public_key> &valid_public_keys_cache,
|
||||
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx &ptx, const rct::RCTConfig &rct_config, const bool use_view_tags);
|
||||
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx &ptx, const rct::RCTConfig &rct_config, const bool use_view_tags,
|
||||
const std::string& source_asset,
|
||||
const std::string& dest_asset,
|
||||
const oracle::pricing_record& pr);
|
||||
|
||||
void commit_tx(pending_tx& ptx_vector);
|
||||
void commit_tx(std::vector<pending_tx>& ptx_vector);
|
||||
@@ -1087,9 +1090,9 @@ private:
|
||||
bool load_tx(const std::string &signed_filename, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set&)> accept_func = NULL);
|
||||
bool parse_tx_from_str(const std::string &signed_tx_st, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set &)> accept_func);
|
||||
std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const std::string& source_asset, const std::string& dest_asset, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices); // pass subaddr_indices by value on purpose
|
||||
std::vector<wallet2::pending_tx> create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices);
|
||||
std::vector<wallet2::pending_tx> create_transactions_all(uint64_t below, const std::string &asset_type, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices);
|
||||
std::vector<wallet2::pending_tx> create_transactions_single(const crypto::key_image &ki, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra);
|
||||
std::vector<wallet2::pending_tx> create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra);
|
||||
std::vector<wallet2::pending_tx> create_transactions_from(const cryptonote::account_public_address &address, const std::string &asset_type, bool is_subaddress, const size_t outputs, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra);
|
||||
bool sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, std::vector<cryptonote::tx_destination_entry> dsts) const;
|
||||
void cold_tx_aux_import(const std::vector<pending_tx>& ptx, const std::vector<std::string>& tx_device_aux);
|
||||
void cold_sign_tx(const std::vector<pending_tx>& ptx_vector, signed_tx_set &exported_txs, std::vector<cryptonote::address_parse_info> &dsts_info, std::vector<std::string> & tx_device_aux);
|
||||
@@ -1770,7 +1773,7 @@ private:
|
||||
void register_devices();
|
||||
hw::device& lookup_device(const std::string & device_descriptor);
|
||||
|
||||
bool get_rct_distribution(uint64_t &start_height, std::vector<uint64_t> &distribution);
|
||||
bool get_rct_distribution(const std::string &rct_asset_type, uint64_t &start_height, std::vector<uint64_t> &distribution);
|
||||
|
||||
uint64_t get_segregation_fork_height() const;
|
||||
|
||||
|
||||
@@ -1565,6 +1565,7 @@ namespace tools
|
||||
destination.push_back(wallet_rpc::transfer_destination());
|
||||
destination.back().amount = 0;
|
||||
destination.back().address = req.address;
|
||||
std::string asset_type = req.asset_type.empty() ? "FULM" : req.asset_type;
|
||||
if (!validate_transfer(destination, req.payment_id, dsts, extra, true, er))
|
||||
{
|
||||
return false;
|
||||
@@ -1592,7 +1593,7 @@ namespace tools
|
||||
{
|
||||
uint64_t mixin = m_wallet->adjust_mixin(req.ring_size ? req.ring_size - 1 : 0);
|
||||
uint32_t priority = m_wallet->adjust_priority(req.priority);
|
||||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_all(req.below_amount, dsts[0].addr, dsts[0].is_subaddress, req.outputs, mixin, req.unlock_time, priority, extra, req.account_index, subaddr_indices);
|
||||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_all(req.below_amount, asset_type, dsts[0].addr, dsts[0].is_subaddress, req.outputs, mixin, req.unlock_time, priority, extra, req.account_index, subaddr_indices);
|
||||
|
||||
return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.weight_list, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
|
||||
res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, res.spent_key_images_list, er);
|
||||
|
||||
@@ -885,6 +885,7 @@ namespace wallet_rpc
|
||||
bool do_not_relay;
|
||||
bool get_tx_hex;
|
||||
bool get_tx_metadata;
|
||||
std::string asset_type;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(address)
|
||||
@@ -901,6 +902,7 @@ namespace wallet_rpc
|
||||
KV_SERIALIZE_OPT(do_not_relay, false)
|
||||
KV_SERIALIZE_OPT(get_tx_hex, false)
|
||||
KV_SERIALIZE_OPT(get_tx_metadata, false)
|
||||
KV_SERIALIZE(asset_type)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<request_t> request;
|
||||
|
||||
Reference in New Issue
Block a user