port get_tx_key/check_tx_key to rct
This commit is contained in:
parent
e06faefde4
commit
e81a2b2cfa
@ -453,12 +453,13 @@ namespace cryptonote
|
|||||||
return encrypt_payment_id(payment_id, public_key, secret_key);
|
return encrypt_payment_id(payment_id, public_key, secret_key);
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct)
|
bool construct_tx_and_get_tx_keys(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &amount_keys, bool rct)
|
||||||
{
|
{
|
||||||
tx.vin.clear();
|
tx.vin.clear();
|
||||||
tx.vout.clear();
|
tx.vout.clear();
|
||||||
tx.signatures.clear();
|
tx.signatures.clear();
|
||||||
tx.rct_signatures = rct::rctSig();
|
tx.rct_signatures = rct::rctSig();
|
||||||
|
amount_keys.clear();
|
||||||
|
|
||||||
tx.version = rct ? 2 : 1;
|
tx.version = rct ? 2 : 1;
|
||||||
tx.unlock_time = unlock_time;
|
tx.unlock_time = unlock_time;
|
||||||
@ -721,10 +722,18 @@ namespace cryptonote
|
|||||||
|
|
||||||
crypto::hash tx_prefix_hash;
|
crypto::hash tx_prefix_hash;
|
||||||
get_transaction_prefix_hash(tx, tx_prefix_hash);
|
get_transaction_prefix_hash(tx, tx_prefix_hash);
|
||||||
|
rct::ctkeyV outSk;
|
||||||
if (use_simple_rct)
|
if (use_simple_rct)
|
||||||
tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, index);
|
tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, index, outSk);
|
||||||
else
|
else
|
||||||
tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, sources[0].real_output); // same index assumption
|
tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, sources[0].real_output, outSk); // same index assumption
|
||||||
|
|
||||||
|
CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout");
|
||||||
|
for (size_t i = 0; i < tx.vout.size(); ++i)
|
||||||
|
{
|
||||||
|
amount_keys.push_back(rct::rct2sk(rct::d2h(shuffled_dsts[i].amount)));
|
||||||
|
amount_keys.push_back(rct::rct2sk(outSk[i].mask));
|
||||||
|
}
|
||||||
|
|
||||||
LOG_PRINT2("construct_tx.log", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL, LOG_LEVEL_3);
|
LOG_PRINT2("construct_tx.log", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL, LOG_LEVEL_3);
|
||||||
}
|
}
|
||||||
@ -735,7 +744,8 @@ namespace cryptonote
|
|||||||
bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time)
|
bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time)
|
||||||
{
|
{
|
||||||
crypto::secret_key tx_key;
|
crypto::secret_key tx_key;
|
||||||
return construct_tx_and_get_tx_key(sender_account_keys, sources, destinations, extra, tx, unlock_time, tx_key);
|
std::vector<crypto::secret_key> amount_keys;
|
||||||
|
return construct_tx_and_get_tx_keys(sender_account_keys, sources, destinations, extra, tx, unlock_time, tx_key, amount_keys);
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
bool get_inputs_money_amount(const transaction& tx, uint64_t& money)
|
bool get_inputs_money_amount(const transaction& tx, uint64_t& money)
|
||||||
|
@ -74,7 +74,7 @@ namespace cryptonote
|
|||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time);
|
bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time);
|
||||||
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &txkey, bool rct = false);
|
bool construct_tx_and_get_tx_keys(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &amount_keys, bool rct = false);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool find_tx_extra_field_by_type(const std::vector<tx_extra_field>& tx_extra_fields, T& field)
|
bool find_tx_extra_field_by_type(const std::vector<tx_extra_field>& tx_extra_fields, T& field)
|
||||||
|
@ -535,7 +535,7 @@ namespace rct {
|
|||||||
// must know the destination private key to find the correct amount, else will return a random number
|
// must know the destination private key to find the correct amount, else will return a random number
|
||||||
// Note: For txn fees, the last index in the amounts vector should contain that
|
// Note: For txn fees, the last index in the amounts vector should contain that
|
||||||
// Thus the amounts vector will be "one" longer than the destinations vectort
|
// Thus the amounts vector will be "one" longer than the destinations vectort
|
||||||
rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & amounts, const ctkeyM &mixRing, unsigned int index) {
|
rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & amounts, const ctkeyM &mixRing, unsigned int index, ctkeyV &outSk) {
|
||||||
CHECK_AND_ASSERT_THROW_MES(amounts.size() == destinations.size() || amounts.size() == destinations.size() + 1, "Different number of amounts/destinations");
|
CHECK_AND_ASSERT_THROW_MES(amounts.size() == destinations.size() || amounts.size() == destinations.size() + 1, "Different number of amounts/destinations");
|
||||||
CHECK_AND_ASSERT_THROW_MES(index < mixRing.size(), "Bad index into mixRing");
|
CHECK_AND_ASSERT_THROW_MES(index < mixRing.size(), "Bad index into mixRing");
|
||||||
for (size_t n = 0; n < mixRing.size(); ++n) {
|
for (size_t n = 0; n < mixRing.size(); ++n) {
|
||||||
@ -550,7 +550,7 @@ namespace rct {
|
|||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
keyV masks(destinations.size()); //sk mask..
|
keyV masks(destinations.size()); //sk mask..
|
||||||
ctkeyV outSk(destinations.size());
|
outSk.resize(destinations.size());
|
||||||
for (i = 0; i < destinations.size(); i++) {
|
for (i = 0; i < destinations.size(); i++) {
|
||||||
//add destination to sig
|
//add destination to sig
|
||||||
rv.outPk[i].dest = copy(destinations[i]);
|
rv.outPk[i].dest = copy(destinations[i]);
|
||||||
@ -587,13 +587,14 @@ namespace rct {
|
|||||||
rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> & amounts, const int mixin) {
|
rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> & amounts, const int mixin) {
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
ctkeyM mixRing;
|
ctkeyM mixRing;
|
||||||
|
ctkeyV outSk;
|
||||||
tie(mixRing, index) = populateFromBlockchain(inPk, mixin);
|
tie(mixRing, index) = populateFromBlockchain(inPk, mixin);
|
||||||
return genRct(message, inSk, destinations, amounts, mixRing, index);
|
return genRct(message, inSk, destinations, amounts, mixRing, index, outSk);
|
||||||
}
|
}
|
||||||
|
|
||||||
//RCT simple
|
//RCT simple
|
||||||
//for post-rct only
|
//for post-rct only
|
||||||
rctSig genRctSimple(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> &inamounts, const vector<xmr_amount> &outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const std::vector<unsigned int> & index) {
|
rctSig genRctSimple(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> &inamounts, const vector<xmr_amount> &outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const std::vector<unsigned int> & index, ctkeyV &outSk) {
|
||||||
CHECK_AND_ASSERT_THROW_MES(inamounts.size() > 0, "Empty inamounts");
|
CHECK_AND_ASSERT_THROW_MES(inamounts.size() > 0, "Empty inamounts");
|
||||||
CHECK_AND_ASSERT_THROW_MES(inamounts.size() == inSk.size(), "Different number of inamounts/inSk");
|
CHECK_AND_ASSERT_THROW_MES(inamounts.size() == inSk.size(), "Different number of inamounts/inSk");
|
||||||
CHECK_AND_ASSERT_THROW_MES(outamounts.size() == destinations.size(), "Different number of amounts/destinations");
|
CHECK_AND_ASSERT_THROW_MES(outamounts.size() == destinations.size(), "Different number of amounts/destinations");
|
||||||
@ -612,7 +613,7 @@ namespace rct {
|
|||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
keyV masks(destinations.size()); //sk mask..
|
keyV masks(destinations.size()); //sk mask..
|
||||||
ctkeyV outSk(destinations.size());
|
outSk.resize(destinations.size());
|
||||||
key sumout = zero();
|
key sumout = zero();
|
||||||
for (i = 0; i < destinations.size(); i++) {
|
for (i = 0; i < destinations.size(); i++) {
|
||||||
|
|
||||||
@ -659,12 +660,13 @@ namespace rct {
|
|||||||
std::vector<unsigned int> index;
|
std::vector<unsigned int> index;
|
||||||
index.resize(inPk.size());
|
index.resize(inPk.size());
|
||||||
ctkeyM mixRing;
|
ctkeyM mixRing;
|
||||||
|
ctkeyV outSk;
|
||||||
mixRing.resize(inPk.size());
|
mixRing.resize(inPk.size());
|
||||||
for (size_t i = 0; i < inPk.size(); ++i) {
|
for (size_t i = 0; i < inPk.size(); ++i) {
|
||||||
mixRing[i].resize(mixin+1);
|
mixRing[i].resize(mixin+1);
|
||||||
index[i] = populateFromBlockchainSimple(mixRing[i], inPk[i], mixin);
|
index[i] = populateFromBlockchainSimple(mixRing[i], inPk[i], mixin);
|
||||||
}
|
}
|
||||||
return genRctSimple(message, inSk, destinations, inamounts, outamounts, txnFee, mixRing, index);
|
return genRctSimple(message, inSk, destinations, inamounts, outamounts, txnFee, mixRing, index, outSk);
|
||||||
}
|
}
|
||||||
|
|
||||||
//RingCT protocol
|
//RingCT protocol
|
||||||
|
@ -135,10 +135,10 @@ namespace rct {
|
|||||||
//decodeRct: (c.f. http://eprint.iacr.org/2015/1098 section 5.1.1)
|
//decodeRct: (c.f. http://eprint.iacr.org/2015/1098 section 5.1.1)
|
||||||
// uses the attached ecdh info to find the amounts represented by each output commitment
|
// uses the attached ecdh info to find the amounts represented by each output commitment
|
||||||
// must know the destination private key to find the correct amount, else will return a random number
|
// must know the destination private key to find the correct amount, else will return a random number
|
||||||
rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & amounts, const ctkeyM &mixRing, unsigned int index);
|
rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & amounts, const ctkeyM &mixRing, unsigned int index, ctkeyV &outSk);
|
||||||
rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> & amounts, const int mixin);
|
rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> & amounts, const int mixin);
|
||||||
rctSig genRctSimple(const key & message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> & inamounts, const vector<xmr_amount> & outamounts, xmr_amount txnFee, unsigned int mixin);
|
rctSig genRctSimple(const key & message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> & inamounts, const vector<xmr_amount> & outamounts, xmr_amount txnFee, unsigned int mixin);
|
||||||
rctSig genRctSimple(const key & message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & inamounts, const vector<xmr_amount> & outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const std::vector<unsigned int> & index);
|
rctSig genRctSimple(const key & message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & inamounts, const vector<xmr_amount> & outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const std::vector<unsigned int> & index, ctkeyV &outSk);
|
||||||
bool verRct(const rctSig & rv);
|
bool verRct(const rctSig & rv);
|
||||||
bool verRct(const rctSig & rv, const ctkeyM &mixRing, const keyV &II, const key &message);
|
bool verRct(const rctSig & rv, const ctkeyM &mixRing, const keyV &II, const key &message);
|
||||||
bool verRctSimple(const rctSig & rv);
|
bool verRctSimple(const rctSig & rv);
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
#include "mnemonics/electrum-words.h"
|
#include "mnemonics/electrum-words.h"
|
||||||
#include "rapidjson/document.h"
|
#include "rapidjson/document.h"
|
||||||
#include "common/json_util.h"
|
#include "common/json_util.h"
|
||||||
|
#include "ringct/rctSigs.h"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
@ -2957,15 +2958,18 @@ bool simple_wallet::get_tx_key(const std::vector<std::string> &args_)
|
|||||||
LOCK_IDLE_SCOPE();
|
LOCK_IDLE_SCOPE();
|
||||||
|
|
||||||
crypto::secret_key tx_key;
|
crypto::secret_key tx_key;
|
||||||
bool r = m_wallet->get_tx_key(txid, tx_key);
|
std::vector<crypto::secret_key> amount_keys;
|
||||||
if (r)
|
if (m_wallet->get_tx_keys(txid, tx_key, amount_keys))
|
||||||
{
|
{
|
||||||
success_msg_writer() << tr("Tx key: ") << tx_key;
|
std::string s = epee::string_tools::pod_to_hex(tx_key);
|
||||||
|
for (const auto &k: amount_keys)
|
||||||
|
s += epee::string_tools::pod_to_hex(k);
|
||||||
|
success_msg_writer() << tr("Tx key: ") << s;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fail_msg_writer() << tr("no tx key found for this txid");
|
fail_msg_writer() << tr("no tx keys found for this txid");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2992,13 +2996,22 @@ bool simple_wallet::check_tx_key(const std::vector<std::string> &args_)
|
|||||||
|
|
||||||
LOCK_IDLE_SCOPE();
|
LOCK_IDLE_SCOPE();
|
||||||
|
|
||||||
cryptonote::blobdata tx_key_data;
|
if (local_args[1].size() < 64 || local_args[1].size() % 64)
|
||||||
if(!epee::string_tools::parse_hexstr_to_binbuff(local_args[1], tx_key_data))
|
|
||||||
{
|
{
|
||||||
fail_msg_writer() << tr("failed to parse tx key");
|
fail_msg_writer() << tr("failed to parse tx key");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
crypto::secret_key tx_key = *reinterpret_cast<const crypto::secret_key*>(tx_key_data.data());
|
std::vector<crypto::secret_key> tx_keys;
|
||||||
|
for (size_t start = 0; start < local_args[1].size(); start += 64)
|
||||||
|
{
|
||||||
|
cryptonote::blobdata tx_key_data;
|
||||||
|
if(!epee::string_tools::parse_hexstr_to_binbuff(std::string(&local_args[1][start], 64), tx_key_data))
|
||||||
|
{
|
||||||
|
fail_msg_writer() << tr("failed to parse tx key");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
tx_keys.push_back(*reinterpret_cast<const crypto::secret_key*>(tx_key_data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
cryptonote::account_public_address address;
|
cryptonote::account_public_address address;
|
||||||
bool has_payment_id;
|
bool has_payment_id;
|
||||||
@ -3043,12 +3056,18 @@ bool simple_wallet::check_tx_key(const std::vector<std::string> &args_)
|
|||||||
}
|
}
|
||||||
|
|
||||||
crypto::key_derivation derivation;
|
crypto::key_derivation derivation;
|
||||||
if (!crypto::generate_key_derivation(address.m_view_public_key, tx_key, derivation))
|
if (!crypto::generate_key_derivation(address.m_view_public_key, tx_keys[0], derivation))
|
||||||
{
|
{
|
||||||
fail_msg_writer() << tr("failed to generate key derivation from supplied parameters");
|
fail_msg_writer() << tr("failed to generate key derivation from supplied parameters");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tx_keys.size() != tx.vout.size() * 2 + 1)
|
||||||
|
{
|
||||||
|
fail_msg_writer() << tr("tx keys don't match tx vout");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t received = 0;
|
uint64_t received = 0;
|
||||||
try {
|
try {
|
||||||
for (size_t n = 0; n < tx.vout.size(); ++n)
|
for (size_t n = 0; n < tx.vout.size(); ++n)
|
||||||
@ -3059,13 +3078,33 @@ bool simple_wallet::check_tx_key(const std::vector<std::string> &args_)
|
|||||||
crypto::public_key pubkey;
|
crypto::public_key pubkey;
|
||||||
derive_public_key(derivation, n, address.m_spend_public_key, pubkey);
|
derive_public_key(derivation, n, address.m_spend_public_key, pubkey);
|
||||||
if (pubkey == tx_out_to_key.key)
|
if (pubkey == tx_out_to_key.key)
|
||||||
received += tx.vout[n].amount;
|
{
|
||||||
|
uint64_t amount;
|
||||||
|
if (tx.version == 1)
|
||||||
|
{
|
||||||
|
amount = tx.vout[n].amount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
rct::key Ctmp;
|
||||||
|
rct::addKeys2(Ctmp, rct::sk2rct(tx_keys[n * 2 + 2]), rct::sk2rct(tx_keys[n * 2 + 1]), rct::H);
|
||||||
|
if (rct::equalKeys(tx.rct_signatures.outPk[n].mask, Ctmp))
|
||||||
|
amount = rct::h2d(rct::sk2rct(tx_keys[n * 2 + 1]));
|
||||||
|
else
|
||||||
|
amount = 0;
|
||||||
|
}
|
||||||
|
catch (...) { amount = 0; }
|
||||||
|
}
|
||||||
|
received += amount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(const std::exception &e)
|
||||||
{
|
{
|
||||||
LOG_ERROR("unknown error");
|
LOG_ERROR("error: " << e.what());
|
||||||
fail_msg_writer() << tr("unknown error");
|
fail_msg_writer() << tr("error: ") << e.what();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1258,6 +1258,7 @@ bool wallet2::clear()
|
|||||||
m_unconfirmed_txs.clear();
|
m_unconfirmed_txs.clear();
|
||||||
m_payments.clear();
|
m_payments.clear();
|
||||||
m_tx_keys.clear();
|
m_tx_keys.clear();
|
||||||
|
m_amount_keys.clear();
|
||||||
m_confirmed_txs.clear();
|
m_confirmed_txs.clear();
|
||||||
m_local_bc_height = 1;
|
m_local_bc_height = 1;
|
||||||
return true;
|
return true;
|
||||||
@ -2343,7 +2344,10 @@ void wallet2::commit_tx(pending_tx& ptx)
|
|||||||
}
|
}
|
||||||
add_unconfirmed_tx(ptx.tx, amount_in, dests, payment_id, ptx.change_dts.amount);
|
add_unconfirmed_tx(ptx.tx, amount_in, dests, payment_id, ptx.change_dts.amount);
|
||||||
if (store_tx_info())
|
if (store_tx_info())
|
||||||
|
{
|
||||||
m_tx_keys.insert(std::make_pair(txid, ptx.tx_key));
|
m_tx_keys.insert(std::make_pair(txid, ptx.tx_key));
|
||||||
|
m_amount_keys.insert(std::make_pair(txid, ptx.amount_keys));
|
||||||
|
}
|
||||||
|
|
||||||
LOG_PRINT_L2("transaction " << txid << " generated ok and sent to daemon, key_images: [" << ptx.key_images << "]");
|
LOG_PRINT_L2("transaction " << txid << " generated ok and sent to daemon, key_images: [" << ptx.key_images << "]");
|
||||||
|
|
||||||
@ -2753,7 +2757,8 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
|
|||||||
}
|
}
|
||||||
|
|
||||||
crypto::secret_key tx_key;
|
crypto::secret_key tx_key;
|
||||||
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key);
|
std::vector<crypto::secret_key> amount_keys;
|
||||||
|
bool r = cryptonote::construct_tx_and_get_tx_keys(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key, amount_keys);
|
||||||
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
|
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
|
||||||
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
|
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
|
||||||
|
|
||||||
@ -2780,6 +2785,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
|
|||||||
ptx.change_dts = change_dts;
|
ptx.change_dts = change_dts;
|
||||||
ptx.selected_transfers = selected_transfers;
|
ptx.selected_transfers = selected_transfers;
|
||||||
ptx.tx_key = tx_key;
|
ptx.tx_key = tx_key;
|
||||||
|
ptx.amount_keys = amount_keys;
|
||||||
ptx.dests = dsts;
|
ptx.dests = dsts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2972,7 +2978,8 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
|
|||||||
dsts.push_back(change_dts);
|
dsts.push_back(change_dts);
|
||||||
|
|
||||||
crypto::secret_key tx_key;
|
crypto::secret_key tx_key;
|
||||||
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, dsts, extra, tx, unlock_time, tx_key, true);
|
std::vector<crypto::secret_key> amount_keys;
|
||||||
|
bool r = cryptonote::construct_tx_and_get_tx_keys(m_account.get_keys(), sources, dsts, extra, tx, unlock_time, tx_key, amount_keys, true);
|
||||||
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, dsts, unlock_time, m_testnet);
|
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, dsts, unlock_time, m_testnet);
|
||||||
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
|
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
|
||||||
|
|
||||||
@ -2993,6 +3000,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
|
|||||||
ptx.change_dts = change_dts;
|
ptx.change_dts = change_dts;
|
||||||
ptx.selected_transfers = selected_transfers;
|
ptx.selected_transfers = selected_transfers;
|
||||||
ptx.tx_key = tx_key;
|
ptx.tx_key = tx_key;
|
||||||
|
ptx.amount_keys = amount_keys;
|
||||||
ptx.dests = dsts;
|
ptx.dests = dsts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3645,7 +3653,8 @@ void wallet2::transfer_from(const std::vector<size_t> &outs, size_t num_outputs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
crypto::secret_key tx_key;
|
crypto::secret_key tx_key;
|
||||||
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key);
|
std::vector<crypto::secret_key> amount_keys;
|
||||||
|
bool r = cryptonote::construct_tx_and_get_tx_keys(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key, amount_keys);
|
||||||
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
|
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
|
||||||
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
|
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
|
||||||
|
|
||||||
@ -3665,6 +3674,7 @@ void wallet2::transfer_from(const std::vector<size_t> &outs, size_t num_outputs,
|
|||||||
ptx.change_dts = change_dts;
|
ptx.change_dts = change_dts;
|
||||||
ptx.selected_transfers = selected_transfers;
|
ptx.selected_transfers = selected_transfers;
|
||||||
ptx.tx_key = tx_key;
|
ptx.tx_key = tx_key;
|
||||||
|
ptx.amount_keys = amount_keys;
|
||||||
ptx.dests = dsts;
|
ptx.dests = dsts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3911,12 +3921,15 @@ std::vector<wallet2::pending_tx> wallet2::create_unmixable_sweep_transactions(bo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key) const
|
bool wallet2::get_tx_keys(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &amount_keys) const
|
||||||
{
|
{
|
||||||
const std::unordered_map<crypto::hash, crypto::secret_key>::const_iterator i = m_tx_keys.find(txid);
|
const std::unordered_map<crypto::hash, crypto::secret_key>::const_iterator i = m_tx_keys.find(txid);
|
||||||
if (i == m_tx_keys.end())
|
if (i == m_tx_keys.end())
|
||||||
return false;
|
return false;
|
||||||
tx_key = i->second;
|
tx_key = i->second;
|
||||||
|
const std::unordered_map<crypto::hash, std::vector<crypto::secret_key>>::const_iterator j = m_amount_keys.find(txid);
|
||||||
|
if (j != m_amount_keys.end())
|
||||||
|
amount_keys = j->second;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +161,7 @@ namespace tools
|
|||||||
std::list<transfer_container::iterator> selected_transfers;
|
std::list<transfer_container::iterator> selected_transfers;
|
||||||
std::string key_images;
|
std::string key_images;
|
||||||
crypto::secret_key tx_key;
|
crypto::secret_key tx_key;
|
||||||
|
std::vector<crypto::secret_key> amount_keys;
|
||||||
std::vector<cryptonote::tx_destination_entry> dests;
|
std::vector<cryptonote::tx_destination_entry> dests;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -351,6 +352,9 @@ namespace tools
|
|||||||
if(ver < 13)
|
if(ver < 13)
|
||||||
return;
|
return;
|
||||||
a & m_unconfirmed_payments;
|
a & m_unconfirmed_payments;
|
||||||
|
if(ver < 14)
|
||||||
|
return;
|
||||||
|
a & m_amount_keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -386,7 +390,7 @@ namespace tools
|
|||||||
bool auto_refresh() const { return m_auto_refresh; }
|
bool auto_refresh() const { return m_auto_refresh; }
|
||||||
void auto_refresh(bool r) { m_auto_refresh = r; }
|
void auto_refresh(bool r) { m_auto_refresh = r; }
|
||||||
|
|
||||||
bool get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key) const;
|
bool get_tx_keys(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &amount_keys) const;
|
||||||
|
|
||||||
|
|
||||||
bool use_fork_rules(uint8_t version);
|
bool use_fork_rules(uint8_t version);
|
||||||
@ -464,6 +468,7 @@ namespace tools
|
|||||||
std::unordered_map<crypto::hash, confirmed_transfer_details> m_confirmed_txs;
|
std::unordered_map<crypto::hash, confirmed_transfer_details> m_confirmed_txs;
|
||||||
std::unordered_map<crypto::hash, payment_details> m_unconfirmed_payments;
|
std::unordered_map<crypto::hash, payment_details> m_unconfirmed_payments;
|
||||||
std::unordered_map<crypto::hash, crypto::secret_key> m_tx_keys;
|
std::unordered_map<crypto::hash, crypto::secret_key> m_tx_keys;
|
||||||
|
std::unordered_map<crypto::hash, std::vector<crypto::secret_key>> m_amount_keys;
|
||||||
|
|
||||||
transfer_container m_transfers;
|
transfer_container m_transfers;
|
||||||
payment_container m_payments;
|
payment_container m_payments;
|
||||||
@ -491,7 +496,7 @@ namespace tools
|
|||||||
uint64_t m_refresh_from_block_height;
|
uint64_t m_refresh_from_block_height;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
BOOST_CLASS_VERSION(tools::wallet2, 13)
|
BOOST_CLASS_VERSION(tools::wallet2, 14)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 2)
|
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 2)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::payment_details, 1)
|
BOOST_CLASS_VERSION(tools::wallet2::payment_details, 1)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 4)
|
BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 4)
|
||||||
@ -795,7 +800,8 @@ namespace tools
|
|||||||
}
|
}
|
||||||
|
|
||||||
crypto::secret_key tx_key;
|
crypto::secret_key tx_key;
|
||||||
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key);
|
std::vector<crypto::secret_key> amount_keys;
|
||||||
|
bool r = cryptonote::construct_tx_and_get_tx_keys(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key, amount_keys);
|
||||||
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
|
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
|
||||||
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
|
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
|
||||||
|
|
||||||
@ -821,6 +827,7 @@ namespace tools
|
|||||||
ptx.change_dts = change_dts;
|
ptx.change_dts = change_dts;
|
||||||
ptx.selected_transfers = selected_transfers;
|
ptx.selected_transfers = selected_transfers;
|
||||||
ptx.tx_key = tx_key;
|
ptx.tx_key = tx_key;
|
||||||
|
ptx.amount_keys = amount_keys;
|
||||||
ptx.dests = dsts;
|
ptx.dests = dsts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,7 +254,16 @@ namespace tools
|
|||||||
// populate response with tx hash
|
// populate response with tx hash
|
||||||
res.tx_hash = epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx_vector.back().tx));
|
res.tx_hash = epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx_vector.back().tx));
|
||||||
if (req.get_tx_key)
|
if (req.get_tx_key)
|
||||||
|
{
|
||||||
res.tx_key = epee::string_tools::pod_to_hex(ptx_vector.back().tx_key);
|
res.tx_key = epee::string_tools::pod_to_hex(ptx_vector.back().tx_key);
|
||||||
|
if (ptx_vector.back().tx.version > 1)
|
||||||
|
{
|
||||||
|
for (const auto &i: ptx_vector.back().amount_keys)
|
||||||
|
{
|
||||||
|
res.amount_keys.push_back(epee::string_tools::pod_to_hex(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (const tools::error::daemon_busy& e)
|
catch (const tools::error::daemon_busy& e)
|
||||||
@ -317,7 +326,17 @@ namespace tools
|
|||||||
{
|
{
|
||||||
res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
|
res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
|
||||||
if (req.get_tx_keys)
|
if (req.get_tx_keys)
|
||||||
|
{
|
||||||
res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key));
|
res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key));
|
||||||
|
res.amount_key_list.push_back(wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::key_list());
|
||||||
|
if (ptx.tx.version > 1)
|
||||||
|
{
|
||||||
|
for (const auto &i: ptx.amount_keys)
|
||||||
|
{
|
||||||
|
res.amount_key_list.back().keys.push_back(epee::string_tools::pod_to_hex(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -363,7 +382,17 @@ namespace tools
|
|||||||
{
|
{
|
||||||
res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
|
res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
|
||||||
if (req.get_tx_keys)
|
if (req.get_tx_keys)
|
||||||
|
{
|
||||||
res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key));
|
res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key));
|
||||||
|
res.amount_key_list.push_back(wallet_rpc::COMMAND_RPC_SWEEP_DUST::key_list());
|
||||||
|
if (ptx.tx.version > 1)
|
||||||
|
{
|
||||||
|
for (const auto &i: ptx.amount_keys)
|
||||||
|
{
|
||||||
|
res.amount_key_list.back().keys.push_back(epee::string_tools::pod_to_hex(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -422,7 +451,17 @@ namespace tools
|
|||||||
{
|
{
|
||||||
res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
|
res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
|
||||||
if (req.get_tx_keys)
|
if (req.get_tx_keys)
|
||||||
|
{
|
||||||
res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key));
|
res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key));
|
||||||
|
res.amount_key_list.push_back(wallet_rpc::COMMAND_RPC_SWEEP_ALL::key_list());
|
||||||
|
if (ptx.tx.version > 1)
|
||||||
|
{
|
||||||
|
for (const auto &i: ptx.amount_keys)
|
||||||
|
{
|
||||||
|
res.amount_key_list.back().keys.push_back(epee::string_tools::pod_to_hex(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -132,10 +132,12 @@ namespace wallet_rpc
|
|||||||
{
|
{
|
||||||
std::string tx_hash;
|
std::string tx_hash;
|
||||||
std::string tx_key;
|
std::string tx_key;
|
||||||
|
std::list<std::string> amount_keys;
|
||||||
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
KV_SERIALIZE(tx_hash)
|
KV_SERIALIZE(tx_hash)
|
||||||
KV_SERIALIZE(tx_key)
|
KV_SERIALIZE(tx_key)
|
||||||
|
KV_SERIALIZE(amount_keys)
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -165,14 +167,25 @@ namespace wallet_rpc
|
|||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct key_list
|
||||||
|
{
|
||||||
|
std::list<std::string> keys;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(keys)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
struct response
|
struct response
|
||||||
{
|
{
|
||||||
std::list<std::string> tx_hash_list;
|
std::list<std::string> tx_hash_list;
|
||||||
std::list<std::string> tx_key_list;
|
std::list<std::string> tx_key_list;
|
||||||
|
std::list<key_list> amount_key_list;
|
||||||
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
KV_SERIALIZE(tx_hash_list)
|
KV_SERIALIZE(tx_hash_list)
|
||||||
KV_SERIALIZE(tx_key_list)
|
KV_SERIALIZE(tx_key_list)
|
||||||
|
KV_SERIALIZE(amount_key_list)
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -190,14 +203,25 @@ namespace wallet_rpc
|
|||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct key_list
|
||||||
|
{
|
||||||
|
std::list<std::string> keys;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(keys)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
struct response
|
struct response
|
||||||
{
|
{
|
||||||
std::list<std::string> tx_hash_list;
|
std::list<std::string> tx_hash_list;
|
||||||
std::list<std::string> tx_key_list;
|
std::list<std::string> tx_key_list;
|
||||||
|
std::list<key_list> amount_key_list;
|
||||||
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
KV_SERIALIZE(tx_hash_list)
|
KV_SERIALIZE(tx_hash_list)
|
||||||
KV_SERIALIZE(tx_key_list)
|
KV_SERIALIZE(tx_key_list)
|
||||||
|
KV_SERIALIZE(amount_key_list)
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -225,14 +249,25 @@ namespace wallet_rpc
|
|||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct key_list
|
||||||
|
{
|
||||||
|
std::list<std::string> keys;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(keys)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
struct response
|
struct response
|
||||||
{
|
{
|
||||||
std::list<std::string> tx_hash_list;
|
std::list<std::string> tx_hash_list;
|
||||||
std::list<std::string> tx_key_list;
|
std::list<std::string> tx_key_list;
|
||||||
|
std::list<key_list> amount_key_list;
|
||||||
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
KV_SERIALIZE(tx_hash_list)
|
KV_SERIALIZE(tx_hash_list)
|
||||||
KV_SERIALIZE(tx_key_list)
|
KV_SERIALIZE(tx_key_list)
|
||||||
|
KV_SERIALIZE(amount_key_list)
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -116,7 +116,8 @@ bool gen_rct_tx_validation_base::generate_with(std::vector<test_event_entry>& ev
|
|||||||
destinations.push_back(td); // 30 -> 7.39 * 4
|
destinations.push_back(td); // 30 -> 7.39 * 4
|
||||||
|
|
||||||
crypto::secret_key tx_key;
|
crypto::secret_key tx_key;
|
||||||
bool r = construct_tx_and_get_tx_key(miner_accounts[n].get_keys(), sources, destinations, std::vector<uint8_t>(), rct_txes[n], 0, tx_key, true);
|
std::vector<crypto::secret_key> amount_keys;
|
||||||
|
bool r = construct_tx_and_get_tx_keys(miner_accounts[n].get_keys(), sources, destinations, std::vector<uint8_t>(), rct_txes[n], 0, tx_key, amount_keys, true);
|
||||||
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
|
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
|
||||||
events.push_back(rct_txes[n]);
|
events.push_back(rct_txes[n]);
|
||||||
starting_rct_tx_hashes.push_back(get_transaction_hash(rct_txes[n]));
|
starting_rct_tx_hashes.push_back(get_transaction_hash(rct_txes[n]));
|
||||||
@ -206,7 +207,8 @@ bool gen_rct_tx_validation_base::generate_with(std::vector<test_event_entry>& ev
|
|||||||
|
|
||||||
transaction tx;
|
transaction tx;
|
||||||
crypto::secret_key tx_key;
|
crypto::secret_key tx_key;
|
||||||
bool r = construct_tx_and_get_tx_key(miner_accounts[0].get_keys(), sources, destinations, std::vector<uint8_t>(), tx, 0, tx_key, true);
|
std::vector<crypto::secret_key> amount_keys;
|
||||||
|
bool r = construct_tx_and_get_tx_keys(miner_accounts[0].get_keys(), sources, destinations, std::vector<uint8_t>(), tx, 0, tx_key, amount_keys, true);
|
||||||
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
|
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
|
||||||
|
|
||||||
if (post_tx)
|
if (post_tx)
|
||||||
|
Loading…
Reference in New Issue
Block a user