rct amount key modified as per luigi1111's recommendations

This allows the key to be not the same for two outputs sent to
the same address (eg, if you pay yourself, and also get change
back). Also remove the key amounts lists and return parameters
since we don't actually generate random ones, so we don't need
to save them as we can recalculate them when needed if we have
the correct keys.
This commit is contained in:
moneromooo-monero 2016-08-10 12:48:20 +01:00
parent 93f5c625f0
commit d4b62a1e29
No known key found for this signature in database
GPG Key ID: 686F07454D6CEFC3
15 changed files with 85 additions and 133 deletions

View File

@ -151,7 +151,7 @@ namespace crypto {
return true; return true;
} }
static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) { void crypto_ops::derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) {
struct { struct {
key_derivation derivation; key_derivation derivation;
char output_index[(sizeof(size_t) * 8 + 6) / 7]; char output_index[(sizeof(size_t) * 8 + 6) / 7];

View File

@ -113,6 +113,8 @@ namespace crypto {
friend bool secret_key_to_public_key(const secret_key &, public_key &); friend bool secret_key_to_public_key(const secret_key &, public_key &);
static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &); static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &); friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res);
friend void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res);
static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &); static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &); friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &); static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
@ -181,6 +183,9 @@ namespace crypto {
const public_key &base, public_key &derived_key) { const public_key &base, public_key &derived_key) {
return crypto_ops::derive_public_key(derivation, output_index, base, derived_key); return crypto_ops::derive_public_key(derivation, output_index, base, derived_key);
} }
inline void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) {
return crypto_ops::derivation_to_scalar(derivation, output_index, res);
}
inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index, inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index,
const secret_key &base, secret_key &derived_key) { const secret_key &base, secret_key &derived_key) {
crypto_ops::derive_secret_key(derivation, output_index, base, derived_key); crypto_ops::derive_secret_key(derivation, output_index, base, derived_key);

View File

@ -458,8 +458,9 @@ 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_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) 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)
{ {
std::vector<crypto::secret_key> amount_keys;
tx.vin.clear(); tx.vin.clear();
tx.vout.clear(); tx.vout.clear();
tx.signatures.clear(); tx.signatures.clear();
@ -577,6 +578,12 @@ namespace cryptonote
bool r = crypto::generate_key_derivation(dst_entr.addr.m_view_public_key, txkey.sec, derivation); bool r = crypto::generate_key_derivation(dst_entr.addr.m_view_public_key, txkey.sec, derivation);
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << txkey.sec << ")"); CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << txkey.sec << ")");
if (tx.version > 1)
{
crypto::secret_key scalar1;
crypto::derivation_to_scalar(derivation, output_index, scalar1);
amount_keys.push_back(scalar1);
}
r = crypto::derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key); r = crypto::derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key);
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << output_index << ", "<< dst_entr.addr.m_spend_public_key << ")"); CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << output_index << ", "<< dst_entr.addr.m_spend_public_key << ")");
@ -686,7 +693,6 @@ namespace cryptonote
destinations.push_back(rct::pk2rct(boost::get<txout_to_key>(tx.vout[i].target).key)); destinations.push_back(rct::pk2rct(boost::get<txout_to_key>(tx.vout[i].target).key));
outamounts.push_back(tx.vout[i].amount); outamounts.push_back(tx.vout[i].amount);
amount_out += tx.vout[i].amount; amount_out += tx.vout[i].amount;
amount_keys.push_back(rct::rct2sk(rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(shuffled_dsts[i].addr.m_view_public_key), rct::sk2rct(txkey.sec)))));
} }
if (use_simple_rct) if (use_simple_rct)
@ -745,8 +751,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)
{ {
crypto::secret_key tx_key; crypto::secret_key tx_key;
std::vector<crypto::secret_key> amount_keys; return construct_tx_and_get_tx_key(sender_account_keys, sources, destinations, extra, tx, unlock_time, tx_key);
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)

View File

@ -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_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); 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 = 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)

View File

@ -741,28 +741,18 @@ void fe_mul(fe h,const fe f,const fe g)
//Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a //Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a
// where C= aG + bH // where C= aG + bH
void ecdhEncodeFromSharedSecret(ecdhTuple & unmasked, const key & sharedSec1) { void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec) {
key sharedSec1 = hash_to_scalar(sharedSec);
key sharedSec2 = hash_to_scalar(sharedSec1); key sharedSec2 = hash_to_scalar(sharedSec1);
//encode //encode
sc_add(unmasked.mask.bytes, unmasked.mask.bytes, sharedSec1.bytes); sc_add(unmasked.mask.bytes, unmasked.mask.bytes, sharedSec1.bytes);
sc_add(unmasked.amount.bytes, unmasked.amount.bytes, sharedSec2.bytes); sc_add(unmasked.amount.bytes, unmasked.amount.bytes, sharedSec2.bytes);
} }
void ecdhEncode(ecdhTuple & unmasked, const key & receiverPk) { void ecdhDecode(ecdhTuple & masked, const key & sharedSec) {
key esk; key sharedSec1 = hash_to_scalar(sharedSec);
//compute shared secret
skpkGen(esk, unmasked.senderPk);
key sharedSec1 = hash_to_scalar(scalarmultKey(receiverPk, esk));
ecdhEncodeFromSharedSecret(unmasked, sharedSec1);
}
void ecdhDecodeFromSharedSecret(ecdhTuple & masked, const key & sharedSec1) {
key sharedSec2 = hash_to_scalar(sharedSec1); key sharedSec2 = hash_to_scalar(sharedSec1);
//decode //decode
sc_sub(masked.mask.bytes, masked.mask.bytes, sharedSec1.bytes); sc_sub(masked.mask.bytes, masked.mask.bytes, sharedSec1.bytes);
sc_sub(masked.amount.bytes, masked.amount.bytes, sharedSec2.bytes); sc_sub(masked.amount.bytes, masked.amount.bytes, sharedSec2.bytes);
} }
void ecdhDecode(ecdhTuple & masked, const key & receiverSk) {
//compute shared secret
key sharedSec1 = hash_to_scalar(scalarmultKey(masked.senderPk, receiverSk));
ecdhDecodeFromSharedSecret(masked, sharedSec1);
}
} }

View File

@ -165,9 +165,7 @@ namespace rct {
//Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a //Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a
// where C= aG + bH // where C= aG + bH
void ecdhEncodeFromSharedSecret(ecdhTuple & unmasked, const key & sharedSec1); void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec);
void ecdhEncode(ecdhTuple & unmasked, const key & receiverPk); void ecdhDecode(ecdhTuple & masked, const key & sharedSec);
void ecdhDecodeFromSharedSecret(ecdhTuple & masked, const key & sharedSec1);
void ecdhDecode(ecdhTuple & masked, const key & receiverSk);
} }
#endif /* RCTOPS_H */ #endif /* RCTOPS_H */

View File

@ -613,7 +613,7 @@ namespace rct {
//mask amount and mask //mask amount and mask
rv.ecdhInfo[i].mask = copy(outSk[i].mask); rv.ecdhInfo[i].mask = copy(outSk[i].mask);
rv.ecdhInfo[i].amount = d2h(amounts[i]); rv.ecdhInfo[i].amount = d2h(amounts[i]);
ecdhEncodeFromSharedSecret(rv.ecdhInfo[i], amount_keys[i]); ecdhEncode(rv.ecdhInfo[i], amount_keys[i]);
} }
@ -679,7 +679,7 @@ namespace rct {
//mask amount and mask //mask amount and mask
rv.ecdhInfo[i].mask = copy(outSk[i].mask); rv.ecdhInfo[i].mask = copy(outSk[i].mask);
rv.ecdhInfo[i].amount = d2h(outamounts[i]); rv.ecdhInfo[i].amount = d2h(outamounts[i]);
ecdhEncodeFromSharedSecret(rv.ecdhInfo[i], amount_keys[i]); ecdhEncode(rv.ecdhInfo[i], amount_keys[i]);
} }
//set txn fee //set txn fee
@ -821,7 +821,7 @@ 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
static xmr_amount decodeRctMain(const rctSig & rv, const key & sk, unsigned int i, key & mask, void (*decode)(ecdhTuple&, const key&)) { xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask) {
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "decodeRct called on non-full rctSig"); CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "decodeRct called on non-full rctSig");
CHECK_AND_ASSERT_THROW_MES(rv.p.rangeSigs.size() > 0, "Empty rv.p.rangeSigs"); CHECK_AND_ASSERT_THROW_MES(rv.p.rangeSigs.size() > 0, "Empty rv.p.rangeSigs");
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.p.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.p.rangeSigs"); CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.p.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.p.rangeSigs");
@ -829,7 +829,7 @@ namespace rct {
//mask amount and mask //mask amount and mask
ecdhTuple ecdh_info = rv.ecdhInfo[i]; ecdhTuple ecdh_info = rv.ecdhInfo[i];
(*decode)(ecdh_info, sk); ecdhDecode(ecdh_info, sk);
mask = ecdh_info.mask; mask = ecdh_info.mask;
key amount = ecdh_info.amount; key amount = ecdh_info.amount;
key C = rv.outPk[i].mask; key C = rv.outPk[i].mask;
@ -845,20 +845,12 @@ namespace rct {
return h2d(amount); return h2d(amount);
} }
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask) {
return decodeRctMain(rv, sk, i, mask, &ecdhDecode);
}
xmr_amount decodeRctFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key & mask) {
return decodeRctMain(rv, sk, i, mask, &ecdhDecodeFromSharedSecret);
}
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i) { xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i) {
key mask; key mask;
return decodeRct(rv, sk, i, mask); return decodeRct(rv, sk, i, mask);
} }
static xmr_amount decodeRctSimpleMain(const rctSig & rv, const key & sk, unsigned int i, key &mask, void (*decode)(ecdhTuple &ecdh, const key&)) { xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask) {
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple, false, "decodeRct called on non simple rctSig"); CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple, false, "decodeRct called on non simple rctSig");
CHECK_AND_ASSERT_THROW_MES(rv.p.rangeSigs.size() > 0, "Empty rv.p.rangeSigs"); CHECK_AND_ASSERT_THROW_MES(rv.p.rangeSigs.size() > 0, "Empty rv.p.rangeSigs");
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.p.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.p.rangeSigs"); CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.p.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.p.rangeSigs");
@ -866,7 +858,7 @@ namespace rct {
//mask amount and mask //mask amount and mask
ecdhTuple ecdh_info = rv.ecdhInfo[i]; ecdhTuple ecdh_info = rv.ecdhInfo[i];
(*decode)(ecdh_info, sk); ecdhDecode(ecdh_info, sk);
mask = ecdh_info.mask; mask = ecdh_info.mask;
key amount = ecdh_info.amount; key amount = ecdh_info.amount;
key C = rv.outPk[i].mask; key C = rv.outPk[i].mask;
@ -882,14 +874,6 @@ namespace rct {
return h2d(amount); return h2d(amount);
} }
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask) {
return decodeRctSimpleMain(rv, sk, i, mask, &ecdhDecode);
}
xmr_amount decodeRctSimpleFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key &mask) {
return decodeRctSimpleMain(rv, sk, i, mask, &ecdhDecodeFromSharedSecret);
}
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i) { xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i) {
key mask; key mask;
return decodeRctSimple(rv, sk, i, mask); return decodeRctSimple(rv, sk, i, mask);

View File

@ -142,9 +142,7 @@ namespace rct {
bool verRct(const rctSig & rv); bool verRct(const rctSig & rv);
bool verRctSimple(const rctSig & rv); bool verRctSimple(const rctSig & rv);
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask); xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask);
xmr_amount decodeRctFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key & mask);
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i); xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i);
xmr_amount decodeRctSimpleFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key & mask);
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key & mask); xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key & mask);
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i); xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i);
} }

View File

@ -3077,15 +3077,27 @@ bool simple_wallet::check_tx_key(const std::vector<std::string> &args_)
try try
{ {
rct::key Ctmp; rct::key Ctmp;
rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(address.m_view_public_key), rct::sk2rct(tx_key))); //rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(address.m_view_public_key), rct::sk2rct(tx_key)));
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n]; crypto::key_derivation derivation;
rct::ecdhDecodeFromSharedSecret(ecdh_info, amount_key); bool r = crypto::generate_key_derivation(address.m_view_public_key, tx_key, derivation);
rct::key C = tx.rct_signatures.outPk[n].mask; if (!r)
rct::addKeys2(Ctmp, ecdh_info.mask, ecdh_info.amount, rct::H); {
if (rct::equalKeys(C, Ctmp)) LOG_ERROR("Failed to generate key derivation to decode rct output " << n);
amount = rct::h2d(ecdh_info.amount);
else
amount = 0; amount = 0;
}
else
{
crypto::secret_key scalar1;
crypto::derivation_to_scalar(derivation, n, scalar1);
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n];
rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1));
rct::key C = tx.rct_signatures.outPk[n].mask;
rct::addKeys2(Ctmp, ecdh_info.mask, ecdh_info.amount, rct::H);
if (rct::equalKeys(C, Ctmp))
amount = rct::h2d(ecdh_info.amount);
else
amount = 0;
}
} }
catch (...) { amount = 0; } catch (...) { amount = 0; }
} }

View File

@ -207,16 +207,25 @@ void wallet2::check_acc_out(const account_keys &acc, const tx_out &o, const cryp
error = false; error = false;
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
static uint64_t decodeRct(const rct::rctSig & rv, const rct::key & sk, unsigned int i, rct::key & mask) static uint64_t decodeRct(const rct::rctSig & rv, const crypto::public_key pub, const crypto::secret_key &sec, unsigned int i, rct::key & mask)
{ {
crypto::key_derivation derivation;
bool r = crypto::generate_key_derivation(pub, sec, derivation);
if (!r)
{
LOG_ERROR("Failed to generate key derivation to decode rct output " << i);
return 0;
}
crypto::secret_key scalar1;
crypto::derivation_to_scalar(derivation, i, scalar1);
try try
{ {
switch (rv.type) switch (rv.type)
{ {
case rct::RCTTypeSimple: case rct::RCTTypeSimple:
return rct::decodeRctSimpleFromSharedSecret(rv, sk, i, mask); return rct::decodeRctSimple(rv, rct::sk2rct(scalar1), i, mask);
case rct::RCTTypeFull: case rct::RCTTypeFull:
return rct::decodeRctFromSharedSecret(rv, sk, i, mask); return rct::decodeRct(rv, rct::sk2rct(scalar1), i, mask);
default: default:
LOG_ERROR("Unsupported rct type: " << rv.type); LOG_ERROR("Unsupported rct type: " << rv.type);
return 0; return 0;
@ -308,8 +317,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
if (money_transfered == 0) if (money_transfered == 0)
{ {
const cryptonote::account_keys& keys = m_account.get_keys(); const cryptonote::account_keys& keys = m_account.get_keys();
rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(pub_key_field.pub_key), rct::sk2rct(keys.m_view_secret_key))); money_transfered = tools::decodeRct(tx.rct_signatures, pub_key_field.pub_key, keys.m_view_secret_key, 0, mask[0]);
money_transfered = tools::decodeRct(tx.rct_signatures, amount_key, 0, mask[0]);
} }
amount[0] = money_transfered; amount[0] = money_transfered;
tx_money_got_in_outs = money_transfered; tx_money_got_in_outs = money_transfered;
@ -352,8 +360,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
if (money_transfered[i] == 0) if (money_transfered[i] == 0)
{ {
const cryptonote::account_keys& keys = m_account.get_keys(); const cryptonote::account_keys& keys = m_account.get_keys();
rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(pub_key_field.pub_key), rct::sk2rct(keys.m_view_secret_key))); money_transfered[i] = tools::decodeRct(tx.rct_signatures, pub_key_field.pub_key, keys.m_view_secret_key, i, mask[i]);
money_transfered[i] = tools::decodeRct(tx.rct_signatures, amount_key, i, mask[i]);
} }
tx_money_got_in_outs += money_transfered[i]; tx_money_got_in_outs += money_transfered[i];
amount[i] = money_transfered[i]; amount[i] = money_transfered[i];
@ -401,8 +408,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
if (money_transfered[i] == 0) if (money_transfered[i] == 0)
{ {
const cryptonote::account_keys& keys = m_account.get_keys(); const cryptonote::account_keys& keys = m_account.get_keys();
rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(pub_key_field.pub_key), rct::sk2rct(keys.m_view_secret_key))); money_transfered[i] = tools::decodeRct(tx.rct_signatures, pub_key_field.pub_key, keys.m_view_secret_key, i, mask[i]);
money_transfered[i] = tools::decodeRct(tx.rct_signatures, amount_key, i, mask[i]);
} }
tx_money_got_in_outs += money_transfered[i]; tx_money_got_in_outs += money_transfered[i];
amount[i] = money_transfered[i]; amount[i] = money_transfered[i];
@ -434,8 +440,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
if (money_transfered == 0) if (money_transfered == 0)
{ {
const cryptonote::account_keys& keys = m_account.get_keys(); const cryptonote::account_keys& keys = m_account.get_keys();
rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(pub_key_field.pub_key), rct::sk2rct(keys.m_view_secret_key))); money_transfered = tools::decodeRct(tx.rct_signatures, pub_key_field.pub_key, keys.m_view_secret_key, i, mask[i]);
money_transfered = tools::decodeRct(tx.rct_signatures, amount_key, i, mask[i]);
} }
amount[i] = money_transfered; amount[i] = money_transfered;
tx_money_got_in_outs += money_transfered; tx_money_got_in_outs += money_transfered;
@ -2896,8 +2901,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
} }
crypto::secret_key tx_key; crypto::secret_key tx_key;
std::vector<crypto::secret_key> amount_keys; bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key);
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);
@ -2924,7 +2928,6 @@ 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;
} }
@ -3113,8 +3116,7 @@ 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;
std::vector<crypto::secret_key> amount_keys; bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, dsts, extra, tx, unlock_time, tx_key, true);
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);
@ -3135,7 +3137,6 @@ 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;
} }
@ -3764,8 +3765,7 @@ void wallet2::transfer_from(const std::vector<size_t> &outs, size_t num_outputs,
} }
crypto::secret_key tx_key; crypto::secret_key tx_key;
std::vector<crypto::secret_key> amount_keys; bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key);
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);
@ -3785,7 +3785,6 @@ 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;
} }

View File

@ -162,7 +162,6 @@ 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;
}; };
@ -828,8 +827,7 @@ namespace tools
} }
crypto::secret_key tx_key; crypto::secret_key tx_key;
std::vector<crypto::secret_key> amount_keys; bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key);
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);
@ -855,7 +853,6 @@ 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;
} }

View File

@ -256,13 +256,6 @@ namespace tools
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;
} }
@ -325,14 +318,6 @@ namespace tools
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));
}
}
} }
} }
@ -381,14 +366,6 @@ namespace tools
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));
}
}
} }
} }
@ -450,14 +427,6 @@ namespace tools
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));
}
}
} }
} }

View File

@ -178,12 +178,10 @@ namespace wallet_rpc
{ {
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()
}; };
}; };
@ -214,12 +212,10 @@ namespace wallet_rpc
{ {
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()
}; };
}; };
@ -260,12 +256,10 @@ namespace wallet_rpc
{ {
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()
}; };
}; };

View File

@ -116,20 +116,22 @@ 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;
std::vector<crypto::secret_key> amount_keys; 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);
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]));
crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(rct_txes[n]);
for (size_t o = 0; o < 4; ++o) for (size_t o = 0; o < 4; ++o)
{ {
rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(tx_pub_key), rct::sk2rct(miner_accounts[n].get_keys().m_view_secret_key))); crypto::key_derivation derivation;
bool r = crypto::generate_key_derivation(destinations[o].addr.m_view_public_key, tx_key, derivation);
CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation");
crypto::secret_key amount_key;
crypto::derivation_to_scalar(derivation, o, amount_key);
if (rct_txes[n].rct_signatures.type == rct::RCTTypeSimple) if (rct_txes[n].rct_signatures.type == rct::RCTTypeSimple)
rct::decodeRctSimpleFromSharedSecret(rct_txes[n].rct_signatures, amount_key, o, rct_tx_masks[o+n*4]); rct::decodeRctSimple(rct_txes[n].rct_signatures, rct::sk2rct(amount_key), o, rct_tx_masks[o+n*4]);
else else
rct::decodeRctFromSharedSecret(rct_txes[n].rct_signatures, amount_key, o, rct_tx_masks[o+n*4]); rct::decodeRct(rct_txes[n].rct_signatures, rct::sk2rct(amount_key), o, rct_tx_masks[o+n*4]);
} }
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk_txes[n], blk_last, miner_account, CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk_txes[n], blk_last, miner_account,
@ -205,8 +207,7 @@ 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;
std::vector<crypto::secret_key> amount_keys; bool r = construct_tx_and_get_tx_key(miner_accounts[0].get_keys(), sources, destinations, std::vector<uint8_t>(), tx, 0, tx_key, true);
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)

View File

@ -196,7 +196,7 @@ TEST(ringct, range_proofs)
ASSERT_TRUE(verRct(s)); ASSERT_TRUE(verRct(s));
//decode received amount //decode received amount
ASSERT_TRUE(decodeRctFromSharedSecret(s, amount_keys[1], 1, mask)); ASSERT_TRUE(decodeRct(s, amount_keys[1], 1, mask));
// Ring CT with failing MG sig part should not verify! // Ring CT with failing MG sig part should not verify!
// Since sum of inputs != outputs // Since sum of inputs != outputs
@ -213,7 +213,7 @@ TEST(ringct, range_proofs)
ASSERT_FALSE(verRct(s)); ASSERT_FALSE(verRct(s));
//decode received amount //decode received amount
ASSERT_TRUE(decodeRctFromSharedSecret(s, amount_keys[1], 1, mask)); ASSERT_TRUE(decodeRct(s, amount_keys[1], 1, mask));
} }
TEST(ringct, range_proofs_with_fee) TEST(ringct, range_proofs_with_fee)
@ -261,7 +261,7 @@ TEST(ringct, range_proofs_with_fee)
ASSERT_TRUE(verRct(s)); ASSERT_TRUE(verRct(s));
//decode received amount //decode received amount
ASSERT_TRUE(decodeRctFromSharedSecret(s, amount_keys[1], 1, mask)); ASSERT_TRUE(decodeRct(s, amount_keys[1], 1, mask));
// Ring CT with failing MG sig part should not verify! // Ring CT with failing MG sig part should not verify!
// Since sum of inputs != outputs // Since sum of inputs != outputs
@ -278,7 +278,7 @@ TEST(ringct, range_proofs_with_fee)
ASSERT_FALSE(verRct(s)); ASSERT_FALSE(verRct(s));
//decode received amount //decode received amount
ASSERT_TRUE(decodeRctFromSharedSecret(s, amount_keys[1], 1, mask)); ASSERT_TRUE(decodeRct(s, amount_keys[1], 1, mask));
} }
TEST(ringct, simple) TEST(ringct, simple)
@ -336,7 +336,7 @@ TEST(ringct, simple)
ASSERT_TRUE(verRctSimple(s)); ASSERT_TRUE(verRctSimple(s));
//decode received amount corresponding to output pubkey index 1 //decode received amount corresponding to output pubkey index 1
ASSERT_TRUE(decodeRctSimpleFromSharedSecret(s, amount_keys[1], 1, mask)); ASSERT_TRUE(decodeRctSimple(s, amount_keys[1], 1, mask));
} }
static rct::rctSig make_sample_rct_sig(int n_inputs, const uint64_t input_amounts[], int n_outputs, const uint64_t output_amounts[], bool last_is_fee) static rct::rctSig make_sample_rct_sig(int n_inputs, const uint64_t input_amounts[], int n_outputs, const uint64_t output_amounts[], bool last_is_fee)
@ -843,17 +843,17 @@ static const xmr_amount test_amounts[]={0, 1, 2, 3, 4, 5, 10000, 100000000000000
TEST(ringct, ecdh_roundtrip) TEST(ringct, ecdh_roundtrip)
{ {
key k, P1; key k;
ecdhTuple t0, t1; ecdhTuple t0, t1;
for (auto amount: test_amounts) { for (auto amount: test_amounts) {
skpkGen(k, P1); skGen(k);
t0.mask = skGen(); t0.mask = skGen();
t0.amount = d2h(amount); t0.amount = d2h(amount);
t1 = t0; t1 = t0;
ecdhEncode(t1, P1); ecdhEncode(t1, k);
ecdhDecode(t1, k); ecdhDecode(t1, k);
ASSERT_TRUE(t0.mask == t1.mask); ASSERT_TRUE(t0.mask == t1.mask);
ASSERT_TRUE(equalKeys(t0.mask, t1.mask)); ASSERT_TRUE(equalKeys(t0.mask, t1.mask));