mirror of https://github.com/oxen-io/oxen-core.git
Remove MLSAG generation
The blockchain only accepts CLSAG txes now, so no need to keep the MLSAG generation code around. (MLSAG verification stays, of course).
This commit is contained in:
parent
16bb065f53
commit
67f4e990d2
|
@ -1185,15 +1185,13 @@ namespace cryptonote
|
|||
}
|
||||
else
|
||||
{
|
||||
transaction &tt = const_cast<transaction&>(t);
|
||||
serialization::binary_string_archiver ba;
|
||||
const size_t inputs = t.vin.size();
|
||||
const size_t outputs = t.vout.size();
|
||||
size_t mixin = 0;
|
||||
if (t.vin.size() > 0 && std::holds_alternative<txin_to_key>(t.vin[0]))
|
||||
mixin = var::get<txin_to_key>(t.vin[0]).key_offsets.size() - 1;
|
||||
try {
|
||||
tt.rct_signatures.p.serialize_rctsig_prunable(ba, t.rct_signatures.type, inputs, outputs, mixin);
|
||||
const_cast<transaction&>(t).rct_signatures.p.serialize_rctsig_prunable(
|
||||
ba, t.rct_signatures.type, t.vin.size(), t.vout.size(), mixin);
|
||||
} catch (const std::exception& e) {
|
||||
LOG_ERROR("Failed to serialize rct signatures (prunable): " << e.what());
|
||||
return false;
|
||||
|
|
|
@ -3514,7 +3514,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|||
break;
|
||||
}
|
||||
default:
|
||||
MERROR_VER(__func__ << ": Unsupported rct type: " << rv.type);
|
||||
MERROR_VER(__func__ << ": Unsupported rct type: " << (int)rv.type);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1249,7 +1249,7 @@ namespace cryptonote
|
|||
rvv.push_back(&rv); // delayed batch verification
|
||||
break;
|
||||
default:
|
||||
MERROR_VER("Unknown rct type: " << rv.type);
|
||||
MERROR_VER("Unknown rct type: " << (int)rv.type);
|
||||
set_semantics_failed(tx_info[n].tx_hash);
|
||||
tx_info[n].tvc.m_verifivation_failed = true;
|
||||
tx_info[n].result = false;
|
||||
|
|
|
@ -621,9 +621,12 @@ namespace cryptonote
|
|||
}
|
||||
|
||||
tx.version = transaction::get_max_version_for_hf(tx_params.hf_version);
|
||||
tx.type = tx_params.tx_type;
|
||||
if (tx.version <= txversion::v2_ringct)
|
||||
tx.unlock_time = unlock_time;
|
||||
CHECK_AND_ASSERT_MES(tx.version >= txversion::v4_tx_types, false, "Cannot construct pre-v4 transactions");
|
||||
CHECK_AND_ASSERT_MES(rct_config.range_proof_type == rct::RangeProofType::PaddedBulletproof &&
|
||||
(rct_config.bp_version == 0 || rct_config.bp_version >= 3),
|
||||
false, "Cannot construct pre-CLSAG transactions");
|
||||
|
||||
tx.type = tx_params.tx_type;
|
||||
|
||||
if (tx_params.burn_percent)
|
||||
{
|
||||
|
@ -631,12 +634,6 @@ namespace cryptonote
|
|||
return false;
|
||||
}
|
||||
|
||||
if (tx_params.burn_fixed && tx_params.hf_version < cryptonote::network_version_14_blink)
|
||||
{
|
||||
LOG_ERROR("cannot construct tx: burn can not be specified before hard fork 14");
|
||||
return false;
|
||||
}
|
||||
|
||||
tx.extra = extra;
|
||||
crypto::public_key txkey_pub;
|
||||
|
||||
|
@ -829,7 +826,6 @@ namespace cryptonote
|
|||
bool found_change_already = false;
|
||||
for(const tx_destination_entry& dst_entr: destinations)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version >= txversion::v2_ringct, false, "Destination with wrong amount: " << dst_entr.amount);
|
||||
crypto::public_key out_eph_public_key;
|
||||
|
||||
bool this_dst_is_change_addr = false;
|
||||
|
@ -838,7 +834,7 @@ namespace cryptonote
|
|||
need_additional_txkeys, additional_tx_keys,
|
||||
additional_tx_public_keys, amount_keys, out_eph_public_key);
|
||||
|
||||
if (tx.version >= txversion::v3_per_output_unlock_times)
|
||||
// Per-output unlock times:
|
||||
{
|
||||
if (change_addr && *change_addr == dst_entr && this_dst_is_change_addr && !found_change_already)
|
||||
{
|
||||
|
@ -924,170 +920,83 @@ namespace cryptonote
|
|||
MDEBUG("Null secret key, skipping signatures");
|
||||
}
|
||||
|
||||
if (tx.version == txversion::v1)
|
||||
uint64_t amount_in = 0, amount_out = 0;
|
||||
rct::ctkeyV inSk;
|
||||
inSk.reserve(sources.size());
|
||||
// mixRing indexing is done the other way round for simple
|
||||
rct::ctkeyM mixRing(sources.size());
|
||||
rct::keyV dest_keys;
|
||||
std::vector<uint64_t> inamounts, outamounts;
|
||||
std::vector<unsigned int> index;
|
||||
std::vector<rct::multisig_kLRki> kLRki;
|
||||
for (size_t i = 0; i < sources.size(); ++i)
|
||||
{
|
||||
//generate ring signatures
|
||||
crypto::hash tx_prefix_hash;
|
||||
get_transaction_prefix_hash(tx, tx_prefix_hash);
|
||||
|
||||
std::stringstream ss_ring_s;
|
||||
size_t i = 0;
|
||||
for(const tx_source_entry& src_entr: sources)
|
||||
rct::ctkey ctkey;
|
||||
amount_in += sources[i].amount;
|
||||
inamounts.push_back(sources[i].amount);
|
||||
index.push_back(sources[i].real_output);
|
||||
// inSk: (secret key, mask)
|
||||
ctkey.dest = rct::sk2rct(in_contexts[i].in_ephemeral.sec);
|
||||
ctkey.mask = sources[i].mask;
|
||||
inSk.push_back(ctkey);
|
||||
memwipe(&ctkey, sizeof(rct::ctkey));
|
||||
// inPk: (public key, commitment)
|
||||
// will be done when filling in mixRing
|
||||
if (msout)
|
||||
{
|
||||
ss_ring_s << "pub_keys:\n";
|
||||
std::vector<const crypto::public_key*> keys_ptrs;
|
||||
std::vector<crypto::public_key> keys(src_entr.outputs.size());
|
||||
size_t ii = 0;
|
||||
for(const tx_source_entry::output_entry& o: src_entr.outputs)
|
||||
{
|
||||
keys[ii] = rct2pk(o.second.dest);
|
||||
keys_ptrs.push_back(&keys[ii]);
|
||||
ss_ring_s << o.second.dest << "\n";
|
||||
++ii;
|
||||
}
|
||||
|
||||
tx.signatures.push_back(std::vector<crypto::signature>());
|
||||
std::vector<crypto::signature>& sigs = tx.signatures.back();
|
||||
sigs.resize(src_entr.outputs.size());
|
||||
if (!zero_secret_key)
|
||||
crypto::generate_ring_signature(tx_prefix_hash, var::get<txin_to_key>(tx.vin[i]).k_image, keys_ptrs, in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data());
|
||||
ss_ring_s << "signatures:\n";
|
||||
std::for_each(sigs.begin(), sigs.end(), [&](const crypto::signature& s){ss_ring_s << s << "\n";});
|
||||
ss_ring_s << "prefix_hash:" << tx_prefix_hash << "\nin_ephemeral_key: " << in_contexts[i].in_ephemeral.sec << "\nreal_output: " << src_entr.real_output << "\n";
|
||||
i++;
|
||||
kLRki.push_back(sources[i].multisig_kLRki);
|
||||
}
|
||||
|
||||
MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << "\n" << obj_to_json_str(tx) << "\n" << ss_ring_s.str());
|
||||
}
|
||||
else
|
||||
for (size_t i = 0; i < tx.vout.size(); ++i)
|
||||
{
|
||||
size_t n_total_outs = sources[0].outputs.size(); // only for non-simple rct
|
||||
|
||||
// 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.
|
||||
bool use_simple_rct = sources.size() > 1 || rct_config.range_proof_type != rct::RangeProofBorromean;
|
||||
|
||||
if (!use_simple_rct)
|
||||
{
|
||||
// non simple ringct requires all real inputs to be at the same index for all inputs
|
||||
for(const tx_source_entry& src_entr: sources)
|
||||
{
|
||||
if(src_entr.real_output != sources.begin()->real_output)
|
||||
{
|
||||
LOG_ERROR("All inputs must have the same index for non-simple ringct");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// enforce same mixin for all outputs
|
||||
for (size_t i = 1; i < sources.size(); ++i) {
|
||||
if (n_total_outs != sources[i].outputs.size()) {
|
||||
LOG_ERROR("Non-simple ringct transaction has varying ring size");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t amount_in = 0, amount_out = 0;
|
||||
rct::ctkeyV inSk;
|
||||
inSk.reserve(sources.size());
|
||||
// mixRing indexing is done the other way round for simple
|
||||
rct::ctkeyM mixRing(use_simple_rct ? sources.size() : n_total_outs);
|
||||
rct::keyV destinations;
|
||||
std::vector<uint64_t> inamounts, outamounts;
|
||||
std::vector<unsigned int> index;
|
||||
std::vector<rct::multisig_kLRki> kLRki;
|
||||
for (size_t i = 0; i < sources.size(); ++i)
|
||||
{
|
||||
rct::ctkey ctkey;
|
||||
amount_in += sources[i].amount;
|
||||
inamounts.push_back(sources[i].amount);
|
||||
index.push_back(sources[i].real_output);
|
||||
// inSk: (secret key, mask)
|
||||
ctkey.dest = rct::sk2rct(in_contexts[i].in_ephemeral.sec);
|
||||
ctkey.mask = sources[i].mask;
|
||||
inSk.push_back(ctkey);
|
||||
memwipe(&ctkey, sizeof(rct::ctkey));
|
||||
// inPk: (public key, commitment)
|
||||
// will be done when filling in mixRing
|
||||
if (msout)
|
||||
{
|
||||
kLRki.push_back(sources[i].multisig_kLRki);
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < tx.vout.size(); ++i)
|
||||
{
|
||||
destinations.push_back(rct::pk2rct(var::get<txout_to_key>(tx.vout[i].target).key));
|
||||
outamounts.push_back(tx.vout[i].amount);
|
||||
amount_out += tx.vout[i].amount;
|
||||
}
|
||||
|
||||
if (use_simple_rct)
|
||||
{
|
||||
// mixRing indexing is done the other way round for simple
|
||||
for (size_t i = 0; i < sources.size(); ++i)
|
||||
{
|
||||
mixRing[i].resize(sources[i].outputs.size());
|
||||
for (size_t n = 0; n < sources[i].outputs.size(); ++n)
|
||||
{
|
||||
mixRing[i][n] = sources[i].outputs[n].second;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < n_total_outs; ++i) // same index assumption
|
||||
{
|
||||
mixRing[i].resize(sources.size());
|
||||
for (size_t n = 0; n < sources.size(); ++n)
|
||||
{
|
||||
mixRing[i][n] = sources[n].outputs[i].second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fee
|
||||
if (!use_simple_rct && amount_in > amount_out)
|
||||
outamounts.push_back(amount_in - amount_out);
|
||||
|
||||
if (tx_params.burn_fixed)
|
||||
{
|
||||
if (amount_in < amount_out + tx_params.burn_fixed)
|
||||
{
|
||||
LOG_ERROR("invalid burn amount: tx does not have enough unspent funds available; amount_in: " << std::to_string(amount_in) << "; amount_out + tx_params.burn_fixed: " << std::to_string(amount_out) << " + " << std::to_string(tx_params.burn_fixed));
|
||||
return false;
|
||||
}
|
||||
remove_field_from_tx_extra<tx_extra_burn>(tx.extra); // doesn't have to be present (but the wallet puts a dummy here as a safety to avoid growing the tx)
|
||||
if (!add_burned_amount_to_tx_extra(tx.extra, tx_params.burn_fixed))
|
||||
{
|
||||
LOG_ERROR("failed to add burn amount to tx extra");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// zero out all amounts to mask rct outputs, real amounts are now encrypted
|
||||
for (size_t i = 0; i < tx.vin.size(); ++i)
|
||||
{
|
||||
if (sources[i].rct)
|
||||
var::get<txin_to_key>(tx.vin[i]).amount = 0;
|
||||
}
|
||||
for (size_t i = 0; i < tx.vout.size(); ++i)
|
||||
tx.vout[i].amount = 0;
|
||||
|
||||
crypto::hash tx_prefix_hash;
|
||||
get_transaction_prefix_hash(tx, tx_prefix_hash, hwdev);
|
||||
rct::ctkeyV outSk;
|
||||
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, rct_config, hwdev);
|
||||
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, rct_config, hwdev); // same index assumption
|
||||
memwipe(inSk.data(), inSk.size() * sizeof(rct::ctkey));
|
||||
|
||||
CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout");
|
||||
|
||||
MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << "\n" << obj_to_json_str(tx) << "\n");
|
||||
dest_keys.push_back(rct::pk2rct(var::get<txout_to_key>(tx.vout[i].target).key));
|
||||
outamounts.push_back(tx.vout[i].amount);
|
||||
amount_out += tx.vout[i].amount;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sources.size(); ++i)
|
||||
{
|
||||
mixRing[i].resize(sources[i].outputs.size());
|
||||
for (size_t n = 0; n < sources[i].outputs.size(); ++n)
|
||||
{
|
||||
mixRing[i][n] = sources[i].outputs[n].second;
|
||||
}
|
||||
}
|
||||
|
||||
if (tx_params.burn_fixed)
|
||||
{
|
||||
if (amount_in < amount_out + tx_params.burn_fixed)
|
||||
{
|
||||
LOG_ERROR("invalid burn amount: tx does not have enough unspent funds available; amount_in: " << std::to_string(amount_in) << "; amount_out + tx_params.burn_fixed: " << std::to_string(amount_out) << " + " << std::to_string(tx_params.burn_fixed));
|
||||
return false;
|
||||
}
|
||||
remove_field_from_tx_extra<tx_extra_burn>(tx.extra); // doesn't have to be present (but the wallet puts a dummy here as a safety to avoid growing the tx)
|
||||
if (!add_burned_amount_to_tx_extra(tx.extra, tx_params.burn_fixed))
|
||||
{
|
||||
LOG_ERROR("failed to add burn amount to tx extra");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// zero out all amounts to mask rct outputs, real amounts are now encrypted
|
||||
for (size_t i = 0; i < tx.vin.size(); ++i)
|
||||
{
|
||||
if (sources[i].rct)
|
||||
var::get<txin_to_key>(tx.vin[i]).amount = 0;
|
||||
}
|
||||
for (size_t i = 0; i < tx.vout.size(); ++i)
|
||||
tx.vout[i].amount = 0;
|
||||
|
||||
crypto::hash tx_prefix_hash;
|
||||
get_transaction_prefix_hash(tx, tx_prefix_hash, hwdev);
|
||||
rct::ctkeyV outSk;
|
||||
tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, dest_keys, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, msout ? &kLRki : NULL, msout, index, outSk, rct_config, hwdev);
|
||||
memwipe(inSk.data(), inSk.size() * sizeof(rct::ctkey));
|
||||
|
||||
CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout");
|
||||
|
||||
MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << "\n" << obj_to_json_str(tx) << "\n");
|
||||
|
||||
tx.invalidate_hashes();
|
||||
|
||||
return true;
|
||||
|
@ -1129,7 +1038,7 @@ namespace cryptonote
|
|||
std::vector<tx_destination_entry> destinations_copy = destinations;
|
||||
|
||||
rct::RCTConfig rct_config{
|
||||
tx_params.hf_version < network_version_10_bulletproofs ? rct::RangeProofBorromean : rct::RangeProofPaddedBulletproof,
|
||||
tx_params.hf_version < network_version_10_bulletproofs ? rct::RangeProofType::Borromean : rct::RangeProofType::PaddedBulletproof,
|
||||
tx_params.hf_version >= HF_VERSION_CLSAG ? 3 : tx_params.hf_version >= HF_VERSION_SMALLER_BP ? 2 : 1
|
||||
};
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ namespace cryptonote
|
|||
|
||||
struct tx_source_entry
|
||||
{
|
||||
typedef std::pair<uint64_t, rct::ctkey> output_entry;
|
||||
using output_entry = std::pair<uint64_t, rct::ctkey>;
|
||||
|
||||
std::vector<output_entry> outputs; //index + key + optional ringct commitment
|
||||
size_t real_output; //index in outputs vector of real output_entry
|
||||
|
@ -223,8 +223,8 @@ namespace cryptonote
|
|||
//---------------------------------------------------------------
|
||||
crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const std::optional<cryptonote::tx_destination_entry>& 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 std::optional<cryptonote::tx_destination_entry>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const loki_construct_tx_params &tx_params = {});
|
||||
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 std::optional<cryptonote::tx_destination_entry>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0}, rct::multisig_out *msout = NULL, bool shuffle_outs = true, loki_construct_tx_params const &tx_params = {});
|
||||
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 std::optional<cryptonote::tx_destination_entry>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0}, rct::multisig_out *msout = NULL, loki_construct_tx_params const &tx_params = {});
|
||||
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 std::optional<cryptonote::tx_destination_entry>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const rct::RCTConfig &rct_config, rct::multisig_out *msout = NULL, bool shuffle_outs = true, loki_construct_tx_params const &tx_params = {});
|
||||
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 std::optional<cryptonote::tx_destination_entry>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, const rct::RCTConfig &rct_config, rct::multisig_out *msout = NULL, loki_construct_tx_params const &tx_params = {});
|
||||
bool generate_output_ephemeral_keys(const size_t tx_version, bool &found_change,
|
||||
const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key,
|
||||
const cryptonote::tx_destination_entry &dst_entr, const std::optional<cryptonote::tx_destination_entry> &change_addr, const size_t output_index,
|
||||
|
|
|
@ -386,18 +386,18 @@ namespace service_nodes
|
|||
{
|
||||
switch (tx.rct_signatures.type)
|
||||
{
|
||||
case rct::RCTType::Simple:
|
||||
case rct::RCTType::Bulletproof:
|
||||
case rct::RCTType::Bulletproof2:
|
||||
case rct::RCTType::CLSAG:
|
||||
money_transferred = rct::decodeRctSimple(tx.rct_signatures, rct::sk2rct(scalar1), i, mask, hwdev);
|
||||
break;
|
||||
case rct::RCTType::Full:
|
||||
money_transferred = rct::decodeRct(tx.rct_signatures, rct::sk2rct(scalar1), i, mask, hwdev);
|
||||
break;
|
||||
default:
|
||||
LOG_PRINT_L0(__func__ << ": Unsupported rct type: " << (int)tx.rct_signatures.type);
|
||||
return 0;
|
||||
case rct::RCTType::Simple:
|
||||
case rct::RCTType::Bulletproof:
|
||||
case rct::RCTType::Bulletproof2:
|
||||
case rct::RCTType::CLSAG:
|
||||
money_transferred = rct::decodeRctSimple(tx.rct_signatures, rct::sk2rct(scalar1), i, mask, hwdev);
|
||||
break;
|
||||
case rct::RCTType::Full:
|
||||
money_transferred = rct::decodeRct(tx.rct_signatures, rct::sk2rct(scalar1), i, mask, hwdev);
|
||||
break;
|
||||
default:
|
||||
LOG_PRINT_L0(__func__ << ": Unsupported rct type: " << (int)tx.rct_signatures.type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
|
|
|
@ -1849,8 +1849,6 @@ namespace hw {
|
|||
this->buffer_send[offset] = (inputs_size == 0)?0x00:0x80;
|
||||
offset += 1;
|
||||
|
||||
//type
|
||||
uint8_t type = data[0];
|
||||
this->buffer_send[offset] = data[0];
|
||||
offset += 1;
|
||||
|
||||
|
@ -1870,8 +1868,10 @@ namespace hw {
|
|||
// check fee user input
|
||||
CHECK_AND_ASSERT_THROW_MES(this->exchange_wait_on_input() == 0, "Fee denied on device.");
|
||||
|
||||
auto type = static_cast<rct::RCTType>(data[0]);
|
||||
|
||||
//pseudoOuts
|
||||
if (type == rct::RCTTypeSimple) {
|
||||
if (type == rct::RCTType::Simple) {
|
||||
for ( i = 0; i < inputs_size; i++) {
|
||||
offset = set_command_header(INS_VALIDATE, 0x01, i+2);
|
||||
//options
|
||||
|
@ -1890,7 +1890,7 @@ namespace hw {
|
|||
|
||||
// ====== Aout, Bout, AKout, C, v, k ======
|
||||
kv_offset = data_offset;
|
||||
if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG) {
|
||||
if (type==rct::RCTType::Bulletproof2 || type==rct::RCTType::CLSAG) {
|
||||
C_offset = kv_offset+ (8)*outputs_size;
|
||||
} else {
|
||||
C_offset = kv_offset+ (32+32)*outputs_size;
|
||||
|
@ -1907,7 +1907,7 @@ namespace hw {
|
|||
offset = set_command_header(INS_VALIDATE, 0x02, i+1);
|
||||
//options
|
||||
this->buffer_send[offset] = (i==outputs_size-1)? 0x00:0x80 ;
|
||||
this->buffer_send[offset] |= (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG)?0x02:0x00;
|
||||
this->buffer_send[offset] |= (type==rct::RCTType::Bulletproof2 || type==rct::RCTType::CLSAG)?0x02:0x00;
|
||||
offset += 1;
|
||||
//is_subaddress
|
||||
this->buffer_send[offset] = outKeys.is_subaddress;
|
||||
|
@ -1928,7 +1928,7 @@ namespace hw {
|
|||
memmove(this->buffer_send+offset, data+C_offset,32);
|
||||
offset += 32;
|
||||
C_offset += 32;
|
||||
if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG) {
|
||||
if (type==rct::RCTType::Bulletproof2 || type==rct::RCTType::CLSAG) {
|
||||
//k
|
||||
memset(this->buffer_send+offset, 0, 32);
|
||||
offset += 32;
|
||||
|
|
|
@ -322,103 +322,6 @@ namespace rct {
|
|||
return CLSAG_Gen(message, P, p, C, z, C_nonzero, C_offset, l, NULL, NULL, NULL, hw::get_device("default"));
|
||||
}
|
||||
|
||||
// MLSAG signatures
|
||||
// See paper by Noether (https://eprint.iacr.org/2015/1098)
|
||||
// This generalization allows for some dimensions not to require linkability;
|
||||
// this is used in practice for commitment data within signatures
|
||||
// Note that using more than one linkable dimension is not recommended.
|
||||
mgSig MLSAG_Gen(const key &message, const keyM & pk, const keyV & xx, const multisig_kLRki *kLRki, key *mscout, const unsigned int index, size_t dsRows, hw::device &hwdev) {
|
||||
mgSig rv;
|
||||
size_t cols = pk.size();
|
||||
CHECK_AND_ASSERT_THROW_MES(cols >= 2, "Error! What is c if cols = 1!");
|
||||
CHECK_AND_ASSERT_THROW_MES(index < cols, "Index out of range");
|
||||
size_t rows = pk[0].size();
|
||||
CHECK_AND_ASSERT_THROW_MES(rows >= 1, "Empty pk");
|
||||
for (size_t i = 1; i < cols; ++i) {
|
||||
CHECK_AND_ASSERT_THROW_MES(pk[i].size() == rows, "pk is not rectangular");
|
||||
}
|
||||
CHECK_AND_ASSERT_THROW_MES(xx.size() == rows, "Bad xx size");
|
||||
CHECK_AND_ASSERT_THROW_MES(dsRows <= rows, "Bad dsRows size");
|
||||
CHECK_AND_ASSERT_THROW_MES((kLRki && mscout) || (!kLRki && !mscout), "Only one of kLRki/mscout is present");
|
||||
CHECK_AND_ASSERT_THROW_MES(!kLRki || dsRows == 1, "Multisig requires exactly 1 dsRows");
|
||||
|
||||
size_t i = 0, j = 0, ii = 0;
|
||||
key c, c_old, L, R, Hi;
|
||||
ge_p3 Hi_p3;
|
||||
sc_0(c_old.bytes);
|
||||
std::vector<geDsmp> Ip(dsRows);
|
||||
rv.II = keyV(dsRows);
|
||||
keyV alpha(rows);
|
||||
keyV aG(rows);
|
||||
rv.ss = keyM(cols, aG);
|
||||
keyV aHP(dsRows);
|
||||
keyV toHash(1 + 3 * dsRows + 2 * (rows - dsRows));
|
||||
toHash[0] = message;
|
||||
DP("here1");
|
||||
for (i = 0; i < dsRows; i++) {
|
||||
toHash[3 * i + 1] = pk[index][i];
|
||||
if (kLRki) {
|
||||
// multisig
|
||||
alpha[i] = kLRki->k;
|
||||
toHash[3 * i + 2] = kLRki->L;
|
||||
toHash[3 * i + 3] = kLRki->R;
|
||||
rv.II[i] = kLRki->ki;
|
||||
}
|
||||
else {
|
||||
hash_to_p3(Hi_p3, pk[index][i]);
|
||||
ge_p3_tobytes(Hi.bytes, &Hi_p3);
|
||||
hwdev.mlsag_prepare(Hi, xx[i], alpha[i] , aG[i] , aHP[i] , rv.II[i]);
|
||||
toHash[3 * i + 2] = aG[i];
|
||||
toHash[3 * i + 3] = aHP[i];
|
||||
}
|
||||
precomp(Ip[i].k, rv.II[i]);
|
||||
}
|
||||
size_t ndsRows = 3 * dsRows; //non Double Spendable Rows (see identity chains paper)
|
||||
for (i = dsRows, ii = 0 ; i < rows ; i++, ii++) {
|
||||
skpkGen(alpha[i], aG[i]); //need to save alphas for later..
|
||||
toHash[ndsRows + 2 * ii + 1] = pk[index][i];
|
||||
toHash[ndsRows + 2 * ii + 2] = aG[i];
|
||||
}
|
||||
|
||||
hwdev.mlsag_hash(toHash, c_old);
|
||||
|
||||
|
||||
i = (index + 1) % cols;
|
||||
if (i == 0) {
|
||||
copy(rv.cc, c_old);
|
||||
}
|
||||
while (i != index) {
|
||||
|
||||
rv.ss[i] = skvGen(rows);
|
||||
sc_0(c.bytes);
|
||||
for (j = 0; j < dsRows; j++) {
|
||||
addKeys2(L, rv.ss[i][j], c_old, pk[i][j]);
|
||||
hash_to_p3(Hi_p3, pk[i][j]);
|
||||
ge_p3_tobytes(Hi.bytes, &Hi_p3);
|
||||
addKeys3(R, rv.ss[i][j], Hi, c_old, Ip[j].k);
|
||||
toHash[3 * j + 1] = pk[i][j];
|
||||
toHash[3 * j + 2] = L;
|
||||
toHash[3 * j + 3] = R;
|
||||
}
|
||||
for (j = dsRows, ii = 0; j < rows; j++, ii++) {
|
||||
addKeys2(L, rv.ss[i][j], c_old, pk[i][j]);
|
||||
toHash[ndsRows + 2 * ii + 1] = pk[i][j];
|
||||
toHash[ndsRows + 2 * ii + 2] = L;
|
||||
}
|
||||
hwdev.mlsag_hash(toHash, c);
|
||||
copy(c_old, c);
|
||||
i = (i + 1) % cols;
|
||||
|
||||
if (i == 0) {
|
||||
copy(rv.cc, c_old);
|
||||
}
|
||||
}
|
||||
hwdev.mlsag_sign(c, xx, alpha, rows, dsRows, rv.ss[index]);
|
||||
if (mscout)
|
||||
*mscout = c;
|
||||
return rv;
|
||||
}
|
||||
|
||||
// MLSAG signatures
|
||||
// See paper by Noether (https://eprint.iacr.org/2015/1098)
|
||||
// This generalization allows for some dimensions not to require linkability;
|
||||
|
@ -626,93 +529,6 @@ namespace rct {
|
|||
return prehash;
|
||||
}
|
||||
|
||||
//Ring-ct MG sigs
|
||||
//Prove:
|
||||
// c.f. https://eprint.iacr.org/2015/1098 section 4. definition 10.
|
||||
// This does the MG sig on the "dest" part of the given key matrix, and
|
||||
// the last row is the sum of input commitments from that column - sum output commitments
|
||||
// this shows that sum inputs = sum outputs
|
||||
//Ver:
|
||||
// verifies the above sig is created corretly
|
||||
mgSig proveRctMG(const key &message, const ctkeyM & pubs, const ctkeyV & inSk, const ctkeyV &outSk, const ctkeyV & outPk, const multisig_kLRki *kLRki, key *mscout, unsigned int index, const key &txnFeeKey, hw::device &hwdev) {
|
||||
//setup vars
|
||||
size_t cols = pubs.size();
|
||||
CHECK_AND_ASSERT_THROW_MES(cols >= 1, "Empty pubs");
|
||||
size_t rows = pubs[0].size();
|
||||
CHECK_AND_ASSERT_THROW_MES(rows >= 1, "Empty pubs");
|
||||
for (size_t i = 1; i < cols; ++i) {
|
||||
CHECK_AND_ASSERT_THROW_MES(pubs[i].size() == rows, "pubs is not rectangular");
|
||||
}
|
||||
CHECK_AND_ASSERT_THROW_MES(inSk.size() == rows, "Bad inSk size");
|
||||
CHECK_AND_ASSERT_THROW_MES(outSk.size() == outPk.size(), "Bad outSk/outPk size");
|
||||
CHECK_AND_ASSERT_THROW_MES((kLRki && mscout) || (!kLRki && !mscout), "Only one of kLRki/mscout is present");
|
||||
|
||||
keyV sk(rows + 1);
|
||||
keyV tmp(rows + 1);
|
||||
size_t i = 0, j = 0;
|
||||
for (i = 0; i < rows + 1; i++) {
|
||||
sc_0(sk[i].bytes);
|
||||
identity(tmp[i]);
|
||||
}
|
||||
keyM M(cols, tmp);
|
||||
//create the matrix to mg sig
|
||||
for (i = 0; i < cols; i++) {
|
||||
M[i][rows] = identity();
|
||||
for (j = 0; j < rows; j++) {
|
||||
M[i][j] = pubs[i][j].dest;
|
||||
addKeys(M[i][rows], M[i][rows], pubs[i][j].mask); //add input commitments in last row
|
||||
}
|
||||
}
|
||||
sc_0(sk[rows].bytes);
|
||||
for (j = 0; j < rows; j++) {
|
||||
sk[j] = copy(inSk[j].dest);
|
||||
sc_add(sk[rows].bytes, sk[rows].bytes, inSk[j].mask.bytes); //add masks in last row
|
||||
}
|
||||
for (i = 0; i < cols; i++) {
|
||||
for (size_t j = 0; j < outPk.size(); j++) {
|
||||
subKeys(M[i][rows], M[i][rows], outPk[j].mask); //subtract output Ci's in last row
|
||||
}
|
||||
//subtract txn fee output in last row
|
||||
subKeys(M[i][rows], M[i][rows], txnFeeKey);
|
||||
}
|
||||
for (size_t j = 0; j < outPk.size(); j++) {
|
||||
sc_sub(sk[rows].bytes, sk[rows].bytes, outSk[j].mask.bytes); //subtract output masks in last row..
|
||||
}
|
||||
mgSig result = MLSAG_Gen(message, M, sk, kLRki, mscout, index, rows, hwdev);
|
||||
memwipe(sk.data(), sk.size() * sizeof(key));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//Ring-ct MG sigs Simple
|
||||
// Simple version for when we assume only
|
||||
// post rct inputs
|
||||
// here pubs is a vector of (P, C) length mixin
|
||||
// inSk is x, a_in corresponding to signing index
|
||||
// a_out, Cout is for the output commitment
|
||||
// index is the signing index..
|
||||
mgSig proveRctMGSimple(const key &message, const ctkeyV & pubs, const ctkey & inSk, const key &a , const key &Cout, const multisig_kLRki *kLRki, key *mscout, unsigned int index, hw::device &hwdev) {
|
||||
//setup vars
|
||||
size_t rows = 1;
|
||||
size_t cols = pubs.size();
|
||||
CHECK_AND_ASSERT_THROW_MES(cols >= 1, "Empty pubs");
|
||||
CHECK_AND_ASSERT_THROW_MES((kLRki && mscout) || (!kLRki && !mscout), "Only one of kLRki/mscout is present");
|
||||
keyV tmp(rows + 1);
|
||||
keyV sk(rows + 1);
|
||||
size_t i;
|
||||
keyM M(cols, tmp);
|
||||
|
||||
sk[0] = copy(inSk.dest);
|
||||
sc_sub(sk[1].bytes, inSk.mask.bytes, a.bytes);
|
||||
for (i = 0; i < cols; i++) {
|
||||
M[i][0] = pubs[i].dest;
|
||||
subKeys(M[i][1], pubs[i].mask, Cout);
|
||||
}
|
||||
mgSig result = MLSAG_Gen(message, M, sk, kLRki, mscout, index, rows, hwdev);
|
||||
memwipe(&sk[0], sizeof(key));
|
||||
return result;
|
||||
}
|
||||
|
||||
clsag proveRctCLSAGSimple(const key &message, const ctkeyV &pubs, const ctkey &inSk, const key &a, const key &Cout, const multisig_kLRki *kLRki, key *mscout, key *mspout, unsigned int index, hw::device &hwdev) {
|
||||
//setup vars
|
||||
size_t rows = 1;
|
||||
|
@ -986,82 +802,9 @@ namespace rct {
|
|||
return index;
|
||||
}
|
||||
|
||||
//RingCT protocol
|
||||
//genRct:
|
||||
// creates an rctSig with all data necessary to verify the rangeProofs and that the signer owns one of the
|
||||
// columns that are claimed as inputs, and that the sum of inputs = sum of outputs.
|
||||
// Also contains masked "amount" and "mask" so the receiver can see how much they received
|
||||
//verRct:
|
||||
// verifies that all signatures (rangeProogs, MG sig, sum inputs = outputs) are correct
|
||||
//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
|
||||
// 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
|
||||
// Thus the amounts vector will be "one" longer than the destinations vectort
|
||||
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) {
|
||||
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(index < mixRing.size(), "Bad index into mixRing");
|
||||
for (size_t n = 0; n < mixRing.size(); ++n) {
|
||||
CHECK_AND_ASSERT_THROW_MES(mixRing[n].size() == inSk.size(), "Bad mixRing size");
|
||||
}
|
||||
CHECK_AND_ASSERT_THROW_MES((kLRki && msout) || (!kLRki && !msout), "Only one of kLRki/msout is present");
|
||||
CHECK_AND_ASSERT_THROW_MES(inSk.size() < 2, "genRct is not suitable for 2+ rings");
|
||||
|
||||
rctSig rv;
|
||||
rv.type = RCTTypeFull;
|
||||
rv.message = message;
|
||||
rv.outPk.resize(destinations.size());
|
||||
rv.p.rangeSigs.resize(destinations.size());
|
||||
rv.ecdhInfo.resize(destinations.size());
|
||||
|
||||
size_t i = 0;
|
||||
keyV masks(destinations.size()); //sk mask..
|
||||
outSk.resize(destinations.size());
|
||||
for (i = 0; i < destinations.size(); i++) {
|
||||
//add destination to sig
|
||||
rv.outPk[i].dest = copy(destinations[i]);
|
||||
//compute range proof
|
||||
rv.p.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, amounts[i]);
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]), "verRange failed on newly created proof");
|
||||
#endif
|
||||
//mask amount and mask
|
||||
rv.ecdhInfo[i].mask = copy(outSk[i].mask);
|
||||
rv.ecdhInfo[i].amount = d2h(amounts[i]);
|
||||
hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG);
|
||||
}
|
||||
|
||||
//set txn fee
|
||||
if (amounts.size() > destinations.size())
|
||||
{
|
||||
rv.txnFee = amounts[destinations.size()];
|
||||
}
|
||||
else
|
||||
{
|
||||
rv.txnFee = 0;
|
||||
}
|
||||
key txnFeeKey = scalarmultH(d2h(rv.txnFee));
|
||||
|
||||
rv.mixRing = mixRing;
|
||||
if (msout)
|
||||
msout->c.resize(1);
|
||||
rv.p.MGs.push_back(proveRctMG(get_pre_mlsag_hash(rv, hwdev), rv.mixRing, inSk, outSk, rv.outPk, kLRki, msout ? &msout->c[0] : NULL, index, txnFeeKey,hwdev));
|
||||
return rv;
|
||||
}
|
||||
|
||||
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) {
|
||||
unsigned int index;
|
||||
ctkeyM mixRing;
|
||||
ctkeyV outSk;
|
||||
tie(mixRing, index) = populateFromBlockchain(inPk, mixin);
|
||||
return genRct(message, inSk, destinations, amounts, mixRing, amount_keys, kLRki, msout, index, outSk, rct_config, hwdev);
|
||||
}
|
||||
|
||||
//RCT simple
|
||||
//for post-rct only
|
||||
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) {
|
||||
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() == inSk.size(), "Different number of inamounts/inSk");
|
||||
CHECK_AND_ASSERT_THROW_MES(outamounts.size() == destinations.size(), "Different number of amounts/destinations");
|
||||
|
@ -1076,107 +819,79 @@ namespace rct {
|
|||
CHECK_AND_ASSERT_THROW_MES(kLRki->size() == inamounts.size(), "Mismatched kLRki/inamounts sizes");
|
||||
}
|
||||
|
||||
rctSig rv;
|
||||
if (bulletproof)
|
||||
{
|
||||
switch (rct_config.bp_version)
|
||||
{
|
||||
case 0:
|
||||
case 3:
|
||||
rv.type = RCTTypeCLSAG;
|
||||
break;
|
||||
case 2:
|
||||
rv.type = RCTTypeBulletproof2;
|
||||
break;
|
||||
case 1:
|
||||
rv.type = RCTTypeBulletproof;
|
||||
break;
|
||||
default:
|
||||
ASSERT_MES_AND_THROW("Unsupported BP version: " << rct_config.bp_version);
|
||||
}
|
||||
}
|
||||
else
|
||||
rv.type = RCTTypeSimple;
|
||||
CHECK_AND_ASSERT_THROW_MES(
|
||||
rct_config.range_proof_type != RangeProofType::Borromean &&
|
||||
(rct_config.bp_version == 3 || rct_config.bp_version == 0), // 0 means latest version
|
||||
"Unable to generate rct for non-CLSAG-bulletproof");
|
||||
|
||||
rctSig rv;
|
||||
rv.type = RCTType::CLSAG;
|
||||
rv.message = message;
|
||||
rv.outPk.resize(destinations.size());
|
||||
if (!bulletproof)
|
||||
rv.p.rangeSigs.resize(destinations.size());
|
||||
rv.ecdhInfo.resize(destinations.size());
|
||||
|
||||
size_t i;
|
||||
keyV masks(destinations.size()); //sk mask..
|
||||
outSk.resize(destinations.size());
|
||||
for (i = 0; i < destinations.size(); i++) {
|
||||
|
||||
//add destination to sig
|
||||
rv.outPk[i].dest = copy(destinations[i]);
|
||||
//compute range proof
|
||||
if (!bulletproof)
|
||||
rv.p.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, outamounts[i]);
|
||||
#ifdef DBG
|
||||
if (!bulletproof)
|
||||
CHECK_AND_ASSERT_THROW_MES(verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]), "verRange failed on newly created proof");
|
||||
#endif
|
||||
}
|
||||
|
||||
rv.p.bulletproofs.clear();
|
||||
if (bulletproof)
|
||||
size_t n_amounts = outamounts.size();
|
||||
size_t amounts_proved = 0;
|
||||
if (rct_config.range_proof_type == RangeProofType::PaddedBulletproof)
|
||||
{
|
||||
size_t n_amounts = outamounts.size();
|
||||
size_t amounts_proved = 0;
|
||||
if (rct_config.range_proof_type == RangeProofPaddedBulletproof)
|
||||
rct::keyV C, masks;
|
||||
if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE)
|
||||
{
|
||||
rct::keyV C, masks;
|
||||
if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE)
|
||||
{
|
||||
// use a fake bulletproof for speed
|
||||
rv.p.bulletproofs.push_back(make_dummy_bulletproof(outamounts, C, masks));
|
||||
}
|
||||
else
|
||||
{
|
||||
const epee::span<const key> keys{&amount_keys[0], amount_keys.size()};
|
||||
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts, keys, hwdev));
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
|
||||
#endif
|
||||
}
|
||||
for (i = 0; i < outamounts.size(); ++i)
|
||||
{
|
||||
rv.outPk[i].mask = rct::scalarmult8(C[i]);
|
||||
outSk[i].mask = masks[i];
|
||||
}
|
||||
// use a fake bulletproof for speed
|
||||
rv.p.bulletproofs.push_back(make_dummy_bulletproof(outamounts, C, masks));
|
||||
}
|
||||
else while (amounts_proved < n_amounts)
|
||||
else
|
||||
{
|
||||
size_t batch_size = 1;
|
||||
if (rct_config.range_proof_type == RangeProofMultiOutputBulletproof)
|
||||
while (batch_size * 2 + amounts_proved <= n_amounts && batch_size * 2 <= BULLETPROOF_MAX_OUTPUTS)
|
||||
batch_size *= 2;
|
||||
rct::keyV C, masks;
|
||||
std::vector<uint64_t> batch_amounts(batch_size);
|
||||
for (i = 0; i < batch_size; ++i)
|
||||
batch_amounts[i] = outamounts[i + amounts_proved];
|
||||
if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE)
|
||||
{
|
||||
// use a fake bulletproof for speed
|
||||
rv.p.bulletproofs.push_back(make_dummy_bulletproof(batch_amounts, C, masks));
|
||||
}
|
||||
else
|
||||
{
|
||||
const epee::span<const key> keys{&amount_keys[amounts_proved], batch_size};
|
||||
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts, keys, hwdev));
|
||||
const epee::span<const key> keys{&amount_keys[0], amount_keys.size()};
|
||||
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts, keys, hwdev));
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
|
||||
CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
|
||||
#endif
|
||||
}
|
||||
for (i = 0; i < batch_size; ++i)
|
||||
{
|
||||
rv.outPk[i + amounts_proved].mask = rct::scalarmult8(C[i]);
|
||||
outSk[i + amounts_proved].mask = masks[i];
|
||||
}
|
||||
amounts_proved += batch_size;
|
||||
}
|
||||
for (i = 0; i < outamounts.size(); ++i)
|
||||
{
|
||||
rv.outPk[i].mask = rct::scalarmult8(C[i]);
|
||||
outSk[i].mask = masks[i];
|
||||
}
|
||||
}
|
||||
else while (amounts_proved < n_amounts)
|
||||
{
|
||||
size_t batch_size = 1;
|
||||
if (rct_config.range_proof_type == RangeProofType::MultiOutputBulletproof)
|
||||
while (batch_size * 2 + amounts_proved <= n_amounts && batch_size * 2 <= BULLETPROOF_MAX_OUTPUTS)
|
||||
batch_size *= 2;
|
||||
rct::keyV C, masks;
|
||||
std::vector<uint64_t> batch_amounts(batch_size);
|
||||
for (i = 0; i < batch_size; ++i)
|
||||
batch_amounts[i] = outamounts[i + amounts_proved];
|
||||
if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE)
|
||||
{
|
||||
// use a fake bulletproof for speed
|
||||
rv.p.bulletproofs.push_back(make_dummy_bulletproof(batch_amounts, C, masks));
|
||||
}
|
||||
else
|
||||
{
|
||||
const epee::span<const key> keys{&amount_keys[amounts_proved], batch_size};
|
||||
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts, keys, hwdev));
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
|
||||
#endif
|
||||
}
|
||||
for (i = 0; i < batch_size; ++i)
|
||||
{
|
||||
rv.outPk[i + amounts_proved].mask = rct::scalarmult8(C[i]);
|
||||
outSk[i + amounts_proved].mask = masks[i];
|
||||
}
|
||||
amounts_proved += batch_size;
|
||||
}
|
||||
|
||||
key sumout = zero();
|
||||
|
@ -1187,20 +902,14 @@ namespace rct {
|
|||
//mask amount and mask
|
||||
rv.ecdhInfo[i].mask = copy(outSk[i].mask);
|
||||
rv.ecdhInfo[i].amount = d2h(outamounts[i]);
|
||||
hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG);
|
||||
hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], true);
|
||||
}
|
||||
|
||||
//set txn fee
|
||||
rv.txnFee = txnFee;
|
||||
// TODO: unused ??
|
||||
// key txnFeeKey = scalarmultH(d2h(rv.txnFee));
|
||||
rv.mixRing = mixRing;
|
||||
keyV &pseudoOuts = bulletproof ? rv.p.pseudoOuts : rv.pseudoOuts;
|
||||
keyV &pseudoOuts = rv.p.pseudoOuts;
|
||||
pseudoOuts.resize(inamounts.size());
|
||||
if (rv.type == RCTTypeCLSAG)
|
||||
rv.p.CLSAGs.resize(inamounts.size());
|
||||
else
|
||||
rv.p.MGs.resize(inamounts.size());
|
||||
rv.p.CLSAGs.resize(inamounts.size());
|
||||
key sumpouts = zero(); //sum pseudoOut masks
|
||||
keyV a(inamounts.size());
|
||||
for (i = 0 ; i < inamounts.size() - 1; i++) {
|
||||
|
@ -1216,18 +925,11 @@ namespace rct {
|
|||
if (msout)
|
||||
{
|
||||
msout->c.resize(inamounts.size());
|
||||
msout->mu_p.resize(rv.type == RCTTypeCLSAG ? inamounts.size() : 0);
|
||||
msout->mu_p.resize(inamounts.size());
|
||||
}
|
||||
for (i = 0 ; i < inamounts.size(); i++)
|
||||
{
|
||||
if (rv.type == RCTTypeCLSAG)
|
||||
{
|
||||
rv.p.CLSAGs[i] = proveRctCLSAGSimple(full_message, rv.mixRing[i], inSk[i], a[i], pseudoOuts[i], kLRki ? &(*kLRki)[i]: NULL, msout ? &msout->c[i] : NULL, msout ? &msout->mu_p[i] : NULL, index[i], hwdev);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv.p.MGs[i] = proveRctMGSimple(full_message, rv.mixRing[i], inSk[i], a[i], pseudoOuts[i], kLRki ? &(*kLRki)[i]: NULL, msout ? &msout->c[i] : NULL, index[i], hwdev);
|
||||
}
|
||||
rv.p.CLSAGs[i] = proveRctCLSAGSimple(full_message, rv.mixRing[i], inSk[i], a[i], pseudoOuts[i], kLRki ? &(*kLRki)[i]: NULL, msout ? &msout->c[i] : NULL, msout ? &msout->mu_p[i] : NULL, index[i], hwdev);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -97,8 +97,6 @@ namespace rct {
|
|||
// this shows that sum inputs = sum outputs
|
||||
//Ver:
|
||||
// verifies the above sig is created corretly
|
||||
mgSig proveRctMG(const ctkeyM & pubs, const ctkeyV & inSk, const keyV &outMasks, const ctkeyV & outPk, const multisig_kLRki *kLRki, key *mscout, unsigned int index, const key &txnFee, const key &message, hw::device &hwdev);
|
||||
mgSig proveRctMGSimple(const key & message, const ctkeyV & pubs, const ctkey & inSk, const key &a , const key &Cout, const multisig_kLRki *kLRki, key *mscout, unsigned int index, hw::device &hwdev);
|
||||
bool verRctMG(const mgSig &mg, const ctkeyM & pubs, const ctkeyV & outPk, const key &txnFee, const key &message);
|
||||
bool verRctMGSimple(const key &message, const mgSig &mg, const ctkeyV & pubs, const key & C);
|
||||
|
||||
|
@ -120,16 +118,14 @@ namespace rct {
|
|||
//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
|
||||
// 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, 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, 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, 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, const RCTConfig &rct_config, hw::device &hwdev);
|
||||
bool verRct(const rctSig & rv, bool semantics);
|
||||
static inline bool verRct(const rctSig & rv) { return verRct(rv, true) && verRct(rv, false); }
|
||||
inline bool verRct(const rctSig & rv) { return verRct(rv, true) && verRct(rv, false); }
|
||||
bool verRctSemanticsSimple(const rctSig & rv);
|
||||
bool verRctSemanticsSimple(const std::vector<const rctSig*> & rv);
|
||||
bool verRctNonSemanticsSimple(const rctSig & rv);
|
||||
static inline bool verRctSimple(const rctSig & rv) { return verRctSemanticsSimple(rv) && verRctNonSemanticsSimple(rv); }
|
||||
inline bool verRctSimple(const rctSig & rv) { return verRctSemanticsSimple(rv) && verRctNonSemanticsSimple(rv); }
|
||||
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask, hw::device &hwdev);
|
||||
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, hw::device &hwdev);
|
||||
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key & mask, hw::device &hwdev);
|
||||
|
|
|
@ -243,7 +243,7 @@ namespace rct {
|
|||
if (Archive::is_deserializer)
|
||||
v.resize(size);
|
||||
else if (v.size() != size)
|
||||
throw std::invalid_argument{"invalid "s + std::string{tag} + " size"s};
|
||||
throw std::invalid_argument{"invalid " + std::string{tag} + " size: " + std::to_string(size) + " (given size) != " + std::to_string(v.size()) + " (# elements)"};
|
||||
return ar.begin_array();
|
||||
}
|
||||
|
||||
|
@ -267,7 +267,7 @@ namespace rct {
|
|||
inline bool is_rct_bulletproof(RCTType type) { return tools::equals_any(type, RCTType::Bulletproof, RCTType::Bulletproof2, RCTType::CLSAG); }
|
||||
inline bool is_rct_borromean(RCTType type) { return tools::equals_any(type, RCTType::Simple, RCTType::Full); }
|
||||
|
||||
enum class RangeProofType { Borromean, Bulletproof, MultiOutputBulletproof, PaddedBulletproof };
|
||||
enum class RangeProofType : uint8_t { Borromean = 0, Bulletproof = 1, MultiOutputBulletproof = 2, PaddedBulletproof = 3 };
|
||||
struct RCTConfig {
|
||||
RangeProofType range_proof_type;
|
||||
int bp_version;
|
||||
|
@ -285,7 +285,7 @@ namespace rct {
|
|||
template <typename Archive>
|
||||
void serialize_rctsig_base(Archive &ar, size_t inputs, size_t outputs)
|
||||
{
|
||||
field_varint(ar, "type", type);
|
||||
field_varint(ar, "type", type, [](const RCTType& x) { return x <= RCTType::CLSAG; });
|
||||
if (type == RCTType::Null)
|
||||
return;
|
||||
if (!tools::equals_any(type, RCTType::Full, RCTType::Simple, RCTType::Bulletproof, RCTType::Bulletproof2, RCTType::CLSAG))
|
||||
|
|
|
@ -1684,15 +1684,15 @@ static uint64_t decodeRct(const rct::rctSig & rv, const crypto::key_derivation &
|
|||
{
|
||||
switch (rv.type)
|
||||
{
|
||||
case rct::RCTTypeSimple:
|
||||
case rct::RCTTypeBulletproof:
|
||||
case rct::RCTTypeBulletproof2:
|
||||
case rct::RCTTypeCLSAG:
|
||||
case rct::RCTType::Simple:
|
||||
case rct::RCTType::Bulletproof:
|
||||
case rct::RCTType::Bulletproof2:
|
||||
case rct::RCTType::CLSAG:
|
||||
return rct::decodeRctSimple(rv, rct::sk2rct(scalar1), i, mask, hwdev);
|
||||
case rct::RCTTypeFull:
|
||||
case rct::RCTType::Full:
|
||||
return rct::decodeRct(rv, rct::sk2rct(scalar1), i, mask, hwdev);
|
||||
default:
|
||||
LOG_ERROR(__func__ << ": Unsupported rct type: " << rv.type);
|
||||
LOG_ERROR(__func__ << ": Unsupported rct type: " << (int)rv.type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -10140,7 +10140,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
|
|||
ptx.construction_data.tx_type = tx_params.tx_type;
|
||||
ptx.construction_data.hf_version = tx_params.hf_version;
|
||||
ptx.construction_data.rct_config = {
|
||||
tx.rct_signatures.p.bulletproofs.empty() ? rct::RangeProofBorromean : rct::RangeProofPaddedBulletproof,
|
||||
tx.rct_signatures.p.bulletproofs.empty() ? rct::RangeProofType::Borromean : rct::RangeProofType::PaddedBulletproof,
|
||||
use_fork_rules(HF_VERSION_CLSAG, 0) ? 3 : 2
|
||||
};
|
||||
ptx.construction_data.dests = dsts;
|
||||
|
@ -10834,7 +10834,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
uint64_t needed_fee, available_for_fee = 0;
|
||||
uint64_t upper_transaction_weight_limit = get_upper_transaction_weight_limit();
|
||||
const bool clsag = use_fork_rules(HF_VERSION_CLSAG, 0);
|
||||
const rct::RCTConfig rct_config{rct::RangeProofPaddedBulletproof, clsag ? 3 : 2};
|
||||
const rct::RCTConfig rct_config{rct::RangeProofType::PaddedBulletproof, clsag ? 3 : 2};
|
||||
|
||||
const auto base_fee = get_base_fees();
|
||||
const uint64_t fee_percent = get_fee_percent(priority, tx_params.tx_type);
|
||||
|
@ -11497,7 +11497,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||
std::vector<std::vector<get_outs_entry>> outs;
|
||||
|
||||
const bool clsag = use_fork_rules(HF_VERSION_CLSAG, 0);
|
||||
const rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, clsag ? 3 : 2 };
|
||||
const rct::RCTConfig rct_config { rct::RangeProofType::PaddedBulletproof, clsag ? 3 : 2 };
|
||||
const auto base_fee = get_base_fees();
|
||||
const uint64_t fee_percent = get_fee_percent(priority, tx_type);
|
||||
const uint64_t fee_quantization_mask = get_fee_quantization_mask();
|
||||
|
@ -12313,7 +12313,7 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt
|
|||
if (found)
|
||||
{
|
||||
uint64_t amount;
|
||||
if (tx.version == txversion::v1 || tx.rct_signatures.type == rct::RCTTypeNull)
|
||||
if (tx.version == txversion::v1 || tx.rct_signatures.type == rct::RCTType::Null)
|
||||
{
|
||||
amount = tx.vout[n].amount;
|
||||
}
|
||||
|
@ -12322,7 +12322,7 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt
|
|||
crypto::secret_key scalar1;
|
||||
crypto::derivation_to_scalar(found_derivation, n, scalar1);
|
||||
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n];
|
||||
rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tools::equals_any(tx.rct_signatures.type, rct::RCTTypeBulletproof2, rct::RCTTypeCLSAG));
|
||||
rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tools::equals_any(tx.rct_signatures.type, rct::RCTType::Bulletproof2, rct::RCTType::CLSAG));
|
||||
const rct::key C = tx.rct_signatures.outPk[n].mask;
|
||||
rct::key Ctmp;
|
||||
THROW_WALLET_EXCEPTION_IF(sc_check(ecdh_info.mask.bytes) != 0, error::wallet_internal_error, "Bad ECDH input mask");
|
||||
|
@ -12879,7 +12879,7 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr
|
|||
crypto::secret_key shared_secret;
|
||||
crypto::derivation_to_scalar(derivation, proof.index_in_tx, shared_secret);
|
||||
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[proof.index_in_tx];
|
||||
rct::ecdhDecode(ecdh_info, rct::sk2rct(shared_secret), tools::equals_any(tx.rct_signatures.type, rct::RCTTypeBulletproof2, rct::RCTTypeCLSAG));
|
||||
rct::ecdhDecode(ecdh_info, rct::sk2rct(shared_secret), tools::equals_any(tx.rct_signatures.type, rct::RCTType::Bulletproof2, rct::RCTType::CLSAG));
|
||||
amount = rct::h2d(ecdh_info.amount);
|
||||
}
|
||||
total += amount;
|
||||
|
|
|
@ -272,11 +272,12 @@ bool gen_bp_tx_validation_base::generate_with(std::vector<test_event_entry>& eve
|
|||
rct::key rct_tx_mask;
|
||||
|
||||
uint64_t amount = 0;
|
||||
const uint8_t type = rct_txes.back().rct_signatures.type;
|
||||
const auto& sigs = rct_txes.back().rct_signatures;
|
||||
const auto type = sigs.type;
|
||||
if (rct::is_rct_simple(type))
|
||||
amount = rct::decodeRctSimple(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default"));
|
||||
amount = rct::decodeRctSimple(sigs, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default"));
|
||||
else
|
||||
amount = rct::decodeRct(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default"));
|
||||
amount = rct::decodeRct(sigs, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default"));
|
||||
|
||||
total_amount_encoded += amount;
|
||||
}
|
||||
|
|
|
@ -1490,7 +1490,7 @@ uint64_t get_amount(const cryptonote::account_base& account, const cryptonote::t
|
|||
else if (tx.rct_signatures.type == rct::RCTType::Null)
|
||||
money_transferred = tx.vout[i].amount;
|
||||
else {
|
||||
LOG_PRINT_L0(__func__ << ": Unsupported rct type: " << +tx.rct_signatures.type);
|
||||
LOG_PRINT_L0(__func__ << ": Unsupported rct type: " << (int)tx.rct_signatures.type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,13 +53,11 @@
|
|||
#include "sc_reduce32.h"
|
||||
#include "sc_check.h"
|
||||
#include "cn_fast_hash.h"
|
||||
#include "rct_mlsag.h"
|
||||
#include "equality.h"
|
||||
#include "range_proof.h"
|
||||
#include "bulletproof.h"
|
||||
#include "crypto_ops.h"
|
||||
#include "multiexp.h"
|
||||
#include "sig_mlsag.h"
|
||||
#include "sig_clsag.h"
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
@ -202,13 +200,6 @@ int main(int argc, char** argv)
|
|||
TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 32);
|
||||
TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 16384);
|
||||
|
||||
TEST_PERFORMANCE3(filter, p, test_sig_mlsag, 4, 2, 2); // MLSAG verification
|
||||
TEST_PERFORMANCE3(filter, p, test_sig_mlsag, 8, 2, 2);
|
||||
TEST_PERFORMANCE3(filter, p, test_sig_mlsag, 16, 2, 2);
|
||||
TEST_PERFORMANCE3(filter, p, test_sig_mlsag, 32, 2, 2);
|
||||
TEST_PERFORMANCE3(filter, p, test_sig_mlsag, 64, 2, 2);
|
||||
TEST_PERFORMANCE3(filter, p, test_sig_mlsag, 128, 2, 2);
|
||||
TEST_PERFORMANCE3(filter, p, test_sig_mlsag, 256, 2, 2);
|
||||
TEST_PERFORMANCE3(filter, p, test_sig_clsag, 4, 2, 2); // CLSAG verification
|
||||
TEST_PERFORMANCE3(filter, p, test_sig_clsag, 8, 2, 2);
|
||||
TEST_PERFORMANCE3(filter, p, test_sig_clsag, 16, 2, 2);
|
||||
|
@ -217,9 +208,6 @@ int main(int argc, char** argv)
|
|||
TEST_PERFORMANCE3(filter, p, test_sig_clsag, 128, 2, 2);
|
||||
TEST_PERFORMANCE3(filter, p, test_sig_clsag, 256, 2, 2);
|
||||
|
||||
TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, false);
|
||||
TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, true);
|
||||
|
||||
TEST_PERFORMANCE2(filter, p, test_equality, memcmp32, true);
|
||||
TEST_PERFORMANCE2(filter, p, test_equality, memcmp32, false);
|
||||
TEST_PERFORMANCE2(filter, p, test_equality, verify32, false);
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
// Copyright (c) 2014-2017, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ringct/rctSigs.h"
|
||||
#include "cryptonote_basic/cryptonote_basic.h"
|
||||
|
||||
#include "single_tx_test_base.h"
|
||||
|
||||
template<size_t ring_size, bool ver>
|
||||
class test_ringct_mlsag : public single_tx_test_base
|
||||
{
|
||||
public:
|
||||
static const size_t cols = ring_size;
|
||||
static const size_t rows = 2; // single spend and commitment data
|
||||
static const size_t loop_count = 1000;
|
||||
|
||||
bool init()
|
||||
{
|
||||
if (!single_tx_test_base::init())
|
||||
return false;
|
||||
|
||||
rct::keyV xtmp = rct::skvGen(rows);
|
||||
rct::keyM xm = rct::keyMInit(rows, cols);// = [[None]*N] #just used to generate test public keys
|
||||
sk = rct::skvGen(rows);
|
||||
P = rct::keyMInit(rows, cols);// = keyM[[None]*N] #stores the public keys;
|
||||
ind = 2;
|
||||
for (size_t j = 0 ; j < rows ; j++)
|
||||
{
|
||||
for (size_t i = 0 ; i < cols ; i++)
|
||||
{
|
||||
xm[i][j] = rct::skGen();
|
||||
P[i][j] = rct::scalarmultBase(xm[i][j]);
|
||||
}
|
||||
}
|
||||
for (size_t j = 0 ; j < rows ; j++)
|
||||
{
|
||||
sk[j] = xm[ind][j];
|
||||
}
|
||||
IIccss = MLSAG_Gen(rct::identity(), P, sk, NULL, NULL, ind, rows-1, hw::get_device("default"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test()
|
||||
{
|
||||
if (ver)
|
||||
MLSAG_Ver(rct::identity(), P, IIccss, rows-1);
|
||||
else
|
||||
MLSAG_Gen(rct::identity(), P, sk, NULL, NULL, ind, rows-1, hw::get_device("default"));
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
rct::keyV sk;
|
||||
rct::keyM P;
|
||||
size_t ind{};
|
||||
rct::mgSig IIccss;
|
||||
};
|
|
@ -1,172 +0,0 @@
|
|||
// Copyright (c) 2014-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ringct/rctSigs.h"
|
||||
#include "ringct/rctTypes.h"
|
||||
#include "device/device.hpp"
|
||||
|
||||
using namespace rct;
|
||||
|
||||
template<size_t a_N, size_t a_T, size_t a_w>
|
||||
class test_sig_mlsag
|
||||
{
|
||||
public:
|
||||
static const size_t loop_count = 1000;
|
||||
static const size_t N = a_N;
|
||||
static const size_t T = a_T;
|
||||
static const size_t w = a_w;
|
||||
|
||||
bool init()
|
||||
{
|
||||
pubs.reserve(N);
|
||||
pubs.resize(N);
|
||||
|
||||
r = keyV(w); // M[l[u]] = Com(0,r[u])
|
||||
|
||||
a = keyV(w); // P[l[u]] = Com(a[u],s[u])
|
||||
s = keyV(w);
|
||||
|
||||
Q = keyV(T); // Q[j] = Com(b[j],t[j])
|
||||
b = keyV(T);
|
||||
t = keyV(T);
|
||||
|
||||
// Random keys
|
||||
key temp;
|
||||
for (size_t k = 0; k < N; k++)
|
||||
{
|
||||
skpkGen(temp,pubs[k].dest);
|
||||
skpkGen(temp,pubs[k].mask);
|
||||
}
|
||||
|
||||
// Signing and commitment keys (assumes fixed signing indices 0,1,...,w-1 for this test)
|
||||
// TODO: random signing indices
|
||||
C_offsets = keyV(w); // P[l[u]] - C_offsets[u] = Com(0,s[u]-s1[u])
|
||||
s1 = keyV(w);
|
||||
key a_sum = zero();
|
||||
key s1_sum = zero();
|
||||
messages = keyV(w);
|
||||
for (size_t u = 0; u < w; u++)
|
||||
{
|
||||
skpkGen(r[u],pubs[u].dest); // M[u] = Com(0,r[u])
|
||||
|
||||
a[u] = skGen(); // P[u] = Com(a[u],s[u])
|
||||
s[u] = skGen();
|
||||
addKeys2(pubs[u].mask,s[u],a[u],H);
|
||||
|
||||
s1[u] = skGen(); // C_offsets[u] = Com(a[u],s1[u])
|
||||
addKeys2(C_offsets[u],s1[u],a[u],H);
|
||||
|
||||
sc_add(a_sum.bytes,a_sum.bytes,a[u].bytes);
|
||||
sc_add(s1_sum.bytes,s1_sum.bytes,s1[u].bytes);
|
||||
|
||||
messages[u] = skGen();
|
||||
}
|
||||
|
||||
// Outputs
|
||||
key b_sum = zero();
|
||||
key t_sum = zero();
|
||||
for (size_t j = 0; j < T-1; j++)
|
||||
{
|
||||
b[j] = skGen(); // Q[j] = Com(b[j],t[j])
|
||||
t[j] = skGen();
|
||||
addKeys2(Q[j],t[j],b[j],H);
|
||||
|
||||
sc_add(b_sum.bytes,b_sum.bytes,b[j].bytes);
|
||||
sc_add(t_sum.bytes,t_sum.bytes,t[j].bytes);
|
||||
}
|
||||
// Value/mask balance for Q[T-1]
|
||||
sc_sub(b[T-1].bytes,a_sum.bytes,b_sum.bytes);
|
||||
sc_sub(t[T-1].bytes,s1_sum.bytes,t_sum.bytes);
|
||||
addKeys2(Q[T-1],t[T-1],b[T-1],H);
|
||||
|
||||
// Build proofs
|
||||
sigs.reserve(w);
|
||||
sigs.resize(0);
|
||||
ctkey sk;
|
||||
for (size_t u = 0; u < w; u++)
|
||||
{
|
||||
sk.dest = r[u];
|
||||
sk.mask = s[u];
|
||||
|
||||
sigs.push_back(proveRctMGSimple(messages[u],pubs,sk,s1[u],C_offsets[u],NULL,NULL,u,hw::get_device("default")));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test()
|
||||
{
|
||||
for (size_t u = 0; u < w; u++)
|
||||
{
|
||||
if (!verRctMGSimple(messages[u],sigs[u],pubs,C_offsets[u]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check balanace
|
||||
std::vector<MultiexpData> balance;
|
||||
balance.reserve(w + T);
|
||||
balance.resize(0);
|
||||
key ZERO = zero();
|
||||
key ONE = identity();
|
||||
key MINUS_ONE;
|
||||
sc_sub(MINUS_ONE.bytes,ZERO.bytes,ONE.bytes);
|
||||
for (size_t u = 0; u < w; u++)
|
||||
{
|
||||
balance.push_back({ONE,C_offsets[u]});
|
||||
}
|
||||
for (size_t j = 0; j < T; j++)
|
||||
{
|
||||
balance.push_back({MINUS_ONE,Q[j]});
|
||||
}
|
||||
if (!(straus(balance) == ONE)) // group identity
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
ctkeyV pubs;
|
||||
keyV Q;
|
||||
keyV r;
|
||||
keyV s;
|
||||
keyV s1;
|
||||
keyV t;
|
||||
keyV a;
|
||||
keyV b;
|
||||
keyV C_offsets;
|
||||
keyV messages;
|
||||
std::vector<mgSig> sigs;
|
||||
};
|
|
@ -86,57 +86,6 @@ TEST(ringct, Borromean)
|
|||
ASSERT_FALSE(verifyBorromean(bb, P1v, P2v));
|
||||
}
|
||||
|
||||
TEST(ringct, MG_sigs)
|
||||
{
|
||||
int j = 0;
|
||||
int N = 0;
|
||||
|
||||
//Tests for MG Sigs
|
||||
//#MG sig: true one
|
||||
N = 3;// #cols
|
||||
int R = 3;// #rows
|
||||
keyV xtmp = skvGen(R);
|
||||
keyM xm = keyMInit(R, N);// = [[None]*N] #just used to generate test public keys
|
||||
keyV sk = skvGen(R);
|
||||
keyM P = keyMInit(R, N);// = keyM[[None]*N] #stores the public keys;
|
||||
int ind = 2;
|
||||
int i = 0;
|
||||
for (j = 0 ; j < R ; j++) {
|
||||
for (i = 0 ; i < N ; i++)
|
||||
{
|
||||
xm[i][j] = skGen();
|
||||
P[i][j] = scalarmultBase(xm[i][j]);
|
||||
}
|
||||
}
|
||||
for (j = 0 ; j < R ; j++) {
|
||||
sk[j] = xm[ind][j];
|
||||
}
|
||||
key message = identity();
|
||||
mgSig IIccss = MLSAG_Gen(message, P, sk, NULL, NULL, ind, R, hw::get_device("default"));
|
||||
ASSERT_TRUE(MLSAG_Ver(message, P, IIccss, R));
|
||||
|
||||
//#MG sig: false one
|
||||
N = 3;// #cols
|
||||
R = 3;// #rows
|
||||
xtmp = skvGen(R);
|
||||
keyM xx(N, xtmp);// = [[None]*N] #just used to generate test public keys
|
||||
sk = skvGen(R);
|
||||
//P (N, xtmp);// = keyM[[None]*N] #stores the public keys;
|
||||
|
||||
ind = 2;
|
||||
for (j = 0 ; j < R ; j++) {
|
||||
for (i = 0 ; i < N ; i++)
|
||||
{
|
||||
xx[i][j] = skGen();
|
||||
P[i][j] = scalarmultBase(xx[i][j]);
|
||||
}
|
||||
sk[j] = xx[ind][j];
|
||||
}
|
||||
sk[2] = skGen();//assume we don't know one of the private keys..
|
||||
IIccss = MLSAG_Gen(message, P, sk, NULL, NULL, ind, R, hw::get_device("default"));
|
||||
ASSERT_FALSE(MLSAG_Ver(message, P, IIccss, R));
|
||||
}
|
||||
|
||||
TEST(ringct, CLSAG)
|
||||
{
|
||||
const size_t N = 11;
|
||||
|
@ -335,13 +284,7 @@ TEST(ringct, range_proofs)
|
|||
skpkGen(Sk, Pk);
|
||||
destinations.push_back(Pk);
|
||||
|
||||
const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
|
||||
|
||||
//compute rct data with mixin 3 - should fail since full type with > 1 input
|
||||
bool ok = false;
|
||||
try { genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default")); }
|
||||
catch(...) { ok = true; }
|
||||
ASSERT_TRUE(ok);
|
||||
const rct::RCTConfig rct_config { RangeProofType::Borromean, 0 };
|
||||
|
||||
//compute rct data with mixin 3
|
||||
rctSig s = genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 0, 3, rct_config, hw::get_device("default"));
|
||||
|
@ -406,7 +349,7 @@ TEST(ringct, range_proofs_with_fee)
|
|||
skpkGen(Sk, Pk);
|
||||
destinations.push_back(Pk);
|
||||
|
||||
const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
|
||||
const rct::RCTConfig rct_config { RangeProofType::Borromean, 0 };
|
||||
|
||||
//compute rct data with mixin 3
|
||||
rctSig s = genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 1, 3, rct_config, hw::get_device("default"));
|
||||
|
@ -484,7 +427,7 @@ TEST(ringct, simple)
|
|||
//compute sig with mixin 2
|
||||
xmr_amount txnfee = 1;
|
||||
|
||||
const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
|
||||
const rct::RCTConfig rct_config { RangeProofType::Borromean, 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
|
||||
|
@ -494,35 +437,6 @@ TEST(ringct, simple)
|
|||
decodeRctSimple(s, amount_keys[1], 1, mask, hw::get_device("default"));
|
||||
}
|
||||
|
||||
static rct::rctSig make_sample_rct_sig(int n_inputs, const uint64_t input_amounts[], int n_outputs, const uint64_t output_amounts[], bool last_is_fee)
|
||||
{
|
||||
ctkeyV sc, pc;
|
||||
ctkey sctmp, pctmp;
|
||||
std::vector<xmr_amount >amounts;
|
||||
keyV destinations;
|
||||
keyV amount_keys;
|
||||
key Sk, Pk;
|
||||
|
||||
for (int n = 0; n < n_inputs; ++n) {
|
||||
std::tie(sctmp, pctmp) = ctskpkGen(input_amounts[n]);
|
||||
sc.push_back(sctmp);
|
||||
pc.push_back(pctmp);
|
||||
}
|
||||
|
||||
for (int n = 0; n < n_outputs; ++n) {
|
||||
amounts.push_back(output_amounts[n]);
|
||||
skpkGen(Sk, Pk);
|
||||
if (n < n_outputs - 1 || !last_is_fee)
|
||||
{
|
||||
destinations.push_back(Pk);
|
||||
amount_keys.push_back(rct::hash_to_scalar(rct::zero()));
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
ctkeyV sc, pc;
|
||||
|
@ -546,26 +460,20 @@ static rct::rctSig make_sample_simple_rct_sig(int n_inputs, const uint64_t input
|
|||
destinations.push_back(Pk);
|
||||
}
|
||||
|
||||
const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
|
||||
const rct::RCTConfig rct_config { RangeProofType::Borromean, 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,
|
||||
int n_inputs, const uint64_t input_amounts[], int n_outputs, const uint64_t output_amounts[], bool last_is_fee, bool simple)
|
||||
int n_inputs, const uint64_t input_amounts[], int n_outputs, const uint64_t output_amounts[], bool last_is_fee)
|
||||
{
|
||||
//compute rct data
|
||||
bool valid;
|
||||
try {
|
||||
rctSig s;
|
||||
// simple takes fee as a parameter, non-simple takes it as an extra element to output amounts
|
||||
if (simple) {
|
||||
s = make_sample_simple_rct_sig(n_inputs, input_amounts, last_is_fee ? n_outputs - 1 : n_outputs, output_amounts, last_is_fee ? output_amounts[n_outputs - 1] : 0);
|
||||
valid = verRctSimple(s);
|
||||
}
|
||||
else {
|
||||
s = make_sample_rct_sig(n_inputs, input_amounts, n_outputs, output_amounts, last_is_fee);
|
||||
valid = verRct(s);
|
||||
}
|
||||
s = make_sample_simple_rct_sig(n_inputs, input_amounts, last_is_fee ? n_outputs - 1 : n_outputs, output_amounts, last_is_fee ? output_amounts[n_outputs - 1] : 0);
|
||||
valid = verRctSimple(s);
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
valid = false;
|
||||
|
@ -581,354 +489,193 @@ static bool range_proof_test(bool expected_valid,
|
|||
|
||||
#define NELTS(array) (sizeof(array)/sizeof(array[0]))
|
||||
|
||||
TEST(ringct, range_proofs_reject_empty_outs)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_empty_outs_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_empty_ins)
|
||||
{
|
||||
const uint64_t inputs[] = {};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_empty_ins_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_all_empty)
|
||||
{
|
||||
const uint64_t inputs[] = {};
|
||||
const uint64_t outputs[] = {};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_all_empty_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {};
|
||||
const uint64_t outputs[] = {};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_zero_empty)
|
||||
{
|
||||
const uint64_t inputs[] = {0};
|
||||
const uint64_t outputs[] = {};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_zero_empty_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {0};
|
||||
const uint64_t outputs[] = {};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_empty_zero)
|
||||
{
|
||||
const uint64_t inputs[] = {};
|
||||
const uint64_t outputs[] = {0};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_empty_zero_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {};
|
||||
const uint64_t outputs[] = {0};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_zero_zero)
|
||||
{
|
||||
const uint64_t inputs[] = {0};
|
||||
const uint64_t outputs[] = {0};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_zero_zero_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {0};
|
||||
const uint64_t outputs[] = {0};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_zero_out_first)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {0, 5000};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_zero_out_first_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {0, 5000};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_zero_out_last)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {5000, 0};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_zero_out_last_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {5000, 0};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_zero_out_middle)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {2500, 0, 2500};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_zero_out_middle_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {2500, 0, 2500};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_zero)
|
||||
{
|
||||
const uint64_t inputs[] = {0};
|
||||
const uint64_t outputs[] = {0};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_zero_in_first_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {0, 5000};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_zero_in_last_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {5000, 0};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_zero_in_middle_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {2500, 0, 2500};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_single_lower)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {1};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_single_lower_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {1};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_single_higher)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {5001};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_single_higher_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {5001};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_single_out_negative)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {(uint64_t)-1000ll};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_single_out_negative_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {(uint64_t)-1000ll};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_out_negative_first)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {(uint64_t)-1000ll, 6000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_out_negative_first_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {(uint64_t)-1000ll, 6000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_out_negative_last)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {6000, (uint64_t)-1000ll};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_out_negative_last_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {6000, (uint64_t)-1000ll};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_out_negative_middle)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {3000, (uint64_t)-1000ll, 3000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_out_negative_middle_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {3000, (uint64_t)-1000ll, 3000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_single_in_negative)
|
||||
{
|
||||
const uint64_t inputs[] = {(uint64_t)-1000ll};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_single_in_negative_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {(uint64_t)-1000ll};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_in_negative_first)
|
||||
{
|
||||
const uint64_t inputs[] = {(uint64_t)-1000ll, 6000};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_in_negative_first_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {(uint64_t)-1000ll, 6000};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_in_negative_last)
|
||||
{
|
||||
const uint64_t inputs[] = {6000, (uint64_t)-1000ll};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_in_negative_last_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {6000, (uint64_t)-1000ll};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_in_negative_middle)
|
||||
{
|
||||
const uint64_t inputs[] = {3000, (uint64_t)-1000ll, 3000};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_in_negative_middle_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {3000, (uint64_t)-1000ll, 3000};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_higher_list)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {1000, 1000, 1000, 1000, 1000, 1000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_reject_higher_list_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {1000, 1000, 1000, 1000, 1000, 1000};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_1_to_1)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_1_to_1_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_1_to_N)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {1000, 1000, 1000, 1000, 1000};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_1_to_N_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {5000};
|
||||
const uint64_t outputs[] = {1000, 1000, 1000, 1000, 1000};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false,true));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_N_to_1_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {1000, 1000, 1000, 1000, 1000};
|
||||
const uint64_t outputs[] = {5000};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_N_to_N_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {1000, 1000, 1000, 1000, 1000};
|
||||
const uint64_t outputs[] = {1000, 1000, 1000, 1000, 1000};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs_accept_very_long_simple)
|
||||
|
@ -942,7 +689,7 @@ TEST(ringct, range_proofs_accept_very_long_simple)
|
|||
}
|
||||
std::shuffle(inputs, inputs + N, crypto::random_device{});
|
||||
std::shuffle(outputs, outputs + N, crypto::random_device{});
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false));
|
||||
}
|
||||
|
||||
TEST(ringct, HPow2)
|
||||
|
@ -999,96 +746,46 @@ TEST(ringct, prooveRange_is_non_deterministic)
|
|||
ASSERT_TRUE(memcmp(mask[0].bytes, mask[1].bytes, sizeof(mask[0].bytes)));
|
||||
}
|
||||
|
||||
TEST(ringct, fee_0_valid)
|
||||
{
|
||||
const uint64_t inputs[] = {2000};
|
||||
const uint64_t outputs[] = {2000, 0};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true, false));
|
||||
}
|
||||
|
||||
TEST(ringct, fee_0_valid_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {1000, 1000};
|
||||
const uint64_t outputs[] = {2000, 0};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true, true));
|
||||
}
|
||||
|
||||
TEST(ringct, fee_non_0_valid)
|
||||
{
|
||||
const uint64_t inputs[] = {2000};
|
||||
const uint64_t outputs[] = {1900, 100};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true, false));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true));
|
||||
}
|
||||
|
||||
TEST(ringct, fee_non_0_valid_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {1000, 1000};
|
||||
const uint64_t outputs[] = {1900, 100};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true, true));
|
||||
}
|
||||
|
||||
TEST(ringct, fee_non_0_invalid_higher)
|
||||
{
|
||||
const uint64_t inputs[] = {1000, 1000};
|
||||
const uint64_t outputs[] = {1990, 100};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, true, false));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true));
|
||||
}
|
||||
|
||||
TEST(ringct, fee_non_0_invalid_higher_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {1000, 1000};
|
||||
const uint64_t outputs[] = {1990, 100};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, true, true));
|
||||
}
|
||||
|
||||
TEST(ringct, fee_non_0_invalid_lower)
|
||||
{
|
||||
const uint64_t inputs[] = {1000, 1000};
|
||||
const uint64_t outputs[] = {1000, 100};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, true, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, true));
|
||||
}
|
||||
|
||||
TEST(ringct, fee_non_0_invalid_lower_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {1000, 1000};
|
||||
const uint64_t outputs[] = {1000, 100};
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, true, true));
|
||||
}
|
||||
|
||||
TEST(ringct, fee_burn_valid_one_out)
|
||||
{
|
||||
const uint64_t inputs[] = {2000};
|
||||
const uint64_t outputs[] = {0, 2000};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true, false));
|
||||
EXPECT_TRUE(range_proof_test(false, NELTS(inputs), inputs, NELTS(outputs), outputs, true));
|
||||
}
|
||||
|
||||
TEST(ringct, fee_burn_valid_one_out_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {1000, 1000};
|
||||
const uint64_t outputs[] = {0, 2000};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true, true));
|
||||
}
|
||||
|
||||
TEST(ringct, fee_burn_valid_zero_out)
|
||||
{
|
||||
const uint64_t inputs[] = {2000};
|
||||
const uint64_t outputs[] = {2000};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true, false));
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true));
|
||||
}
|
||||
|
||||
TEST(ringct, fee_burn_valid_zero_out_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {1000, 1000};
|
||||
const uint64_t outputs[] = {2000};
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true, true));
|
||||
}
|
||||
|
||||
static rctSig make_sig()
|
||||
{
|
||||
static const uint64_t inputs[] = {2000};
|
||||
static const uint64_t outputs[] = {1000, 1000};
|
||||
static rct::rctSig sig = make_sample_rct_sig(NELTS(inputs), inputs, NELTS(outputs), outputs, true);
|
||||
return sig;
|
||||
EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true));
|
||||
}
|
||||
|
||||
#define TEST_rctSig_elements(name, op) \
|
||||
|
@ -1100,32 +797,6 @@ TEST(ringct, rctSig_##name) \
|
|||
ASSERT_FALSE(rct::verRct(sig)); \
|
||||
}
|
||||
|
||||
TEST_rctSig_elements(rangeSigs_empty, sig.p.rangeSigs.resize(0));
|
||||
TEST_rctSig_elements(rangeSigs_too_many, sig.p.rangeSigs.push_back(sig.p.rangeSigs.back()));
|
||||
TEST_rctSig_elements(rangeSigs_too_few, sig.p.rangeSigs.pop_back());
|
||||
TEST_rctSig_elements(mgSig_MG_empty, sig.p.MGs.resize(0));
|
||||
TEST_rctSig_elements(mgSig_ss_empty, sig.p.MGs[0].ss.resize(0));
|
||||
TEST_rctSig_elements(mgSig_ss_too_many, sig.p.MGs[0].ss.push_back(sig.p.MGs[0].ss.back()));
|
||||
TEST_rctSig_elements(mgSig_ss_too_few, sig.p.MGs[0].ss.pop_back());
|
||||
TEST_rctSig_elements(mgSig_ss0_empty, sig.p.MGs[0].ss[0].resize(0));
|
||||
TEST_rctSig_elements(mgSig_ss0_too_many, sig.p.MGs[0].ss[0].push_back(sig.p.MGs[0].ss[0].back()));
|
||||
TEST_rctSig_elements(mgSig_ss0_too_few, sig.p.MGs[0].ss[0].pop_back());
|
||||
TEST_rctSig_elements(mgSig_II_empty, sig.p.MGs[0].II.resize(0));
|
||||
TEST_rctSig_elements(mgSig_II_too_many, sig.p.MGs[0].II.push_back(sig.p.MGs[0].II.back()));
|
||||
TEST_rctSig_elements(mgSig_II_too_few, sig.p.MGs[0].II.pop_back());
|
||||
TEST_rctSig_elements(mixRing_empty, sig.mixRing.resize(0));
|
||||
TEST_rctSig_elements(mixRing_too_many, sig.mixRing.push_back(sig.mixRing.back()));
|
||||
TEST_rctSig_elements(mixRing_too_few, sig.mixRing.pop_back());
|
||||
TEST_rctSig_elements(mixRing0_empty, sig.mixRing[0].resize(0));
|
||||
TEST_rctSig_elements(mixRing0_too_many, sig.mixRing[0].push_back(sig.mixRing[0].back()));
|
||||
TEST_rctSig_elements(mixRing0_too_few, sig.mixRing[0].pop_back());
|
||||
TEST_rctSig_elements(ecdhInfo_empty, sig.ecdhInfo.resize(0));
|
||||
TEST_rctSig_elements(ecdhInfo_too_many, sig.ecdhInfo.push_back(sig.ecdhInfo.back()));
|
||||
TEST_rctSig_elements(ecdhInfo_too_few, sig.ecdhInfo.pop_back());
|
||||
TEST_rctSig_elements(outPk_empty, sig.outPk.resize(0));
|
||||
TEST_rctSig_elements(outPk_too_many, sig.outPk.push_back(sig.outPk.back()));
|
||||
TEST_rctSig_elements(outPk_too_few, sig.outPk.pop_back());
|
||||
|
||||
static rct::rctSig make_sig_simple()
|
||||
{
|
||||
static const uint64_t inputs[] = {1000, 1000};
|
||||
|
@ -1182,14 +853,6 @@ TEST(ringct, reject_gen_simple_ver_non_simple)
|
|||
ASSERT_FALSE(rct::verRct(sig));
|
||||
}
|
||||
|
||||
TEST(ringct, reject_gen_non_simple_ver_simple)
|
||||
{
|
||||
const uint64_t inputs[] = {2000};
|
||||
const uint64_t outputs[] = {1000, 1000};
|
||||
rct::rctSig sig = make_sample_rct_sig(NELTS(inputs), inputs, NELTS(outputs), outputs, true);
|
||||
ASSERT_FALSE(rct::verRctSimple(sig));
|
||||
}
|
||||
|
||||
TEST(ringct, key_ostream)
|
||||
{
|
||||
std::stringstream out;
|
||||
|
|
|
@ -579,28 +579,9 @@ TEST(Serialization, serializes_ringct)
|
|||
amount_keys.push_back(rct::hash_to_scalar(rct::zero()));
|
||||
rct::skpkGen(Sk, Pk);
|
||||
destinations.push_back(Pk);
|
||||
//compute rct data with mixin 3
|
||||
const rct::RCTConfig rct_config{ rct::RangeProofType::PaddedBulletproof, 2 };
|
||||
auto s0 = rct::genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 0, 3, rct_config, hw::get_device("default"));
|
||||
|
||||
ASSERT_FALSE(s0.p.MGs.empty());
|
||||
ASSERT_TRUE(s0.p.CLSAGs.empty());
|
||||
const auto& mg = s0.p.MGs[0];
|
||||
auto mg1 = round_trip(s0.p.MGs[0]);
|
||||
ASSERT_EQ(mg.ss, mg1.ss);
|
||||
ASSERT_EQ(mg.cc, mg1.cc);
|
||||
|
||||
// mixRing and II are not serialized, they are meant to be reconstructed
|
||||
ASSERT_TRUE(mg1.II.empty());
|
||||
|
||||
ASSERT_FALSE(s0.p.bulletproofs.empty());
|
||||
auto& bp = s0.p.bulletproofs.front();
|
||||
auto bp1 = round_trip(bp);
|
||||
bp1.V = bp.V; // this is not saved, as it is reconstructed from other tx data
|
||||
ASSERT_EQ(bp, bp1);
|
||||
|
||||
const rct::RCTConfig rct_config_clsag{ rct::RangeProofType::PaddedBulletproof, 3 };
|
||||
s0 = rct::genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 0, 3, rct_config_clsag, hw::get_device("default"));
|
||||
auto s0 = rct::genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 0, 3, rct_config_clsag, hw::get_device("default"));
|
||||
|
||||
ASSERT_FALSE(s0.p.CLSAGs.empty());
|
||||
ASSERT_TRUE(s0.p.MGs.empty());
|
||||
|
|
Loading…
Reference in New Issue