add a bulletproof version, new bulletproof type, and rct config

This makes it easier to modify the bulletproof format
release-v0.5.1
moneromooo-monero 6 years ago committed by wowario
parent 817be97f39
commit b5c9aed261
No known key found for this signature in database
GPG Key ID: 24DCBE762DE9C111

@ -295,7 +295,7 @@ namespace boost
a & x.type; a & x.type;
if (x.type == rct::RCTTypeNull) if (x.type == rct::RCTTypeNull)
return; return;
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof) if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2)
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type"); throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
// a & x.message; message is not serialized, as it can be reconstructed from the tx data // a & x.message; message is not serialized, as it can be reconstructed from the tx data
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets // a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
@ -323,7 +323,7 @@ namespace boost
a & x.type; a & x.type;
if (x.type == rct::RCTTypeNull) if (x.type == rct::RCTTypeNull)
return; return;
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof) if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2)
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type"); throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
// a & x.message; message is not serialized, as it can be reconstructed from the tx data // a & x.message; message is not serialized, as it can be reconstructed from the tx data
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets // a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
@ -337,7 +337,7 @@ namespace boost
if (x.p.rangeSigs.empty()) if (x.p.rangeSigs.empty())
a & x.p.bulletproofs; a & x.p.bulletproofs;
a & x.p.MGs; a & x.p.MGs;
if (x.type == rct::RCTTypeBulletproof) if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2)
a & x.p.pseudoOuts; a & x.p.pseudoOuts;
} }
} }

@ -141,6 +141,7 @@
#define HF_VERSION_ENFORCE_RCT 6 #define HF_VERSION_ENFORCE_RCT 6
#define HF_VERSION_PER_BYTE_FEE 8 #define HF_VERSION_PER_BYTE_FEE 8
#define HF_VERSION_LONG_TERM_BLOCK_WEIGHT 10 #define HF_VERSION_LONG_TERM_BLOCK_WEIGHT 10
#define HF_VERSION_SMALLER_BP 10
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8 #define PER_KB_FEE_QUANTIZATION_DECIMALS 8

@ -2416,6 +2416,18 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
} }
} }
// from v10, allow bulletproofs v2
if (hf_version < HF_VERSION_SMALLER_BP) {
if (tx.version >= 2) {
if (tx.rct_signatures.type == rct::RCTTypeBulletproof2)
{
MERROR_VER("Bulletproofs v2 are not allowed before v" << HF_VERSION_SMALLER_BP);
tvc.m_invalid_output = true;
return false;
}
}
}
return true; return true;
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -2456,7 +2468,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
} }
} }
} }
else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof) else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2)
{ {
CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys"); CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys");
rv.mixRing.resize(pubkeys.size()); rv.mixRing.resize(pubkeys.size());
@ -2482,7 +2494,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
for (size_t n = 0; n < tx.vin.size(); ++n) for (size_t n = 0; n < tx.vin.size(); ++n)
rv.p.MGs[0].II[n] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image); rv.p.MGs[0].II[n] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
} }
else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof) else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rct::RCTTypeBulletproof2)
{ {
CHECK_AND_ASSERT_MES(rv.p.MGs.size() == tx.vin.size(), false, "Bad MGs size"); CHECK_AND_ASSERT_MES(rv.p.MGs.size() == tx.vin.size(), false, "Bad MGs size");
for (size_t n = 0; n < tx.vin.size(); ++n) for (size_t n = 0; n < tx.vin.size(); ++n)
@ -2756,6 +2768,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
} }
case rct::RCTTypeSimple: case rct::RCTTypeSimple:
case rct::RCTTypeBulletproof: case rct::RCTTypeBulletproof:
case rct::RCTTypeBulletproof2:
{ {
// check all this, either reconstructed (so should really pass), or not // check all this, either reconstructed (so should really pass), or not
{ {

@ -831,6 +831,7 @@ namespace cryptonote
} }
break; break;
case rct::RCTTypeBulletproof: case rct::RCTTypeBulletproof:
case rct::RCTTypeBulletproof2:
if (!is_canonical_bulletproof_layout(rv.p.bulletproofs)) if (!is_canonical_bulletproof_layout(rv.p.bulletproofs))
{ {
MERROR_VER("Bulletproof does not have canonical form"); MERROR_VER("Bulletproof does not have canonical form");
@ -858,7 +859,7 @@ namespace cryptonote
{ {
if (!tx_info[n].result) if (!tx_info[n].result)
continue; continue;
if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof) if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof2)
continue; continue;
if (assumed_bad || !rct::verRctSemanticsSimple(tx_info[n].tx->rct_signatures)) if (assumed_bad || !rct::verRctSemanticsSimple(tx_info[n].tx->rct_signatures))
{ {

@ -195,7 +195,7 @@ namespace cryptonote
return addr.m_view_public_key; return addr.m_view_public_key;
} }
//--------------------------------------------------------------- //---------------------------------------------------------------
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, 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, rct::RangeProofType range_proof_type, rct::multisig_out *msout, bool shuffle_outs) 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, 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, rct::multisig_out *msout, bool shuffle_outs)
{ {
hw::device &hwdev = sender_account_keys.get_device(); hw::device &hwdev = sender_account_keys.get_device();
@ -525,7 +525,7 @@ namespace cryptonote
// the non-simple version is slightly smaller, but assumes all real inputs // the non-simple version is slightly smaller, but assumes all real inputs
// are on the same index, so can only be used if there just one ring. // are on the same index, so can only be used if there just one ring.
bool use_simple_rct = sources.size() > 1 || range_proof_type != rct::RangeProofBorromean; bool use_simple_rct = sources.size() > 1 || rct_config.range_proof_type != rct::RangeProofBorromean;
if (!use_simple_rct) if (!use_simple_rct)
{ {
@ -623,9 +623,9 @@ namespace cryptonote
get_transaction_prefix_hash(tx, tx_prefix_hash); get_transaction_prefix_hash(tx, tx_prefix_hash);
rct::ctkeyV outSk; 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, amount_keys, msout ? &kLRki : NULL, msout, index, outSk, range_proof_type, hwdev); tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, msout ? &kLRki : NULL, msout, index, outSk, rct_config, hwdev);
else else
tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, amount_keys, msout ? &kLRki[0] : NULL, msout, sources[0].real_output, outSk, hwdev); // same index assumption tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, amount_keys, msout ? &kLRki[0] : NULL, msout, sources[0].real_output, outSk, rct_config, hwdev); // same index assumption
memwipe(inSk.data(), inSk.size() * sizeof(rct::ctkey)); memwipe(inSk.data(), inSk.size() * sizeof(rct::ctkey));
CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout"); CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout");
@ -638,7 +638,7 @@ namespace cryptonote
return true; 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, 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, rct::RangeProofType range_proof_type, rct::multisig_out *msout) 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, 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, rct::multisig_out *msout)
{ {
hw::device &hwdev = sender_account_keys.get_device(); hw::device &hwdev = sender_account_keys.get_device();
hwdev.open_tx(tx_key); hwdev.open_tx(tx_key);
@ -656,7 +656,7 @@ namespace cryptonote
additional_tx_keys.push_back(keypair::generate(sender_account_keys.get_device()).sec); additional_tx_keys.push_back(keypair::generate(sender_account_keys.get_device()).sec);
} }
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, range_proof_type, msout); 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, msout);
hwdev.close_tx(); hwdev.close_tx();
return r; return r;
} }
@ -668,7 +668,7 @@ namespace cryptonote
crypto::secret_key tx_key; crypto::secret_key tx_key;
std::vector<crypto::secret_key> additional_tx_keys; std::vector<crypto::secret_key> additional_tx_keys;
std::vector<tx_destination_entry> destinations_copy = destinations; 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, NULL); 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}, NULL);
} }
//--------------------------------------------------------------- //---------------------------------------------------------------
bool generate_genesis_block( bool generate_genesis_block(

@ -95,8 +95,8 @@ 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); 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, 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 boost::optional<cryptonote::account_public_address>& change_addr, 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, 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, rct::RangeProofType range_proof_type = rct::RangeProofBorromean, rct::multisig_out *msout = NULL, bool shuffle_outs = 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, 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 }, rct::multisig_out *msout = NULL, bool shuffle_outs = 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, 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, rct::RangeProofType range_proof_type = rct::RangeProofBorromean, rct::multisig_out *msout = NULL); 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, 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 }, rct::multisig_out *msout = NULL);
bool generate_genesis_block( bool generate_genesis_block(
block& bl block& bl

@ -391,7 +391,7 @@ namespace rct {
hashes.push_back(hash2rct(h)); hashes.push_back(hash2rct(h));
keyV kv; keyV kv;
if (rv.type == RCTTypeBulletproof) if (rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2)
{ {
kv.reserve((6*2+9) * rv.p.bulletproofs.size()); kv.reserve((6*2+9) * rv.p.bulletproofs.size());
for (const auto &p: rv.p.bulletproofs) for (const auto &p: rv.p.bulletproofs)
@ -652,7 +652,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, const keyV &amount_keys, const multisig_kLRki *kLRki, multisig_out *msout, unsigned int index, ctkeyV &outSk, hw::device &hwdev) { rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & amounts, const ctkeyM &mixRing, const keyV &amount_keys, const multisig_kLRki *kLRki, multisig_out *msout, unsigned int index, ctkeyV &outSk, const RCTConfig &rct_config, hw::device &hwdev) {
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(amount_keys.size() == destinations.size(), "Different number of amount_keys/destinations"); CHECK_AND_ASSERT_THROW_MES(amount_keys.size() == destinations.size(), "Different number of amount_keys/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");
@ -703,18 +703,18 @@ namespace rct {
return rv; return rv;
} }
rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> & amounts, const keyV &amount_keys, const multisig_kLRki *kLRki, multisig_out *msout, const int mixin, hw::device &hwdev) { rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> & amounts, const keyV &amount_keys, const multisig_kLRki *kLRki, multisig_out *msout, const int mixin, const RCTConfig &rct_config, hw::device &hwdev) {
unsigned int index; unsigned int index;
ctkeyM mixRing; ctkeyM mixRing;
ctkeyV outSk; ctkeyV outSk;
tie(mixRing, index) = populateFromBlockchain(inPk, mixin); tie(mixRing, index) = populateFromBlockchain(inPk, mixin);
return genRct(message, inSk, destinations, amounts, mixRing, amount_keys, kLRki, msout, index, outSk, hwdev); return genRct(message, inSk, destinations, amounts, mixRing, amount_keys, kLRki, msout, index, outSk, rct_config, hwdev);
} }
//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 keyV &amount_keys, const std::vector<multisig_kLRki> *kLRki, multisig_out *msout, const std::vector<unsigned int> & index, ctkeyV &outSk, RangeProofType range_proof_type, hw::device &hwdev) { 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 keyV &amount_keys, const std::vector<multisig_kLRki> *kLRki, multisig_out *msout, const std::vector<unsigned int> & index, ctkeyV &outSk, const RCTConfig &rct_config, hw::device &hwdev) {
const bool bulletproof = range_proof_type != RangeProofBorromean; const bool bulletproof = rct_config.range_proof_type != RangeProofBorromean;
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");
@ -730,7 +730,7 @@ namespace rct {
} }
rctSig rv; rctSig rv;
rv.type = bulletproof ? RCTTypeBulletproof : RCTTypeSimple; rv.type = bulletproof ? (rct_config.bp_version == 0 || rct_config.bp_version >= 2 ? RCTTypeBulletproof2 : RCTTypeBulletproof) : RCTTypeSimple;
rv.message = message; rv.message = message;
rv.outPk.resize(destinations.size()); rv.outPk.resize(destinations.size());
if (!bulletproof) if (!bulletproof)
@ -759,7 +759,7 @@ namespace rct {
std::vector<uint64_t> proof_amounts; std::vector<uint64_t> proof_amounts;
size_t n_amounts = outamounts.size(); size_t n_amounts = outamounts.size();
size_t amounts_proved = 0; size_t amounts_proved = 0;
if (range_proof_type == RangeProofPaddedBulletproof) if (rct_config.range_proof_type == RangeProofPaddedBulletproof)
{ {
rct::keyV C, masks; rct::keyV C, masks;
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts)); rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts));
@ -775,7 +775,7 @@ namespace rct {
else while (amounts_proved < n_amounts) else while (amounts_proved < n_amounts)
{ {
size_t batch_size = 1; size_t batch_size = 1;
if (range_proof_type == RangeProofMultiOutputBulletproof) if (rct_config.range_proof_type == RangeProofMultiOutputBulletproof)
while (batch_size * 2 + amounts_proved <= n_amounts && batch_size * 2 <= BULLETPROOF_MAX_OUTPUTS) while (batch_size * 2 + amounts_proved <= n_amounts && batch_size * 2 <= BULLETPROOF_MAX_OUTPUTS)
batch_size *= 2; batch_size *= 2;
rct::keyV C, masks; rct::keyV C, masks;
@ -835,7 +835,7 @@ namespace rct {
return rv; return rv;
} }
rctSig genRctSimple(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> &inamounts, const vector<xmr_amount> &outamounts, const keyV &amount_keys, const std::vector<multisig_kLRki> *kLRki, multisig_out *msout, xmr_amount txnFee, unsigned int mixin, hw::device &hwdev) { rctSig genRctSimple(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> &inamounts, const vector<xmr_amount> &outamounts, const keyV &amount_keys, const std::vector<multisig_kLRki> *kLRki, multisig_out *msout, xmr_amount txnFee, unsigned int mixin, const RCTConfig &rct_config, hw::device &hwdev) {
std::vector<unsigned int> index; std::vector<unsigned int> index;
index.resize(inPk.size()); index.resize(inPk.size());
ctkeyM mixRing; ctkeyM mixRing;
@ -845,7 +845,7 @@ namespace rct {
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, amount_keys, kLRki, msout, index, outSk, RangeProofBorromean, hwdev); return genRctSimple(message, inSk, destinations, inamounts, outamounts, txnFee, mixRing, amount_keys, kLRki, msout, index, outSk, rct_config, hwdev);
} }
//RingCT protocol //RingCT protocol
@ -935,7 +935,8 @@ namespace rct {
{ {
CHECK_AND_ASSERT_MES(rvp, false, "rctSig pointer is NULL"); CHECK_AND_ASSERT_MES(rvp, false, "rctSig pointer is NULL");
const rctSig &rv = *rvp; const rctSig &rv = *rvp;
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof, false, "verRctSemanticsSimple called on non simple rctSig"); CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2,
false, "verRctSemanticsSimple called on non simple rctSig");
const bool bulletproof = is_rct_bulletproof(rv.type); const bool bulletproof = is_rct_bulletproof(rv.type);
if (bulletproof) if (bulletproof)
{ {
@ -1034,7 +1035,8 @@ namespace rct {
{ {
PERF_TIMER(verRctNonSemanticsSimple); PERF_TIMER(verRctNonSemanticsSimple);
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof, false, "verRctNonSemanticsSimple called on non simple rctSig"); CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2,
false, "verRctNonSemanticsSimple called on non simple rctSig");
const bool bulletproof = is_rct_bulletproof(rv.type); const bool bulletproof = is_rct_bulletproof(rv.type);
// semantics check is early, and mixRing/MGs aren't resolved yet // semantics check is early, and mixRing/MGs aren't resolved yet
if (bulletproof) if (bulletproof)
@ -1124,7 +1126,7 @@ namespace rct {
} }
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask, hw::device &hwdev) { xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask, hw::device &hwdev) {
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof, false, "decodeRct called on non simple rctSig"); CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2, false, "decodeRct called on non simple rctSig");
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index"); CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo"); CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo");
@ -1154,7 +1156,7 @@ namespace rct {
} }
bool signMultisig(rctSig &rv, const std::vector<unsigned int> &indices, const keyV &k, const multisig_out &msout, const key &secret_key) { bool signMultisig(rctSig &rv, const std::vector<unsigned int> &indices, const keyV &k, const multisig_out &msout, const key &secret_key) {
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull || rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof, CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull || rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2,
false, "unsupported rct type"); false, "unsupported rct type");
CHECK_AND_ASSERT_MES(indices.size() == k.size(), false, "Mismatched k/indices sizes"); CHECK_AND_ASSERT_MES(indices.size() == k.size(), false, "Mismatched k/indices sizes");
CHECK_AND_ASSERT_MES(k.size() == rv.p.MGs.size(), false, "Mismatched k/MGs size"); CHECK_AND_ASSERT_MES(k.size() == rv.p.MGs.size(), false, "Mismatched k/MGs size");

@ -119,10 +119,10 @@ namespace rct {
//decodeRct: (c.f. https://eprint.iacr.org/2015/1098 section 5.1.1) //decodeRct: (c.f. https://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 std::vector<xmr_amount> & amounts, const ctkeyM &mixRing, const keyV &amount_keys, const multisig_kLRki *kLRki, multisig_out *msout, unsigned int index, ctkeyV &outSk, hw::device &hwdev); rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const std::vector<xmr_amount> & amounts, const ctkeyM &mixRing, const keyV &amount_keys, const multisig_kLRki *kLRki, multisig_out *msout, unsigned int index, ctkeyV &outSk, const RCTConfig &rct_config, hw::device &hwdev);
rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const std::vector<xmr_amount> & amounts, const keyV &amount_keys, const multisig_kLRki *kLRki, multisig_out *msout, const int mixin, hw::device &hwdev); rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const std::vector<xmr_amount> & amounts, const keyV &amount_keys, const multisig_kLRki *kLRki, multisig_out *msout, const int mixin, const RCTConfig &rct_config, hw::device &hwdev);
rctSig genRctSimple(const key & message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const std::vector<xmr_amount> & inamounts, const std::vector<xmr_amount> & outamounts, const keyV &amount_keys, const std::vector<multisig_kLRki> *kLRki, multisig_out *msout, xmr_amount txnFee, unsigned int mixin, hw::device &hwdev); rctSig genRctSimple(const key & message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const std::vector<xmr_amount> & inamounts, const std::vector<xmr_amount> & outamounts, const keyV &amount_keys, const std::vector<multisig_kLRki> *kLRki, multisig_out *msout, xmr_amount txnFee, unsigned int mixin, const RCTConfig &rct_config, hw::device &hwdev);
rctSig genRctSimple(const key & message, const ctkeyV & inSk, const keyV & destinations, const std::vector<xmr_amount> & inamounts, const std::vector<xmr_amount> & outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const keyV &amount_keys, const std::vector<multisig_kLRki> *kLRki, multisig_out *msout, const std::vector<unsigned int> & index, ctkeyV &outSk, RangeProofType range_proof_type, hw::device &hwdev); rctSig genRctSimple(const key & message, const ctkeyV & inSk, const keyV & destinations, const std::vector<xmr_amount> & inamounts, const std::vector<xmr_amount> & outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const keyV &amount_keys, const std::vector<multisig_kLRki> *kLRki, multisig_out *msout, const std::vector<unsigned int> & index, ctkeyV &outSk, const RCTConfig &rct_config, hw::device &hwdev);
bool verRct(const rctSig & rv, bool semantics); bool verRct(const rctSig & rv, bool semantics);
static inline bool verRct(const rctSig & rv) { return verRct(rv, true) && verRct(rv, false); } static inline bool verRct(const rctSig & rv) { return verRct(rv, true) && verRct(rv, false); }
bool verRctSemanticsSimple(const rctSig & rv); bool verRctSemanticsSimple(const rctSig & rv);

@ -217,6 +217,7 @@ namespace rct {
{ {
case RCTTypeSimple: case RCTTypeSimple:
case RCTTypeBulletproof: case RCTTypeBulletproof:
case RCTTypeBulletproof2:
return true; return true;
default: default:
return false; return false;
@ -228,6 +229,7 @@ namespace rct {
switch (type) switch (type)
{ {
case RCTTypeBulletproof: case RCTTypeBulletproof:
case RCTTypeBulletproof2:
return true; return true;
default: default:
return false; return false;

@ -230,8 +230,13 @@ namespace rct {
RCTTypeFull = 1, RCTTypeFull = 1,
RCTTypeSimple = 2, RCTTypeSimple = 2,
RCTTypeBulletproof = 3, RCTTypeBulletproof = 3,
RCTTypeBulletproof2 = 4,
}; };
enum RangeProofType { RangeProofBorromean, RangeProofBulletproof, RangeProofMultiOutputBulletproof, RangeProofPaddedBulletproof }; enum RangeProofType { RangeProofBorromean, RangeProofBulletproof, RangeProofMultiOutputBulletproof, RangeProofPaddedBulletproof };
struct RCTConfig {
RangeProofType range_proof_type;
int bp_version;
};
struct rctSigBase { struct rctSigBase {
uint8_t type; uint8_t type;
key message; key message;
@ -248,7 +253,7 @@ namespace rct {
FIELD(type) FIELD(type)
if (type == RCTTypeNull) if (type == RCTTypeNull)
return true; return true;
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof) if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2)
return false; return false;
VARINT_FIELD(txnFee) VARINT_FIELD(txnFee)
// inputs/outputs not saved, only here for serialization help // inputs/outputs not saved, only here for serialization help
@ -309,9 +314,9 @@ namespace rct {
{ {
if (type == RCTTypeNull) if (type == RCTTypeNull)
return true; return true;
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof) if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2)
return false; return false;
if (type == RCTTypeBulletproof) if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2)
{ {
uint32_t nbp = bulletproofs.size(); uint32_t nbp = bulletproofs.size();
FIELD(nbp) FIELD(nbp)
@ -350,7 +355,7 @@ namespace rct {
ar.begin_array(); ar.begin_array();
// we keep a byte for size of MGs, because we don't know whether this is // we keep a byte for size of MGs, because we don't know whether this is
// a simple or full rct signature, and it's starting to annoy the hell out of me // a simple or full rct signature, and it's starting to annoy the hell out of me
size_t mg_elements = (type == RCTTypeSimple || type == RCTTypeBulletproof) ? inputs : 1; size_t mg_elements = (type == RCTTypeSimple || type == RCTTypeBulletproof || type == RCTTypeBulletproof2) ? inputs : 1;
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_elements, MGs); PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_elements, MGs);
if (MGs.size() != mg_elements) if (MGs.size() != mg_elements)
return false; return false;
@ -368,7 +373,7 @@ namespace rct {
for (size_t j = 0; j < mixin + 1; ++j) for (size_t j = 0; j < mixin + 1; ++j)
{ {
ar.begin_array(); ar.begin_array();
size_t mg_ss2_elements = ((type == RCTTypeSimple || type == RCTTypeBulletproof) ? 1 : inputs) + 1; size_t mg_ss2_elements = ((type == RCTTypeSimple || type == RCTTypeBulletproof || type == RCTTypeBulletproof2) ? 1 : inputs) + 1;
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_ss2_elements, MGs[i].ss[j]); PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_ss2_elements, MGs[i].ss[j]);
if (MGs[i].ss[j].size() != mg_ss2_elements) if (MGs[i].ss[j].size() != mg_ss2_elements)
return false; return false;
@ -394,7 +399,7 @@ namespace rct {
ar.delimit_array(); ar.delimit_array();
} }
ar.end_array(); ar.end_array();
if (type == RCTTypeBulletproof) if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2)
{ {
ar.tag("pseudoOuts"); ar.tag("pseudoOuts");
ar.begin_array(); ar.begin_array();
@ -418,12 +423,12 @@ namespace rct {
keyV& get_pseudo_outs() keyV& get_pseudo_outs()
{ {
return type == RCTTypeBulletproof ? p.pseudoOuts : pseudoOuts; return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 ? p.pseudoOuts : pseudoOuts;
} }
keyV const& get_pseudo_outs() const keyV const& get_pseudo_outs() const
{ {
return type == RCTTypeBulletproof ? p.pseudoOuts : pseudoOuts; return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 ? p.pseudoOuts : pseudoOuts;
} }
}; };

@ -1281,6 +1281,7 @@ static uint64_t decodeRct(const rct::rctSig & rv, const crypto::key_derivation &
{ {
case rct::RCTTypeSimple: case rct::RCTTypeSimple:
case rct::RCTTypeBulletproof: case rct::RCTTypeBulletproof:
case rct::RCTTypeBulletproof2:
return rct::decodeRctSimple(rv, rct::sk2rct(scalar1), i, mask, hwdev); return rct::decodeRctSimple(rv, rct::sk2rct(scalar1), i, mask, hwdev);
case rct::RCTTypeFull: case rct::RCTTypeFull:
return rct::decodeRct(rv, rct::sk2rct(scalar1), i, mask, hwdev); return rct::decodeRct(rv, rct::sk2rct(scalar1), i, mask, hwdev);
@ -5563,15 +5564,16 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin
LOG_PRINT_L1(" " << (n+1) << ": " << sd.sources.size() << " inputs, ring size " << sd.sources[0].outputs.size()); LOG_PRINT_L1(" " << (n+1) << ": " << sd.sources.size() << " inputs, ring size " << sd.sources[0].outputs.size());
signed_txes.ptx.push_back(pending_tx()); signed_txes.ptx.push_back(pending_tx());
tools::wallet2::pending_tx &ptx = signed_txes.ptx.back(); tools::wallet2::pending_tx &ptx = signed_txes.ptx.back();
rct::RangeProofType range_proof_type = rct::RangeProofBorromean; rct::RCTConfig rct_config = { rct::RangeProofBorromean, 0 };
if (sd.use_bulletproofs) if (sd.use_bulletproofs)
{ {
range_proof_type = rct::RangeProofPaddedBulletproof; rct_config.range_proof_type = rct::RangeProofPaddedBulletproof;
rct_config.bp_version = use_fork_rules(HF_VERSION_SMALLER_BP, -10) ? 2 : 1;
} }
crypto::secret_key tx_key; crypto::secret_key tx_key;
std::vector<crypto::secret_key> additional_tx_keys; std::vector<crypto::secret_key> additional_tx_keys;
rct::multisig_out msout; rct::multisig_out msout;
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, range_proof_type, m_multisig ? &msout : NULL); 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, m_multisig ? &msout : NULL);
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype); 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, // 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, // and it's a bit pointless to fail there anyway, since it'd be a (good) guess only. We sign anyway,
@ -5984,15 +5986,16 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector<crypto
cryptonote::transaction tx; cryptonote::transaction tx;
rct::multisig_out msout = ptx.multisig_sigs.front().msout; rct::multisig_out msout = ptx.multisig_sigs.front().msout;
auto sources = sd.sources; auto sources = sd.sources;
rct::RangeProofType range_proof_type = rct::RangeProofBorromean; rct::RCTConfig rct_config = { rct::RangeProofBorromean, 0 };
if (sd.use_bulletproofs) if (sd.use_bulletproofs)
{ {
range_proof_type = rct::RangeProofBulletproof; rct_config.range_proof_type = rct::RangeProofBulletproof;
for (const rct::Bulletproof &proof: ptx.tx.rct_signatures.p.bulletproofs) for (const rct::Bulletproof &proof: ptx.tx.rct_signatures.p.bulletproofs)
if (proof.V.size() > 1) if (proof.V.size() > 1)
range_proof_type = rct::RangeProofPaddedBulletproof; rct_config.range_proof_type = rct::RangeProofPaddedBulletproof;
rct_config.bp_version = use_fork_rules(HF_VERSION_SMALLER_BP, -10) ? 2 : 1;
} }
bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources, sd.splitted_dsts, ptx.change_dts.addr, sd.extra, tx, sd.unlock_time, ptx.tx_key, ptx.additional_tx_keys, sd.use_rct, range_proof_type, &msout, false); bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources, sd.splitted_dsts, ptx.change_dts.addr, sd.extra, tx, sd.unlock_time, ptx.tx_key, ptx.additional_tx_keys, sd.use_rct, rct_config, &msout, false);
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype);
THROW_WALLET_EXCEPTION_IF(get_transaction_prefix_hash (tx) != get_transaction_prefix_hash(ptx.tx), THROW_WALLET_EXCEPTION_IF(get_transaction_prefix_hash (tx) != get_transaction_prefix_hash(ptx.tx),
@ -7353,7 +7356,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
std::vector<crypto::secret_key> additional_tx_keys; std::vector<crypto::secret_key> additional_tx_keys;
rct::multisig_out msout; rct::multisig_out msout;
LOG_PRINT_L2("constructing tx"); 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, rct::RangeProofBulletproof, m_multisig ? &msout : NULL); 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, {}, m_multisig ? &msout : NULL);
LOG_PRINT_L2("constructed tx, r="<<r); 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(!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); THROW_WALLET_EXCEPTION_IF(upper_transaction_weight_limit <= get_transaction_weight(tx), error::tx_too_big, tx, upper_transaction_weight_limit);
@ -7402,7 +7405,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry> dsts, const std::vector<size_t>& selected_transfers, size_t fake_outputs_count, 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::vector<std::vector<tools::wallet2::get_outs_entry>> &outs,
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx &ptx, rct::RangeProofType range_proof_type) uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx &ptx, const rct::RCTConfig &rct_config)
{ {
using namespace cryptonote; using namespace cryptonote;
// throw if attempting a transaction with no destinations // throw if attempting a transaction with no destinations
@ -7558,7 +7561,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
rct::multisig_out msout; rct::multisig_out msout;
LOG_PRINT_L2("constructing tx"); LOG_PRINT_L2("constructing tx");
auto sources_copy = sources; auto sources_copy = sources;
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, range_proof_type, m_multisig ? &msout : NULL); 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, m_multisig ? &msout : NULL);
LOG_PRINT_L2("constructed tx, r="<<r); LOG_PRINT_L2("constructed tx, r="<<r);
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, dsts, unlock_time, m_nettype); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, 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); THROW_WALLET_EXCEPTION_IF(upper_transaction_weight_limit <= get_transaction_weight(tx), error::tx_too_big, tx, upper_transaction_weight_limit);
@ -7603,7 +7606,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
LOG_PRINT_L2("Creating supplementary multisig transaction"); LOG_PRINT_L2("Creating supplementary multisig transaction");
cryptonote::transaction ms_tx; cryptonote::transaction ms_tx;
auto sources_copy_copy = sources_copy; auto sources_copy_copy = sources_copy;
bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources_copy_copy, splitted_dsts, change_dts.addr, extra, ms_tx, unlock_time,tx_key, additional_tx_keys, true, range_proof_type, &msout, false); bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources_copy_copy, splitted_dsts, change_dts.addr, extra, ms_tx, unlock_time,tx_key, additional_tx_keys, true, rct_config, &msout, false);
LOG_PRINT_L2("constructed tx, r="<<r); 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(!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); THROW_WALLET_EXCEPTION_IF(upper_transaction_weight_limit <= get_transaction_weight(tx), error::tx_too_big, tx, upper_transaction_weight_limit);
@ -8314,7 +8317,10 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE, 0); const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE, 0);
const bool use_rct = use_fork_rules(4, 0); const bool use_rct = use_fork_rules(4, 0);
const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0); const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
const rct::RangeProofType range_proof_type = bulletproof ? rct::RangeProofPaddedBulletproof : rct::RangeProofBorromean; const rct::RCTConfig rct_config {
bulletproof ? rct::RangeProofPaddedBulletproof : rct::RangeProofBorromean,
bulletproof ? (use_fork_rules(HF_VERSION_SMALLER_BP, -10) ? 2 : 1) : 0
};
const uint64_t base_fee = get_base_fee(); const uint64_t base_fee = get_base_fee();
const uint64_t fee_multiplier = get_fee_multiplier(priority, get_fee_algorithm()); const uint64_t fee_multiplier = get_fee_multiplier(priority, get_fee_algorithm());
@ -8631,7 +8637,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
tx.selected_transfers.size() << " inputs"); tx.selected_transfers.size() << " inputs");
if (use_rct) if (use_rct)
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
test_tx, test_ptx, range_proof_type); test_tx, test_ptx, rct_config);
else else
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
@ -8674,7 +8680,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
while (needed_fee > test_ptx.fee) { while (needed_fee > test_ptx.fee) {
if (use_rct) if (use_rct)
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
test_tx, test_ptx, range_proof_type); test_tx, test_ptx, rct_config);
else else
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
@ -8747,7 +8753,7 @@ skip_tx:
extra, /* const std::vector<uint8_t>& extra, */ extra, /* const std::vector<uint8_t>& extra, */
test_tx, /* OUT cryptonote::transaction& tx, */ test_tx, /* OUT cryptonote::transaction& tx, */
test_ptx, /* OUT cryptonote::transaction& tx, */ test_ptx, /* OUT cryptonote::transaction& tx, */
range_proof_type); rct_config);
} else { } else {
transfer_selected(tx.dsts, transfer_selected(tx.dsts,
tx.selected_transfers, tx.selected_transfers,
@ -8887,7 +8893,10 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE); const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE);
const bool use_rct = fake_outs_count > 0 && use_fork_rules(4, 0); const bool use_rct = fake_outs_count > 0 && use_fork_rules(4, 0);
const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0); const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
const rct::RangeProofType range_proof_type = bulletproof ? rct::RangeProofPaddedBulletproof : rct::RangeProofBorromean; const rct::RCTConfig rct_config {
bulletproof ? rct::RangeProofPaddedBulletproof : rct::RangeProofBorromean,
bulletproof ? (use_fork_rules(HF_VERSION_SMALLER_BP, -10) ? 2 : 1) : 0,
};
const uint64_t base_fee = get_base_fee(); const uint64_t base_fee = get_base_fee();
const uint64_t fee_multiplier = get_fee_multiplier(priority, get_fee_algorithm()); const uint64_t fee_multiplier = get_fee_multiplier(priority, get_fee_algorithm());
const uint64_t fee_quantization_mask = get_fee_quantization_mask(); const uint64_t fee_quantization_mask = get_fee_quantization_mask();
@ -8963,7 +8972,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
tx.selected_transfers.size() << " outputs"); tx.selected_transfers.size() << " outputs");
if (use_rct) if (use_rct)
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
test_tx, test_ptx, range_proof_type); test_tx, test_ptx, rct_config);
else else
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
@ -9000,7 +9009,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
} }
if (use_rct) if (use_rct)
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
test_tx, test_ptx, range_proof_type); test_tx, test_ptx, rct_config);
else else
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
@ -9039,7 +9048,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
pending_tx test_ptx; pending_tx test_ptx;
if (use_rct) { if (use_rct) {
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, tx.needed_fee, extra, transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, tx.needed_fee, extra,
test_tx, test_ptx, range_proof_type); test_tx, test_ptx, rct_config);
} else { } else {
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, tx.needed_fee, extra, transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, tx.needed_fee, extra,
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);

@ -738,7 +738,7 @@ namespace tools
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); 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);
void transfer_selected_rct(std::vector<cryptonote::tx_destination_entry> dsts, const std::vector<size_t>& selected_transfers, size_t fake_outputs_count, 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::vector<std::vector<tools::wallet2::get_outs_entry>> &outs,
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx &ptx, rct::RangeProofType range_proof_type); uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx &ptx, const rct::RCTConfig &rct_config);
void commit_tx(pending_tx& ptx_vector); void commit_tx(pending_tx& ptx_vector);
void commit_tx(std::vector<pending_tx>& ptx_vector); void commit_tx(std::vector<pending_tx>& ptx_vector);

@ -42,7 +42,7 @@ using namespace cryptonote;
// Tests // Tests
bool gen_bp_tx_validation_base::generate_with(std::vector<test_event_entry>& events, bool gen_bp_tx_validation_base::generate_with(std::vector<test_event_entry>& events,
size_t mixin, size_t n_txes, const uint64_t *amounts_paid, bool valid, const rct::RangeProofType *range_proof_type, size_t mixin, size_t n_txes, const uint64_t *amounts_paid, bool valid, const rct::RCTConfig *rct_config,
const std::function<bool(std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations, size_t tx_idx)> &pre_tx, const std::function<bool(std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations, size_t tx_idx)> &pre_tx,
const std::function<bool(transaction &tx, size_t tx_idx)> &post_tx) const const std::function<bool(transaction &tx, size_t tx_idx)> &post_tx) const
{ {
@ -136,7 +136,7 @@ bool gen_bp_tx_validation_base::generate_with(std::vector<test_event_entry>& eve
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses; std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
subaddresses[miner_accounts[n].get_keys().m_account_address.m_spend_public_key] = {0,0}; subaddresses[miner_accounts[n].get_keys().m_account_address.m_spend_public_key] = {0,0};
rct_txes.resize(rct_txes.size() + 1); rct_txes.resize(rct_txes.size() + 1);
bool r = construct_tx_and_get_tx_key(miner_accounts[n].get_keys(), subaddresses, sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), rct_txes.back(), 0, tx_key, additional_tx_keys, true, range_proof_type[n]); bool r = construct_tx_and_get_tx_key(miner_accounts[n].get_keys(), subaddresses, sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), rct_txes.back(), 0, tx_key, additional_tx_keys, true, rct_config[n]);
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction"); CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
if (post_tx && !post_tx(rct_txes.back(), n)) if (post_tx && !post_tx(rct_txes.back(), n))
@ -157,7 +157,8 @@ bool gen_bp_tx_validation_base::generate_with(std::vector<test_event_entry>& eve
crypto::secret_key amount_key; crypto::secret_key amount_key;
crypto::derivation_to_scalar(derivation, o, amount_key); crypto::derivation_to_scalar(derivation, o, amount_key);
rct::key rct_tx_mask; rct::key rct_tx_mask;
if (rct_txes.back().rct_signatures.type == rct::RCTTypeSimple || rct_txes.back().rct_signatures.type == rct::RCTTypeBulletproof) const uint8_t type = rct_txes.back().rct_signatures.type;
if (type == rct::RCTTypeSimple || type == rct::RCTTypeBulletproof || type == rct::RCTTypeBulletproof2)
rct::decodeRctSimple(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default")); rct::decodeRctSimple(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default"));
else else
rct::decodeRct(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default")); rct::decodeRct(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default"));
@ -173,8 +174,8 @@ bool gen_bp_tx_validation_base::generate_with(std::vector<test_event_entry>& eve
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk_txes, blk_last, miner_account, CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk_txes, blk_last, miner_account,
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_tx_hashes | test_generator::bf_hf_version | test_generator::bf_max_outs, test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_tx_hashes | test_generator::bf_hf_version | test_generator::bf_max_outs,
8, 8, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long 10, 10, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
crypto::hash(), 0, transaction(), starting_rct_tx_hashes, 0, 6, 8), crypto::hash(), 0, transaction(), starting_rct_tx_hashes, 0, 6, 10),
false, "Failed to generate block"); false, "Failed to generate block");
if (!valid) if (!valid)
DO_CALLBACK(events, "mark_invalid_block"); DO_CALLBACK(events, "mark_invalid_block");
@ -210,16 +211,16 @@ bool gen_bp_tx_valid_1::generate(std::vector<test_event_entry>& events) const
const size_t mixin = 10; const size_t mixin = 10;
const uint64_t amounts_paid[] = {10000, (uint64_t)-1}; const uint64_t amounts_paid[] = {10000, (uint64_t)-1};
const size_t bp_sizes[] = {1, (size_t)-1}; const size_t bp_sizes[] = {1, (size_t)-1};
const rct::RangeProofType range_proof_type[] = {rct::RangeProofPaddedBulletproof}; const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 0 } };
return generate_with(events, mixin, 1, amounts_paid, true, range_proof_type, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_1"); }); return generate_with(events, mixin, 1, amounts_paid, true, rct_config, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_1"); });
} }
bool gen_bp_tx_invalid_1_1::generate(std::vector<test_event_entry>& events) const bool gen_bp_tx_invalid_1_1::generate(std::vector<test_event_entry>& events) const
{ {
const size_t mixin = 10; const size_t mixin = 10;
const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1}; const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1};
const rct::RangeProofType range_proof_type[] = { rct::RangeProofBulletproof }; const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof , 0 } };
return generate_with(events, mixin, 1, amounts_paid, false, range_proof_type, NULL, NULL); return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, NULL);
} }
bool gen_bp_tx_valid_2::generate(std::vector<test_event_entry>& events) const bool gen_bp_tx_valid_2::generate(std::vector<test_event_entry>& events) const
@ -227,8 +228,8 @@ bool gen_bp_tx_valid_2::generate(std::vector<test_event_entry>& events) const
const size_t mixin = 10; const size_t mixin = 10;
const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1}; const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1};
const size_t bp_sizes[] = {2, (size_t)-1}; const size_t bp_sizes[] = {2, (size_t)-1};
const rct::RangeProofType range_proof_type[] = {rct::RangeProofPaddedBulletproof}; const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 0 } };
return generate_with(events, mixin, 1, amounts_paid, true, range_proof_type, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_2"); }); return generate_with(events, mixin, 1, amounts_paid, true, rct_config, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_2"); });
} }
bool gen_bp_tx_valid_3::generate(std::vector<test_event_entry>& events) const bool gen_bp_tx_valid_3::generate(std::vector<test_event_entry>& events) const
@ -236,8 +237,8 @@ bool gen_bp_tx_valid_3::generate(std::vector<test_event_entry>& events) const
const size_t mixin = 10; const size_t mixin = 10;
const uint64_t amounts_paid[] = {5000, 5000, 5000, (uint64_t)-1}; const uint64_t amounts_paid[] = {5000, 5000, 5000, (uint64_t)-1};
const size_t bp_sizes[] = {4, (size_t)-1}; const size_t bp_sizes[] = {4, (size_t)-1};
const rct::RangeProofType range_proof_type[] = { rct::RangeProofPaddedBulletproof }; const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof , 0 } };
return generate_with(events, mixin, 1, amounts_paid, true, range_proof_type, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_3"); }); return generate_with(events, mixin, 1, amounts_paid, true, rct_config, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_3"); });
} }
bool gen_bp_tx_valid_16::generate(std::vector<test_event_entry>& events) const bool gen_bp_tx_valid_16::generate(std::vector<test_event_entry>& events) const
@ -245,24 +246,24 @@ bool gen_bp_tx_valid_16::generate(std::vector<test_event_entry>& events) const
const size_t mixin = 10; const size_t mixin = 10;
const uint64_t amounts_paid[] = {500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, (uint64_t)-1}; const uint64_t amounts_paid[] = {500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, (uint64_t)-1};
const size_t bp_sizes[] = {16, (size_t)-1}; const size_t bp_sizes[] = {16, (size_t)-1};
const rct::RangeProofType range_proof_type[] = { rct::RangeProofPaddedBulletproof }; const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof , 0 } };
return generate_with(events, mixin, 1, amounts_paid, true, range_proof_type, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_16"); }); return generate_with(events, mixin, 1, amounts_paid, true, rct_config, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_16"); });
} }
bool gen_bp_tx_invalid_4_2_1::generate(std::vector<test_event_entry>& events) const bool gen_bp_tx_invalid_4_2_1::generate(std::vector<test_event_entry>& events) const
{ {
const size_t mixin = 10; const size_t mixin = 10;
const uint64_t amounts_paid[] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1}; const uint64_t amounts_paid[] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1};
const rct::RangeProofType range_proof_type[] = { rct::RangeProofMultiOutputBulletproof }; const rct::RCTConfig rct_config[] = { { rct::RangeProofMultiOutputBulletproof , 0 } };
return generate_with(events, mixin, 1, amounts_paid, false, range_proof_type, NULL, NULL); return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, NULL);
} }
bool gen_bp_tx_invalid_16_16::generate(std::vector<test_event_entry>& events) const bool gen_bp_tx_invalid_16_16::generate(std::vector<test_event_entry>& events) const
{ {
const size_t mixin = 10; const size_t mixin = 10;
const uint64_t amounts_paid[] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1}; const uint64_t amounts_paid[] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1};
const rct::RangeProofType range_proof_type[] = { rct::RangeProofMultiOutputBulletproof }; const rct::RCTConfig rct_config[] = { { rct::RangeProofMultiOutputBulletproof , 0 } };
return generate_with(events, mixin, 1, amounts_paid, false, range_proof_type, NULL, NULL); return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, NULL);
} }
bool gen_bp_txs_valid_2_and_2::generate(std::vector<test_event_entry>& events) const bool gen_bp_txs_valid_2_and_2::generate(std::vector<test_event_entry>& events) const
@ -270,25 +271,25 @@ bool gen_bp_txs_valid_2_and_2::generate(std::vector<test_event_entry>& events) c
const size_t mixin = 10; const size_t mixin = 10;
const uint64_t amounts_paid[] = {1000, 1000, (size_t)-1, 1000, 1000, (uint64_t)-1}; const uint64_t amounts_paid[] = {1000, 1000, (size_t)-1, 1000, 1000, (uint64_t)-1};
const size_t bp_sizes[] = {2, (size_t)-1, 2, (size_t)-1}; const size_t bp_sizes[] = {2, (size_t)-1, 2, (size_t)-1};
const rct::RangeProofType range_proof_type[] = { rct::RangeProofPaddedBulletproof, rct::RangeProofPaddedBulletproof}; const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 0 }, {rct::RangeProofPaddedBulletproof, 0 } };
return generate_with(events, mixin, 2, amounts_paid, true, range_proof_type, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_txs_valid_2_and_2"); }); return generate_with(events, mixin, 2, amounts_paid, true, rct_config, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_txs_valid_2_and_2"); });
} }
bool gen_bp_txs_invalid_2_and_8_2_and_16_16_1::generate(std::vector<test_event_entry>& events) const bool gen_bp_txs_invalid_2_and_8_2_and_16_16_1::generate(std::vector<test_event_entry>& events) const
{ {
const size_t mixin = 10; const size_t mixin = 10;
const uint64_t amounts_paid[] = {1000, 1000, (uint64_t)-1, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1}; const uint64_t amounts_paid[] = {1000, 1000, (uint64_t)-1, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1};
const rct::RangeProofType range_proof_type[] = {rct::RangeProofMultiOutputBulletproof, rct::RangeProofMultiOutputBulletproof, rct::RangeProofMultiOutputBulletproof}; const rct::RCTConfig rct_config[] = {{rct::RangeProofMultiOutputBulletproof, 0}, {rct::RangeProofMultiOutputBulletproof, 0}, {rct::RangeProofMultiOutputBulletproof, 0}};
return generate_with(events, mixin, 3, amounts_paid, false, range_proof_type, NULL, NULL); return generate_with(events, mixin, 3, amounts_paid, false, rct_config, NULL, NULL);
} }
bool gen_bp_txs_valid_2_and_3_and_2_and_4::generate(std::vector<test_event_entry>& events) const bool gen_bp_txs_valid_2_and_3_and_2_and_4::generate(std::vector<test_event_entry>& events) const
{ {
const size_t mixin = 10; const size_t mixin = 10;
const uint64_t amounts_paid[] = {11111115000, 11111115000, (uint64_t)-1, 11111115000, 11111115000, 11111115001, (uint64_t)-1, 11111115000, 11111115002, (uint64_t)-1, 11111115000, 11111115000, 11111115000, 11111115003, (uint64_t)-1}; const uint64_t amounts_paid[] = {11111115000, 11111115000, (uint64_t)-1, 11111115000, 11111115000, 11111115001, (uint64_t)-1, 11111115000, 11111115002, (uint64_t)-1, 11111115000, 11111115000, 11111115000, 11111115003, (uint64_t)-1};
const rct::RangeProofType range_proof_type[] = {rct::RangeProofPaddedBulletproof, rct::RangeProofPaddedBulletproof, rct::RangeProofPaddedBulletproof, rct::RangeProofPaddedBulletproof}; const rct::RCTConfig rct_config[] = {{rct::RangeProofPaddedBulletproof, 0}, {rct::RangeProofPaddedBulletproof, 0}, {rct::RangeProofPaddedBulletproof, 0}, {rct::RangeProofPaddedBulletproof, 0}};
const size_t bp_sizes[] = {2, (size_t)-1, 4, (size_t)-1, 2, (size_t)-1, 4, (size_t)-1}; const size_t bp_sizes[] = {2, (size_t)-1, 4, (size_t)-1, 2, (size_t)-1, 4, (size_t)-1};
return generate_with(events, mixin, 4, amounts_paid, true, range_proof_type, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx) { return check_bp(tx, tx_idx, bp_sizes, "gen_bp_txs_valid_2_and_3_and_2_and_4"); }); return generate_with(events, mixin, 4, amounts_paid, true, rct_config, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx) { return check_bp(tx, tx_idx, bp_sizes, "gen_bp_txs_valid_2_and_3_and_2_and_4"); });
} }
bool gen_bp_tx_invalid_not_enough_proofs::generate(std::vector<test_event_entry>& events) const bool gen_bp_tx_invalid_not_enough_proofs::generate(std::vector<test_event_entry>& events) const
@ -296,9 +297,9 @@ bool gen_bp_tx_invalid_not_enough_proofs::generate(std::vector<test_event_entry>
DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_not_enough_proofs"); DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_not_enough_proofs");
const size_t mixin = 10; const size_t mixin = 10;
const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1}; const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1};
const rct::RangeProofType range_proof_type[] = { rct::RangeProofBulletproof }; const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 0 } };
return generate_with(events, mixin, 1, amounts_paid, false, range_proof_type, NULL, [&](cryptonote::transaction &tx, size_t idx){ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, [&](cryptonote::transaction &tx, size_t idx){
CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof); CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2);
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs.empty()); CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs.empty());
tx.rct_signatures.p.bulletproofs.pop_back(); tx.rct_signatures.p.bulletproofs.pop_back();
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs.empty()); CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs.empty());
@ -311,9 +312,9 @@ bool gen_bp_tx_invalid_empty_proofs::generate(std::vector<test_event_entry>& eve
DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_empty_proofs"); DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_empty_proofs");
const size_t mixin = 10; const size_t mixin = 10;
const uint64_t amounts_paid[] = {50000, 50000, (uint64_t)-1}; const uint64_t amounts_paid[] = {50000, 50000, (uint64_t)-1};
const rct::RangeProofType range_proof_type[] = { rct::RangeProofBulletproof }; const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 0 } };
return generate_with(events, mixin, 1, amounts_paid, false, range_proof_type, NULL, [&](cryptonote::transaction &tx, size_t idx){ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, [&](cryptonote::transaction &tx, size_t idx){
CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof); CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2);
tx.rct_signatures.p.bulletproofs.clear(); tx.rct_signatures.p.bulletproofs.clear();
return true; return true;
}); });
@ -324,9 +325,9 @@ bool gen_bp_tx_invalid_too_many_proofs::generate(std::vector<test_event_entry>&
DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_too_many_proofs"); DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_too_many_proofs");
const size_t mixin = 10; const size_t mixin = 10;
const uint64_t amounts_paid[] = {10000, (uint64_t)-1}; const uint64_t amounts_paid[] = {10000, (uint64_t)-1};
const rct::RangeProofType range_proof_type[] = { rct::RangeProofBulletproof }; const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 0 } };
return generate_with(events, mixin, 1, amounts_paid, false, range_proof_type, NULL, [&](cryptonote::transaction &tx, size_t idx){ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, [&](cryptonote::transaction &tx, size_t idx){
CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof); CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2);
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs.empty()); CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs.empty());
tx.rct_signatures.p.bulletproofs.push_back(tx.rct_signatures.p.bulletproofs.back()); tx.rct_signatures.p.bulletproofs.push_back(tx.rct_signatures.p.bulletproofs.back());
return true; return true;
@ -338,9 +339,9 @@ bool gen_bp_tx_invalid_wrong_amount::generate(std::vector<test_event_entry>& eve
DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_wrong_amount"); DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_wrong_amount");
const size_t mixin = 10; const size_t mixin = 10;
const uint64_t amounts_paid[] = {10000, (uint64_t)-1}; const uint64_t amounts_paid[] = {10000, (uint64_t)-1};
const rct::RangeProofType range_proof_type[] = { rct::RangeProofBulletproof }; const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 0 } };
return generate_with(events, mixin, 1, amounts_paid, false, range_proof_type, NULL, [&](cryptonote::transaction &tx, size_t idx){ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, [&](cryptonote::transaction &tx, size_t idx){
CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof); CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2);
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs.empty()); CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs.empty());
tx.rct_signatures.p.bulletproofs.back() = rct::bulletproof_PROVE(1000, rct::skGen()); tx.rct_signatures.p.bulletproofs.back() = rct::bulletproof_PROVE(1000, rct::skGen());
return true; return true;
@ -352,10 +353,8 @@ bool gen_bp_tx_invalid_borromean_type::generate(std::vector<test_event_entry>& e
DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_borromean_type"); DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_borromean_type");
const size_t mixin = 10; const size_t mixin = 10;
const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1}; const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1};
const rct::RangeProofType range_proof_type[] = {rct::RangeProofPaddedBulletproof}; const rct::RCTConfig rct_config[] = { { rct::RangeProofBorromean, 0 } };
return generate_with(events, mixin, 1, amounts_paid, false, range_proof_type, NULL, [&](cryptonote::transaction &tx, size_t tx_idx){ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, [&](cryptonote::transaction &tx, size_t tx_idx){
CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof);
tx.rct_signatures.type = rct::RCTTypeSimple;
return true; return true;
}); });
} }

@ -82,7 +82,7 @@ struct gen_bp_tx_validation_base : public test_chain_unit_base
} }
bool generate_with(std::vector<test_event_entry>& events, size_t mixin, bool generate_with(std::vector<test_event_entry>& events, size_t mixin,
size_t n_txes, const uint64_t *amounts_paid, bool valid, const rct::RangeProofType *range_proof_type, size_t n_txes, const uint64_t *amounts_paid, bool valid, const rct::RCTConfig *rct_config,
const std::function<bool(std::vector<cryptonote::tx_source_entry> &sources, std::vector<cryptonote::tx_destination_entry> &destinations, size_t)> &pre_tx, const std::function<bool(std::vector<cryptonote::tx_source_entry> &sources, std::vector<cryptonote::tx_destination_entry> &destinations, size_t)> &pre_tx,
const std::function<bool(cryptonote::transaction &tx, size_t)> &post_tx) const; const std::function<bool(cryptonote::transaction &tx, size_t)> &post_tx) const;
@ -95,7 +95,7 @@ private:
template<> template<>
struct get_test_options<gen_bp_tx_validation_base> { struct get_test_options<gen_bp_tx_validation_base> {
const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(8, 73), std::make_pair(0, 0)}; const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(10, 73), std::make_pair(0, 0)};
const cryptonote::test_options test_options = { const cryptonote::test_options test_options = {
hard_forks hard_forks
}; };

@ -365,7 +365,7 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
#endif #endif
std::vector<crypto::secret_key> additional_tx_secret_keys; std::vector<crypto::secret_key> additional_tx_secret_keys;
auto sources_copy = sources; auto sources_copy = sources;
r = construct_tx_and_get_tx_key(miner_account[creator].get_keys(), subaddresses, sources, destinations, boost::none, std::vector<uint8_t>(), tx, 0, tx_key, additional_tx_secret_keys, true, rct::RangeProofBorromean, msoutp); r = construct_tx_and_get_tx_key(miner_account[creator].get_keys(), subaddresses, sources, destinations, boost::none, std::vector<uint8_t>(), tx, 0, tx_key, additional_tx_secret_keys, true, { rct::RangeProofBorromean, 0 }, msoutp);
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction"); CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
#ifndef NO_MULTISIG #ifndef NO_MULTISIG

@ -133,7 +133,8 @@ bool gen_rct_tx_validation_base::generate_with(std::vector<test_event_entry>& ev
CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation"); CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation");
crypto::secret_key amount_key; crypto::secret_key amount_key;
crypto::derivation_to_scalar(derivation, o, amount_key); crypto::derivation_to_scalar(derivation, o, amount_key);
if (rct_txes[n].rct_signatures.type == rct::RCTTypeSimple || rct_txes[n].rct_signatures.type == rct::RCTTypeBulletproof) const uint8_t type = rct_txes[n].rct_signatures.type;
if (type == rct::RCTTypeSimple || type == rct::RCTTypeBulletproof || type == rct::RCTTypeBulletproof2)
rct::decodeRctSimple(rct_txes[n].rct_signatures, rct::sk2rct(amount_key), o, rct_tx_masks[o+n*4], hw::get_device("default")); rct::decodeRctSimple(rct_txes[n].rct_signatures, rct::sk2rct(amount_key), o, rct_tx_masks[o+n*4], hw::get_device("default"));
else else
rct::decodeRct(rct_txes[n].rct_signatures, rct::sk2rct(amount_key), o, rct_tx_masks[o+n*4], hw::get_device("default")); rct::decodeRct(rct_txes[n].rct_signatures, rct::sk2rct(amount_key), o, rct_tx_masks[o+n*4], hw::get_device("default"));

@ -40,7 +40,7 @@
#include "multi_tx_test_base.h" #include "multi_tx_test_base.h"
template<size_t a_ring_size, size_t a_outputs, bool a_rct, rct::RangeProofType range_proof_type = rct::RangeProofBorromean> template<size_t a_ring_size, size_t a_outputs, bool a_rct, rct::RangeProofType range_proof_type = rct::RangeProofBorromean, int bp_version = 2>
class test_check_tx_signature : private multi_tx_test_base<a_ring_size> class test_check_tx_signature : private multi_tx_test_base<a_ring_size>
{ {
static_assert(0 < a_ring_size, "ring_size must be greater than 0"); static_assert(0 < a_ring_size, "ring_size must be greater than 0");
@ -71,7 +71,8 @@ public:
std::vector<crypto::secret_key> additional_tx_keys; std::vector<crypto::secret_key> additional_tx_keys;
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses; std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
subaddresses[this->m_miners[this->real_source_idx].get_keys().m_account_address.m_spend_public_key] = {0,0}; subaddresses[this->m_miners[this->real_source_idx].get_keys().m_account_address.m_spend_public_key] = {0,0};
if (!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), m_tx, 0, tx_key, additional_tx_keys, rct, range_proof_type)) rct::RCTConfig rct_config{range_proof_type, bp_version};
if (!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), m_tx, 0, tx_key, additional_tx_keys, rct, rct_config))
return false; return false;
get_transaction_prefix_hash(m_tx, m_tx_prefix_hash); get_transaction_prefix_hash(m_tx, m_tx_prefix_hash);
@ -135,7 +136,7 @@ public:
m_txes.resize(a_num_txes + (extra_outs > 0 ? 1 : 0)); m_txes.resize(a_num_txes + (extra_outs > 0 ? 1 : 0));
for (size_t n = 0; n < a_num_txes; ++n) for (size_t n = 0; n < a_num_txes; ++n)
{ {
if (!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), m_txes[n], 0, tx_key, additional_tx_keys, true, rct::RangeProofPaddedBulletproof)) if (!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), m_txes[n], 0, tx_key, additional_tx_keys, true, {rct::RangeProofPaddedBulletproof, 2}))
return false; return false;
} }
@ -146,7 +147,7 @@ public:
for (size_t n = 1; n < extra_outs; ++n) for (size_t n = 1; n < extra_outs; ++n)
destinations.push_back(tx_destination_entry(1, m_alice.get_keys().m_account_address, false)); destinations.push_back(tx_destination_entry(1, m_alice.get_keys().m_account_address, false));
if (!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), m_txes.back(), 0, tx_key, additional_tx_keys, true, rct::RangeProofMultiOutputBulletproof)) if (!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), m_txes.back(), 0, tx_key, additional_tx_keys, true, {rct::RangeProofMultiOutputBulletproof, 2}))
return false; return false;
} }

@ -36,7 +36,7 @@
#include "multi_tx_test_base.h" #include "multi_tx_test_base.h"
template<size_t a_in_count, size_t a_out_count, bool a_rct, rct::RangeProofType range_proof_type = rct::RangeProofBorromean> template<size_t a_in_count, size_t a_out_count, bool a_rct, rct::RangeProofType range_proof_type = rct::RangeProofBorromean, int bp_version = 2>
class test_construct_tx : private multi_tx_test_base<a_in_count> class test_construct_tx : private multi_tx_test_base<a_in_count>
{ {
static_assert(0 < a_in_count, "in_count must be greater than 0"); static_assert(0 < a_in_count, "in_count must be greater than 0");
@ -73,7 +73,8 @@ public:
std::vector<crypto::secret_key> additional_tx_keys; std::vector<crypto::secret_key> additional_tx_keys;
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses; std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
subaddresses[this->m_miners[this->real_source_idx].get_keys().m_account_address.m_spend_public_key] = {0,0}; subaddresses[this->m_miners[this->real_source_idx].get_keys().m_account_address.m_spend_public_key] = {0,0};
return cryptonote::construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, m_destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), m_tx, 0, tx_key, additional_tx_keys, rct, range_proof_type); rct::RCTConfig rct_config{range_proof_type, bp_version};
return cryptonote::construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, m_destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), m_tx, 0, tx_key, additional_tx_keys, rct, rct_config);
} }
private: private:

@ -132,17 +132,17 @@ int main(int argc, char** argv)
TEST_PERFORMANCE3(filter, p, test_construct_tx, 100, 2, true); TEST_PERFORMANCE3(filter, p, test_construct_tx, 100, 2, true);
TEST_PERFORMANCE3(filter, p, test_construct_tx, 100, 10, true); TEST_PERFORMANCE3(filter, p, test_construct_tx, 100, 10, true);
TEST_PERFORMANCE4(filter, p, test_construct_tx, 2, 1, true, rct::RangeProofPaddedBulletproof); TEST_PERFORMANCE5(filter, p, test_construct_tx, 2, 1, true, rct::RangeProofPaddedBulletproof, 2);
TEST_PERFORMANCE4(filter, p, test_construct_tx, 2, 2, true, rct::RangeProofPaddedBulletproof); TEST_PERFORMANCE5(filter, p, test_construct_tx, 2, 2, true, rct::RangeProofPaddedBulletproof, 2);
TEST_PERFORMANCE4(filter, p, test_construct_tx, 2, 10, true, rct::RangeProofPaddedBulletproof); TEST_PERFORMANCE5(filter, p, test_construct_tx, 2, 10, true, rct::RangeProofPaddedBulletproof, 2);
TEST_PERFORMANCE4(filter, p, test_construct_tx, 10, 1, true, rct::RangeProofPaddedBulletproof); TEST_PERFORMANCE5(filter, p, test_construct_tx, 10, 1, true, rct::RangeProofPaddedBulletproof, 2);
TEST_PERFORMANCE4(filter, p, test_construct_tx, 10, 2, true, rct::RangeProofPaddedBulletproof); TEST_PERFORMANCE5(filter, p, test_construct_tx, 10, 2, true, rct::RangeProofPaddedBulletproof, 2);
TEST_PERFORMANCE4(filter, p, test_construct_tx, 10, 10, true, rct::RangeProofPaddedBulletproof); TEST_PERFORMANCE5(filter, p, test_construct_tx, 10, 10, true, rct::RangeProofPaddedBulletproof, 2);
TEST_PERFORMANCE4(filter, p, test_construct_tx, 100, 1, true, rct::RangeProofPaddedBulletproof); TEST_PERFORMANCE5(filter, p, test_construct_tx, 100, 1, true, rct::RangeProofPaddedBulletproof, 2);
TEST_PERFORMANCE4(filter, p, test_construct_tx, 100, 2, true, rct::RangeProofPaddedBulletproof); TEST_PERFORMANCE5(filter, p, test_construct_tx, 100, 2, true, rct::RangeProofPaddedBulletproof, 2);
TEST_PERFORMANCE4(filter, p, test_construct_tx, 100, 10, true, rct::RangeProofPaddedBulletproof); TEST_PERFORMANCE5(filter, p, test_construct_tx, 100, 10, true, rct::RangeProofPaddedBulletproof, 2);
TEST_PERFORMANCE3(filter, p, test_check_tx_signature, 1, 2, false); TEST_PERFORMANCE3(filter, p, test_check_tx_signature, 1, 2, false);
TEST_PERFORMANCE3(filter, p, test_check_tx_signature, 2, 2, false); TEST_PERFORMANCE3(filter, p, test_check_tx_signature, 2, 2, false);
@ -155,14 +155,14 @@ int main(int argc, char** argv)
TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 100, 2, true, rct::RangeProofBorromean); TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 100, 2, true, rct::RangeProofBorromean);
TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 2, 10, true, rct::RangeProofBorromean); TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 2, 10, true, rct::RangeProofBorromean);
TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 2, 2, true, rct::RangeProofPaddedBulletproof); TEST_PERFORMANCE5(filter, p, test_check_tx_signature, 2, 2, true, rct::RangeProofPaddedBulletproof, 2);
TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 2, 2, true, rct::RangeProofMultiOutputBulletproof); TEST_PERFORMANCE5(filter, p, test_check_tx_signature, 2, 2, true, rct::RangeProofMultiOutputBulletproof, 2);
TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 10, 2, true, rct::RangeProofPaddedBulletproof); TEST_PERFORMANCE5(filter, p, test_check_tx_signature, 10, 2, true, rct::RangeProofPaddedBulletproof, 2);
TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 10, 2, true, rct::RangeProofMultiOutputBulletproof); TEST_PERFORMANCE5(filter, p, test_check_tx_signature, 10, 2, true, rct::RangeProofMultiOutputBulletproof, 2);
TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 100, 2, true, rct::RangeProofPaddedBulletproof); TEST_PERFORMANCE5(filter, p, test_check_tx_signature, 100, 2, true, rct::RangeProofPaddedBulletproof, 2);
TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 100, 2, true, rct::RangeProofMultiOutputBulletproof); TEST_PERFORMANCE5(filter, p, test_check_tx_signature, 100, 2, true, rct::RangeProofMultiOutputBulletproof, 2);
TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 2, 10, true, rct::RangeProofPaddedBulletproof); TEST_PERFORMANCE5(filter, p, test_check_tx_signature, 2, 10, true, rct::RangeProofPaddedBulletproof, 2);
TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 2, 10, true, rct::RangeProofMultiOutputBulletproof); TEST_PERFORMANCE5(filter, p, test_check_tx_signature, 2, 10, true, rct::RangeProofMultiOutputBulletproof, 2);
TEST_PERFORMANCE3(filter, p, test_check_tx_signature_aggregated_bulletproofs, 2, 2, 64); TEST_PERFORMANCE3(filter, p, test_check_tx_signature_aggregated_bulletproofs, 2, 2, 64);
TEST_PERFORMANCE3(filter, p, test_check_tx_signature_aggregated_bulletproofs, 10, 2, 64); TEST_PERFORMANCE3(filter, p, test_check_tx_signature_aggregated_bulletproofs, 10, 2, 64);

@ -131,7 +131,8 @@ TEST(bulletproofs, multi_splitting)
} }
rct::ctkeyV outSk; rct::ctkeyV outSk;
rct::rctSig s = rct::genRctSimple(rct::zero(), sc, destinations, inamounts, outamounts, available, mixRing, amount_keys, NULL, NULL, index, outSk, rct::RangeProofPaddedBulletproof, hw::get_device("default")); rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 0 };
rct::rctSig s = rct::genRctSimple(rct::zero(), sc, destinations, inamounts, outamounts, available, mixRing, amount_keys, NULL, NULL, index, outSk, rct_config, hw::get_device("default"));
ASSERT_TRUE(rct::verRctSimple(s)); ASSERT_TRUE(rct::verRctSimple(s));
for (size_t i = 0; i < n_outputs; ++i) for (size_t i = 0; i < n_outputs; ++i)
{ {

@ -75,7 +75,7 @@ namespace
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses; std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
subaddresses[from.m_account_address.m_spend_public_key] = {0,0}; subaddresses[from.m_account_address.m_spend_public_key] = {0,0};
if (!cryptonote::construct_tx_and_get_tx_key(from, subaddresses, actual_sources, to, boost::none, {}, tx, 0, tx_key, extra_keys, rct, bulletproof ? rct::RangeProofBulletproof : rct::RangeProofBorromean)) if (!cryptonote::construct_tx_and_get_tx_key(from, subaddresses, actual_sources, to, boost::none, {}, tx, 0, tx_key, extra_keys, rct, { bulletproof ? rct::RangeProofBulletproof : rct::RangeProofBorromean, bulletproof ? 2 : 0 }))
throw std::runtime_error{"transaction construction error"}; throw std::runtime_error{"transaction construction error"};
return tx; return tx;

@ -171,8 +171,10 @@ TEST(ringct, range_proofs)
skpkGen(Sk, Pk); skpkGen(Sk, Pk);
destinations.push_back(Pk); destinations.push_back(Pk);
const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
//compute rct data with mixin 500 //compute rct data with mixin 500
rctSig s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, hw::get_device("default")); rctSig s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default"));
//verify rct data //verify rct data
ASSERT_TRUE(verRct(s)); ASSERT_TRUE(verRct(s));
@ -189,7 +191,7 @@ TEST(ringct, range_proofs)
//compute rct data with mixin 500 //compute rct data with mixin 500
s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, hw::get_device("default")); s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default"));
//verify rct data //verify rct data
ASSERT_FALSE(verRct(s)); ASSERT_FALSE(verRct(s));
@ -235,8 +237,10 @@ TEST(ringct, range_proofs_with_fee)
skpkGen(Sk, Pk); skpkGen(Sk, Pk);
destinations.push_back(Pk); destinations.push_back(Pk);
const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
//compute rct data with mixin 500 //compute rct data with mixin 500
rctSig s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, hw::get_device("default")); rctSig s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default"));
//verify rct data //verify rct data
ASSERT_TRUE(verRct(s)); ASSERT_TRUE(verRct(s));
@ -253,7 +257,7 @@ TEST(ringct, range_proofs_with_fee)
//compute rct data with mixin 500 //compute rct data with mixin 500
s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, hw::get_device("default")); s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default"));
//verify rct data //verify rct data
ASSERT_FALSE(verRct(s)); ASSERT_FALSE(verRct(s));
@ -311,7 +315,8 @@ TEST(ringct, simple)
//compute sig with mixin 2 //compute sig with mixin 2
xmr_amount txnfee = 1; xmr_amount txnfee = 1;
rctSig s = genRctSimple(message, sc, pc, destinations,inamounts, outamounts, amount_keys, NULL, NULL, txnfee, 2, hw::get_device("default")); const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
rctSig s = genRctSimple(message, sc, pc, destinations,inamounts, outamounts, amount_keys, NULL, NULL, txnfee, 2, rct_config, hw::get_device("default"));
//verify ring ct signature //verify ring ct signature
ASSERT_TRUE(verRctSimple(s)); ASSERT_TRUE(verRctSimple(s));
@ -345,7 +350,8 @@ static rct::rctSig make_sample_rct_sig(int n_inputs, const uint64_t input_amount
} }
} }
return genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, hw::get_device("default")); const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
return genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default"));
} }
static rct::rctSig make_sample_simple_rct_sig(int n_inputs, const uint64_t input_amounts[], int n_outputs, const uint64_t output_amounts[], uint64_t fee) static rct::rctSig make_sample_simple_rct_sig(int n_inputs, const uint64_t input_amounts[], int n_outputs, const uint64_t output_amounts[], uint64_t fee)
@ -371,7 +377,8 @@ static rct::rctSig make_sample_simple_rct_sig(int n_inputs, const uint64_t input
destinations.push_back(Pk); destinations.push_back(Pk);
} }
return genRctSimple(rct::zero(), sc, pc, destinations, inamounts, outamounts, amount_keys, NULL, NULL, fee, 3, hw::get_device("default")); const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
return genRctSimple(rct::zero(), sc, pc, destinations, inamounts, outamounts, amount_keys, NULL, NULL, fee, 3, rct_config, hw::get_device("default"));
} }
static bool range_proof_test(bool expected_valid, static bool range_proof_test(bool expected_valid,

@ -591,7 +591,8 @@ TEST(Serialization, serializes_ringct_types)
rct::skpkGen(Sk, Pk); rct::skpkGen(Sk, Pk);
destinations.push_back(Pk); destinations.push_back(Pk);
//compute rct data with mixin 500 //compute rct data with mixin 500
s0 = rct::genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, hw::get_device("default")); const rct::RCTConfig rct_config{ rct::RangeProofPaddedBulletproof, 0 };
s0 = rct::genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default"));
mg0 = s0.p.MGs[0]; mg0 = s0.p.MGs[0];
ASSERT_TRUE(serialization::dump_binary(mg0, blob)); ASSERT_TRUE(serialization::dump_binary(mg0, blob));

Loading…
Cancel
Save