updated RCT functions to support SalviumOne and T-CLSAG use
This commit is contained in:
@@ -355,6 +355,16 @@ namespace boost
|
||||
a & x.D;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, rct::tclsag &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & x.sx;
|
||||
a & x.sy;
|
||||
a & x.c1;
|
||||
// a & x.I; // not serialized, we can recover it from the tx vin
|
||||
a & x.D;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, rct::zk_proof &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
@@ -376,7 +386,7 @@ namespace boost
|
||||
a & x.salvium_data_type;
|
||||
a & x.pr_proof;
|
||||
a & x.sa_proof;
|
||||
if (x.salvium_data_type == rct::SalviumAudit)
|
||||
if (x.salvium_data_type == rct::SalviumZeroAudit)
|
||||
{
|
||||
a & x.cz_proof;
|
||||
a & x.input_verification_data;
|
||||
@@ -438,7 +448,7 @@ namespace boost
|
||||
a & x.type;
|
||||
if (x.type == rct::RCTTypeNull)
|
||||
return;
|
||||
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus && x.type != rct::RCTTypeFullProofs && x.type != rct::RCTTypeSalviumOne)
|
||||
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproofPlus && x.type != rct::RCTTypeFullProofs && x.type != rct::RCTTypeSalviumZero && x.type != rct::RCTTypeSalviumOne)
|
||||
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
|
||||
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
|
||||
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
|
||||
@@ -448,7 +458,7 @@ namespace boost
|
||||
serializeOutPk(a, x.outPk, ver);
|
||||
a & x.txnFee;
|
||||
a & x.p_r;
|
||||
if (x.type == rct::RCTTypeSalviumOne) {
|
||||
if (x.type == rct::RCTTypeSalviumZero || x.type == rct::RCTTypeSalviumOne) {
|
||||
a & x.salvium_data;
|
||||
} else if (x.type == rct::RCTTypeFullProofs) {
|
||||
a & x.salvium_data.pr_proof;
|
||||
@@ -467,6 +477,8 @@ namespace boost
|
||||
a & x.bulletproofs_plus;
|
||||
}
|
||||
a & x.MGs;
|
||||
if (ver >= 3u)
|
||||
a & x.TCLSAGs;
|
||||
if (ver >= 1u)
|
||||
a & x.CLSAGs;
|
||||
if (x.rangeSigs.empty())
|
||||
@@ -479,7 +491,7 @@ namespace boost
|
||||
a & x.type;
|
||||
if (x.type == rct::RCTTypeNull)
|
||||
return;
|
||||
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus && x.type != rct::RCTTypeFullProofs && x.type != rct::RCTTypeSalviumOne)
|
||||
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproofPlus && x.type != rct::RCTTypeFullProofs && x.type != rct::RCTTypeSalviumZero && x.type != rct::RCTTypeSalviumOne)
|
||||
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
|
||||
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
|
||||
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
|
||||
@@ -489,7 +501,7 @@ namespace boost
|
||||
serializeOutPk(a, x.outPk, ver);
|
||||
a & x.txnFee;
|
||||
a & x.p_r;
|
||||
if (x.type == rct::RCTTypeSalviumOne) {
|
||||
if (x.type == rct::RCTTypeSalviumZero || x.type == rct::RCTTypeSalviumOne) {
|
||||
a & x.salvium_data;
|
||||
} else if (x.type == rct::RCTTypeFullProofs) {
|
||||
a & x.salvium_data.pr_proof;
|
||||
@@ -504,9 +516,11 @@ namespace boost
|
||||
a & x.p.bulletproofs_plus;
|
||||
}
|
||||
a & x.p.MGs;
|
||||
if (ver >= 5u)
|
||||
a & x.p.TCLSAGs;
|
||||
if (ver >= 1u)
|
||||
a & x.p.CLSAGs;
|
||||
if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeCLSAG || x.type == rct::RCTTypeBulletproofPlus || x.type == rct::RCTTypeFullProofs || x.type == rct::RCTTypeSalviumOne)
|
||||
if (x.type == rct::RCTTypeBulletproofPlus || x.type == rct::RCTTypeFullProofs || x.type == rct::RCTTypeSalviumZero || x.type == rct::RCTTypeSalviumOne)
|
||||
a & x.p.pseudoOuts;
|
||||
}
|
||||
|
||||
@@ -547,6 +561,6 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_CLASS_VERSION(rct::rctSigPrunable, 2)
|
||||
BOOST_CLASS_VERSION(rct::rctSig, 4)
|
||||
BOOST_CLASS_VERSION(rct::rctSigPrunable, 3)
|
||||
BOOST_CLASS_VERSION(rct::rctSig, 5)
|
||||
BOOST_CLASS_VERSION(rct::multisig_out, 1)
|
||||
|
||||
@@ -834,12 +834,12 @@ namespace cryptonote
|
||||
salvium_data.enc_view_privkey_str = encrypt_pvk(sender_account_keys.m_view_secret_key, PK);
|
||||
|
||||
// And now the rest of the structure
|
||||
salvium_data.salvium_data_type = rct::SalviumAudit;
|
||||
salvium_data.salvium_data_type = rct::SalviumZeroAudit;
|
||||
salvium_data.input_verification_data.reserve(sources.size());
|
||||
salvium_data.spend_pubkey = sender_account_keys.m_account_address.m_spend_public_key;
|
||||
|
||||
} else {
|
||||
salvium_data.salvium_data_type = rct::SalviumNormal;
|
||||
salvium_data.salvium_data_type = rct::SalviumZero;
|
||||
}
|
||||
uint64_t summary_inputs_money = 0;
|
||||
//fill inputs
|
||||
|
||||
+254
-80
@@ -119,6 +119,13 @@ namespace
|
||||
const size_t n_scalars = ring_size;
|
||||
return rct::clsag{rct::keyV(n_scalars, I), I, I, I};
|
||||
}
|
||||
|
||||
rct::tclsag make_dummy_tclsag(size_t ring_size)
|
||||
{
|
||||
const rct::key I = rct::identity();
|
||||
const size_t n_scalars = ring_size;
|
||||
return rct::tclsag{rct::keyV(n_scalars, I), rct::keyV(n_scalars, I), I, I, I};
|
||||
}
|
||||
}
|
||||
|
||||
namespace rct {
|
||||
@@ -365,7 +372,7 @@ namespace rct {
|
||||
return sig;
|
||||
}
|
||||
|
||||
clsagCarrot CLSAG_Gen_Carrot(
|
||||
tclsag TCLSAG_Gen(
|
||||
const key &message,
|
||||
const keyV & P,
|
||||
const key & x, // x term of P
|
||||
@@ -377,7 +384,7 @@ namespace rct {
|
||||
const unsigned int l,
|
||||
hw::device &hwdev)
|
||||
{
|
||||
clsagCarrot sig;
|
||||
tclsag sig;
|
||||
size_t n = P.size(); // ring size
|
||||
CHECK_AND_ASSERT_THROW_MES(n == C.size(), "Signing and commitment key vector sizes must match!");
|
||||
CHECK_AND_ASSERT_THROW_MES(n == C_nonzero.size(), "Signing and commitment key vector sizes must match!");
|
||||
@@ -803,7 +810,7 @@ namespace rct {
|
||||
hashes.push_back(hash2rct(h));
|
||||
|
||||
keyV kv;
|
||||
if (rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG)
|
||||
if (is_rct_bulletproof(rv.type))
|
||||
{
|
||||
kv.reserve((6*2+9) * rv.p.bulletproofs.size());
|
||||
for (const auto &p: rv.p.bulletproofs)
|
||||
@@ -825,7 +832,7 @@ namespace rct {
|
||||
kv.push_back(p.t);
|
||||
}
|
||||
}
|
||||
else if (rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumOne)
|
||||
else if (is_rct_bulletproof_plus(rv.type))
|
||||
{
|
||||
kv.reserve((6*2+6) * rv.p.bulletproofs_plus.size());
|
||||
for (const auto &p: rv.p.bulletproofs_plus)
|
||||
@@ -977,7 +984,7 @@ namespace rct {
|
||||
return result;
|
||||
}
|
||||
|
||||
clsagCarrot proveRctCLSAGSimpleCarrot(const key &message, const ctkeyV &pubs, const key &x, const key &y, const key &mask, const key &a, const key &Cout, unsigned int index, hw::device &hwdev) {
|
||||
tclsag proveRctTCLSAGSimple(const key &message, const ctkeyV &pubs, const key &x, const key &y, const key &mask, const key &a, const key &Cout, unsigned int index, hw::device &hwdev) {
|
||||
//setup vars
|
||||
size_t rows = 1;
|
||||
size_t cols = pubs.size();
|
||||
@@ -1000,7 +1007,7 @@ namespace rct {
|
||||
|
||||
key sk;
|
||||
sc_sub(sk.bytes, mask.bytes, a.bytes); // private key of the output commitment
|
||||
clsagCarrot result = CLSAG_Gen_Carrot(message, P, x, y, C, sk, C_nonzero, Cout, index, hwdev);
|
||||
tclsag result = TCLSAG_Gen(message, P, x, y, C, sk, C_nonzero, Cout, index, hwdev);
|
||||
memwipe(&sk, sizeof(key));
|
||||
return result;
|
||||
}
|
||||
@@ -1197,7 +1204,7 @@ namespace rct {
|
||||
catch (...) { return false; }
|
||||
}
|
||||
|
||||
bool verRctCLSAGSimpleCarrot(const key &message, const clsagCarrot &sig, const ctkeyV & pubs, const key & C_offset) {
|
||||
bool verRctTCLSAGSimple(const key &message, const tclsag &sig, const ctkeyV & pubs, const key & C_offset) {
|
||||
try
|
||||
{
|
||||
PERF_TIMER(verRctCLSAGSimpleCarrot);
|
||||
@@ -1366,55 +1373,60 @@ namespace rct {
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
zk_proof SAProof_Gen(const key &P, const key &x_change, const key &y_change, const key &key_yF) {
|
||||
|
||||
zk_proof SAProof_Gen(const key &P, const key &x_change, const key &key_yF) {
|
||||
|
||||
// Sanity checks for inputs
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(P, rct::zero()), "SAProof_Gen() failed - invalid public key provided");
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(x_change, rct::zero()), "SAProof_Gen() failed - invalid x_change key provided");
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(key_yF, rct::zero()), "SAProof_Gen() failed - invalid shared secret key provided");
|
||||
|
||||
// Declare a return structure
|
||||
zk_proof proof{};
|
||||
proof.z2 = rct::zero();
|
||||
|
||||
// Calculate a random r value and calculate a commitment R for it
|
||||
rct::key r = rct::skGen();
|
||||
proof.R = rct::scalarmultBase(r);
|
||||
|
||||
// Calculate the challenge hash from the commitment plus the pubkey plus the shared secret
|
||||
keyV challenge_keys{proof.R, P, key_yF};
|
||||
rct::key c = rct::hash_to_scalar(challenge_keys);
|
||||
|
||||
rct::key z_x;
|
||||
sc_muladd(z_x.bytes, x_change.bytes, c.bytes, r.bytes);
|
||||
proof.z1 = z_x;
|
||||
|
||||
// Return the proof to the caller
|
||||
return proof;
|
||||
}
|
||||
|
||||
bool SAProof_Ver(const zk_proof &proof, const key &P, const key &key_yF) {
|
||||
|
||||
// Sanity checks for inputs
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(P, rct::zero()), "SAProof_Ver() failed - invalid public key provided");
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(key_yF, rct::zero()), "SAProof_Ver() failed - invalid shared secret key provided");
|
||||
|
||||
// Recompute the challenge hash
|
||||
keyV challenge_keys{proof.R, P, key_yF};
|
||||
rct::key c = rct::hash_to_scalar(challenge_keys);
|
||||
|
||||
// Recalculate the expected commitment using the formula: z_x * G = R + c * P
|
||||
rct::key expected_commitment = rct::addKeys(proof.R, rct::scalarmultKey(P, c));
|
||||
|
||||
// Verify z_x * G matches the expected commitment
|
||||
if (!rct::equalKeys(rct::scalarmultBase(proof.z1), expected_commitment)) {
|
||||
return false; // Verification failed
|
||||
// Sanity checks for inputs
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(P, rct::zero()), "SAProof_Gen() failed - invalid public key provided");
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(x_change, rct::zero()), "SAProof_Gen() failed - invalid x_change key provided");
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(y_change, rct::zero()), "SAProof_Gen() failed - invalid y_change key provided");
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(key_yF, rct::zero()), "SAProof_Gen() failed - invalid shared secret key provided");
|
||||
|
||||
// Declare a return structure
|
||||
zk_proof proof{};
|
||||
|
||||
// Calculate a random r_x and r_y values and calculate a commitment R for it
|
||||
rct::key r_x = rct::skGen();
|
||||
rct::key r_y = rct::skGen();
|
||||
rct::addKeys2(proof.R, r_x, r_y, rct::pk2rct(crypto::get_T()));
|
||||
|
||||
// Calculate the challenge hash from the commitment plus the pubkey plus the shared secret
|
||||
keyV challenge_keys{proof.R, P, key_yF};
|
||||
rct::key c = rct::hash_to_scalar(challenge_keys);
|
||||
|
||||
rct::key z_x,z_y;
|
||||
sc_muladd(z_x.bytes, x_change.bytes, c.bytes, r_x.bytes);
|
||||
sc_muladd(z_y.bytes, y_change.bytes, c.bytes, r_y.bytes);
|
||||
proof.z1 = z_x;
|
||||
proof.z2 = z_y;
|
||||
|
||||
// Return the proof to the caller
|
||||
return proof;
|
||||
}
|
||||
|
||||
// All checks passed
|
||||
return true;
|
||||
}
|
||||
bool SAProof_Ver(const zk_proof &proof, const key &P, const key &key_yF) {
|
||||
|
||||
// Sanity checks for inputs
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(P, rct::zero()), "SAProof_Ver() failed - invalid public key provided");
|
||||
CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(key_yF, rct::zero()), "SAProof_Ver() failed - invalid shared secret key provided");
|
||||
|
||||
// Recompute the challenge hash
|
||||
keyV challenge_keys{proof.R, P, key_yF};
|
||||
rct::key c = rct::hash_to_scalar(challenge_keys);
|
||||
|
||||
// Recalculate the expected commitment using the formula: R + c * P
|
||||
rct::key expected_result = rct::addKeys(proof.R, rct::scalarmultKey(P, c));
|
||||
|
||||
// Verify z_x * G + z_y * T matches the expected commitment
|
||||
rct::key actual_result;
|
||||
rct::addKeys2(actual_result, proof.z1, proof.z2, rct::pk2rct(crypto::get_T()));
|
||||
if (!rct::equalKeys(actual_result, expected_result)) {
|
||||
return false; // Verification failed
|
||||
}
|
||||
|
||||
// All checks passed
|
||||
return true;
|
||||
}
|
||||
|
||||
//RingCT protocol
|
||||
//genRct:
|
||||
@@ -1458,7 +1470,7 @@ namespace rct {
|
||||
//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 || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumOne);
|
||||
hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], is_rct_bulletproof_plus(rv.type));
|
||||
}
|
||||
|
||||
//set txn fee
|
||||
@@ -1485,6 +1497,172 @@ namespace rct {
|
||||
return genRct(message, inSk, destinations, amounts, mixRing, amount_keys, index, outSk, rct_config, hwdev);
|
||||
}
|
||||
|
||||
//RCT simple
|
||||
//for post-rct only
|
||||
rctSig genRctSimpleCarrot(
|
||||
const key &message,
|
||||
const carrot_ctkeyV & inSk,
|
||||
const keyV & destinations,
|
||||
const cryptonote::transaction_type tx_type,
|
||||
const std::string& in_asset_type,
|
||||
const std::vector<std::string> & destination_asset_types,
|
||||
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<unsigned int> & index,
|
||||
ctkeyV &outSk,
|
||||
const RCTConfig &rct_config,
|
||||
hw::device &hwdev,
|
||||
const rct::salvium_data_t &salvium_data,
|
||||
const key &x_change,
|
||||
const key &y_change,
|
||||
const size_t change_index,
|
||||
const key &key_yF
|
||||
)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(rct_config.range_proof_type == RangeProofPaddedBulletproof, "Borromean range proofs no longer supported");
|
||||
CHECK_AND_ASSERT_THROW_MES(destination_asset_types.size() == destinations.size(), "Different number of amount_keys/destinations");
|
||||
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");
|
||||
CHECK_AND_ASSERT_THROW_MES(amount_keys.size() == destinations.size(), "Different number of amount_keys/destinations");
|
||||
CHECK_AND_ASSERT_THROW_MES(index.size() == inSk.size(), "Different number of index/inSk");
|
||||
CHECK_AND_ASSERT_THROW_MES(mixRing.size() == inSk.size(), "Different number of mixRing/inSk");
|
||||
for (size_t n = 0; n < mixRing.size(); ++n) {
|
||||
CHECK_AND_ASSERT_THROW_MES(index[n] < mixRing[n].size(), "Bad index into mixRing");
|
||||
}
|
||||
|
||||
rctSig rv;
|
||||
switch (rct_config.bp_version)
|
||||
{
|
||||
case 0:
|
||||
case 6:
|
||||
rv.type = RCTTypeSalviumOne;
|
||||
break;
|
||||
default:
|
||||
ASSERT_MES_AND_THROW("Unsupported BP version: " << rct_config.bp_version);
|
||||
}
|
||||
|
||||
rv.message = message;
|
||||
rv.outPk.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]);
|
||||
}
|
||||
|
||||
rv.p.bulletproofs.clear();
|
||||
rv.p.bulletproofs_plus.clear();
|
||||
CHECK_AND_ASSERT_THROW_MES(rct_config.range_proof_type == rct::RangeProofPaddedBulletproof,
|
||||
"Unsupported range proof type: " << rct_config.range_proof_type);
|
||||
{
|
||||
rct::keyV C, masks;
|
||||
if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE)
|
||||
{
|
||||
// use a fake bulletproof for speed
|
||||
rv.p.bulletproofs_plus.push_back(make_dummy_bulletproof_plus(outamounts, C, masks));
|
||||
}
|
||||
else
|
||||
{
|
||||
const epee::span<const key> keys{&amount_keys[0], amount_keys.size()};
|
||||
rv.p.bulletproofs_plus.push_back(proveRangeBulletproofPlus(C, masks, outamounts, keys, hwdev));
|
||||
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(verBulletproofPlus(rv.p.bulletproofs_plus.back()), "verBulletproofPlus 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];
|
||||
}
|
||||
}
|
||||
|
||||
key sumout = zero();
|
||||
for (i = 0; i < outSk.size(); ++i)
|
||||
{
|
||||
sc_add(sumout.bytes, outSk[i].mask.bytes, sumout.bytes);
|
||||
|
||||
//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], is_rct_bulletproof_plus(rv.type));
|
||||
}
|
||||
|
||||
//set txn fee
|
||||
rv.txnFee = txnFee;
|
||||
// TODO: unused ??
|
||||
// key txnFeeKey = scalarmultH(d2h(rv.txnFee));
|
||||
rv.mixRing = mixRing;
|
||||
keyV &pseudoOuts = is_rct_bulletproof_plus(rv.type) ? rv.p.pseudoOuts : rv.pseudoOuts;
|
||||
pseudoOuts.resize(inamounts.size());
|
||||
if (is_rct_tclsag(rv.type))
|
||||
rv.p.TCLSAGs.resize(inamounts.size());
|
||||
else if (is_rct_clsag(rv.type))
|
||||
rv.p.CLSAGs.resize(inamounts.size());
|
||||
else
|
||||
rv.p.MGs.resize(inamounts.size());
|
||||
key sumpouts = zero(); //sum pseudoOut masks
|
||||
keyV a(inamounts.size());
|
||||
bool audit = (tx_type == cryptonote::transaction_type::AUDIT && rv.type == RCTTypeSalviumZero && salvium_data.salvium_data_type == rct::SalviumZeroAudit);
|
||||
for (i = 0 ; i < inamounts.size(); i++) {
|
||||
if (audit)
|
||||
a[i] = rct::zero();
|
||||
else
|
||||
skGen(a[i]);
|
||||
sc_add(sumpouts.bytes, a[i].bytes, sumpouts.bytes);
|
||||
genC(pseudoOuts[i], a[i], inamounts[i]);
|
||||
}
|
||||
key difference;
|
||||
sc_sub(difference.bytes, sumpouts.bytes, sumout.bytes);
|
||||
genC(rv.p_r, difference, 0);
|
||||
DP(rv.p_r);
|
||||
if (rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumZero || rv.type == RCTTypeSalviumOne) {
|
||||
rv.salvium_data.pr_proof = PRProof_Gen(difference);
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(PRProof_Ver(rv.p_r, rv.salvium_data.pr_proof), "PRProof_Ver() failed on recently created proof");
|
||||
#endif
|
||||
rv.salvium_data.salvium_data_type = salvium_data.salvium_data_type;
|
||||
if (audit) {
|
||||
// SRCG: populate the audit proof here
|
||||
rv.salvium_data.input_verification_data = salvium_data.input_verification_data;
|
||||
rv.salvium_data.spend_pubkey = salvium_data.spend_pubkey;
|
||||
rv.salvium_data.enc_view_privkey_str = salvium_data.enc_view_privkey_str;
|
||||
rv.salvium_data.cz_proof = PRProof_Gen(outSk[0].mask);
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(PRProof_Ver(rv.outPk[0].mask, rv.salvium_data.cz_proof), "PRProof_Ver() failed on recently created change proof");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Check if spend authority proof is needed (only for TRANSFER TXs)
|
||||
if (tx_type == cryptonote::transaction_type::TRANSFER && rv.type == rct::RCTTypeSalviumOne) {
|
||||
rv.salvium_data.sa_proof = SAProof_Gen(destinations[change_index], x_change, y_change, key_yF);
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(SAProof_Ver(rv.salvium_data.sa_proof, destinations[change_index], key_yF), "SAProof_Ver() failed on recently created proof");
|
||||
#endif
|
||||
}
|
||||
|
||||
key full_message = get_pre_mlsag_hash(rv,hwdev);
|
||||
|
||||
for (i = 0 ; i < inamounts.size(); i++)
|
||||
{
|
||||
if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE)
|
||||
rv.p.TCLSAGs[i] = make_dummy_tclsag(rv.mixRing[i].size());
|
||||
else
|
||||
rv.p.TCLSAGs[i] = proveRctTCLSAGSimple(full_message, rv.mixRing[i], inSk[i].x, inSk[i].y, inSk[i].mask, a[i], pseudoOuts[i], index[i], hwdev);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
//RCT simple
|
||||
//for post-rct only
|
||||
rctSig genRctSimple(
|
||||
@@ -1534,7 +1712,7 @@ namespace rct {
|
||||
rv.type = RCTTypeFullProofs;
|
||||
break;
|
||||
case 6:
|
||||
rv.type = RCTTypeSalviumOne;
|
||||
rv.type = RCTTypeSalviumZero;
|
||||
break;
|
||||
default:
|
||||
ASSERT_MES_AND_THROW("Unsupported BP version: " << rct_config.bp_version);
|
||||
@@ -1653,7 +1831,7 @@ 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 || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumOne);
|
||||
hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumZero);
|
||||
}
|
||||
|
||||
//set txn fee
|
||||
@@ -1669,7 +1847,7 @@ namespace rct {
|
||||
rv.p.MGs.resize(inamounts.size());
|
||||
key sumpouts = zero(); //sum pseudoOut masks
|
||||
keyV a(inamounts.size());
|
||||
bool audit = (tx_type == cryptonote::transaction_type::AUDIT && rv.type == RCTTypeSalviumOne && salvium_data.salvium_data_type == rct::SalviumAudit);
|
||||
bool audit = (tx_type == cryptonote::transaction_type::AUDIT && rv.type == RCTTypeSalviumZero && salvium_data.salvium_data_type == rct::SalviumZeroAudit);
|
||||
for (i = 0 ; i < inamounts.size(); i++) {
|
||||
if (audit)
|
||||
a[i] = rct::zero();
|
||||
@@ -1682,7 +1860,7 @@ namespace rct {
|
||||
sc_sub(difference.bytes, sumpouts.bytes, sumout.bytes);
|
||||
genC(rv.p_r, difference, 0);
|
||||
DP(rv.p_r);
|
||||
if (rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumOne) {
|
||||
if (rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumZero) {
|
||||
rv.salvium_data.pr_proof = PRProof_Gen(difference);
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(PRProof_Ver(rv.p_r, rv.salvium_data.pr_proof), "PRProof_Ver() failed on recently created proof");
|
||||
@@ -1700,16 +1878,6 @@ namespace rct {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Check if spend authority proof is needed (only for TRANSFER TXs)
|
||||
if (tx_type == cryptonote::transaction_type::TRANSFER && rv.type == rct::RCTTypeSalviumOne) {
|
||||
rv.salvium_data.sa_proof = SAProof_Gen(destinations[change_index], x_change, key_yF);
|
||||
#ifdef DBG
|
||||
CHECK_AND_ASSERT_THROW_MES(SAProof_Ver(rv.salvium_data.sa_proof, destinations[change_index], key_yF), "SAProof_Ver() failed on recently created proof");
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
key full_message = get_pre_mlsag_hash(rv,hwdev);
|
||||
|
||||
for (i = 0 ; i < inamounts.size(); i++)
|
||||
@@ -1719,9 +1887,6 @@ namespace rct {
|
||||
if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE)
|
||||
rv.p.CLSAGs[i] = make_dummy_clsag(rv.mixRing[i].size());
|
||||
else {
|
||||
if (rv.type == RCTTypeSalviumOne)
|
||||
rv.p.CLSAGs[i] = proveRctCLSAGSimpleCarrot(full_message, rv.mixRing[i], inSk[i].x, inSk[i].y, inSk[i].dest, a[i], pseudoOuts[i], index[i], hwdev);
|
||||
else
|
||||
rv.p.CLSAGs[i] = proveRctCLSAGSimple(full_message, rv.mixRing[i], inSk[i], a[i], pseudoOuts[i], index[i], hwdev);
|
||||
}
|
||||
}
|
||||
@@ -1852,9 +2017,9 @@ namespace rct {
|
||||
std::vector<const BulletproofPlus*> bpp_proofs;
|
||||
size_t max_non_bp_proofs = 0, offset = 0;
|
||||
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumOne,
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumZero || rv.type == RCTTypeSalviumOne,
|
||||
false, "verRctSemanticsSimple called on non simple rctSig");
|
||||
if (rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumOne)
|
||||
if (rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumZero || rv.type == RCTTypeSalviumOne)
|
||||
CHECK_AND_ASSERT_MES(PRProof_Ver(rv.p_r, rv.salvium_data.pr_proof), false, "Invalid p_r commitment to difference");
|
||||
|
||||
const bool bulletproof = is_rct_bulletproof(rv.type);
|
||||
@@ -1865,8 +2030,15 @@ namespace rct {
|
||||
CHECK_AND_ASSERT_MES(rv.outPk.size() == n_bulletproof_plus_amounts(rv.p.bulletproofs_plus), false, "Mismatched sizes of outPk and bulletproofs_plus");
|
||||
else
|
||||
CHECK_AND_ASSERT_MES(rv.outPk.size() == n_bulletproof_amounts(rv.p.bulletproofs), false, "Mismatched sizes of outPk and bulletproofs");
|
||||
if (is_rct_clsag(rv.type))
|
||||
if (is_rct_tclsag(rv.type))
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(rv.p.CLSAGs.empty(), false, "CLSAGs are not empty for TCLSAG");
|
||||
CHECK_AND_ASSERT_MES(rv.p.MGs.empty(), false, "MGs are not empty for TCLSAG");
|
||||
CHECK_AND_ASSERT_MES(rv.p.pseudoOuts.size() == rv.p.TCLSAGs.size(), false, "Mismatched sizes of rv.p.pseudoOuts and rv.p.TCLSAGs");
|
||||
}
|
||||
else if (is_rct_clsag(rv.type))
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(rv.p.TCLSAGs.empty(), false, "TCLSAGs are not empty for CLSAG");
|
||||
CHECK_AND_ASSERT_MES(rv.p.MGs.empty(), false, "MGs are not empty for CLSAG");
|
||||
CHECK_AND_ASSERT_MES(rv.p.pseudoOuts.size() == rv.p.CLSAGs.size(), false, "Mismatched sizes of rv.p.pseudoOuts and rv.p.CLSAGs");
|
||||
}
|
||||
@@ -1979,7 +2151,7 @@ namespace rct {
|
||||
{
|
||||
PERF_TIMER(verRctNonSemanticsSimple);
|
||||
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumOne,
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumZero || rv.type == RCTTypeSalviumOne,
|
||||
false, "verRctNonSemanticsSimple called on non simple rctSig");
|
||||
const bool bulletproof = is_rct_bulletproof(rv.type);
|
||||
const bool bulletproof_plus = is_rct_bulletproof_plus(rv.type);
|
||||
@@ -2003,7 +2175,9 @@ namespace rct {
|
||||
results.resize(rv.mixRing.size());
|
||||
for (size_t i = 0 ; i < rv.mixRing.size() ; i++) {
|
||||
tpool.submit(&waiter, [&, i] {
|
||||
if (is_rct_clsag(rv.type))
|
||||
if (is_rct_tclsag(rv.type))
|
||||
results[i] = verRctTCLSAGSimple(message, rv.p.TCLSAGs[i], rv.mixRing[i], pseudoOuts[i]);
|
||||
else if (is_rct_clsag(rv.type))
|
||||
results[i] = verRctCLSAGSimple(message, rv.p.CLSAGs[i], rv.mixRing[i], pseudoOuts[i]);
|
||||
else
|
||||
results[i] = verRctMGSimple(message, rv.p.MGs[i], rv.mixRing[i], pseudoOuts[i]);
|
||||
@@ -2019,7 +2193,7 @@ namespace rct {
|
||||
}
|
||||
}
|
||||
|
||||
bool audit = (rv.type == RCTTypeSalviumOne && rv.salvium_data.salvium_data_type == rct::SalviumAudit);
|
||||
bool audit = (rv.type == RCTTypeSalviumZero && rv.salvium_data.salvium_data_type == rct::SalviumZeroAudit);
|
||||
if (audit) {
|
||||
// Validate the Salvium audit data
|
||||
CHECK_AND_ASSERT_THROW_MES(PRProof_Ver(rv.outPk[0].mask, rv.salvium_data.cz_proof), "PRProof_Ver() failed on change proof");
|
||||
@@ -2087,7 +2261,7 @@ namespace rct {
|
||||
|
||||
//mask amount and mask
|
||||
ecdhTuple ecdh_info = rv.ecdhInfo[i];
|
||||
hwdev.ecdhDecode(ecdh_info, sk, rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumOne);
|
||||
hwdev.ecdhDecode(ecdh_info, sk, is_rct_bulletproof_plus(rv.type));
|
||||
mask = ecdh_info.mask;
|
||||
key amount = ecdh_info.amount;
|
||||
key C = rv.outPk[i].mask;
|
||||
@@ -2111,14 +2285,14 @@ namespace rct {
|
||||
}
|
||||
|
||||
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask, hw::device &hwdev) {
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumOne,
|
||||
CHECK_AND_ASSERT_MES(is_rct_bulletproof_plus(rv.type),
|
||||
false, "decodeRct called on non simple rctSig");
|
||||
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
||||
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo");
|
||||
|
||||
//mask amount and mask
|
||||
ecdhTuple ecdh_info = rv.ecdhInfo[i];
|
||||
hwdev.ecdhDecode(ecdh_info, sk, rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeFullProofs || rv.type == RCTTypeSalviumOne);
|
||||
hwdev.ecdhDecode(ecdh_info, sk, is_rct_bulletproof_plus(rv.type));
|
||||
mask = ecdh_info.mask;
|
||||
key amount = ecdh_info.amount;
|
||||
key C = rv.outPk[i].mask;
|
||||
|
||||
+25
-4
@@ -85,14 +85,14 @@ namespace rct {
|
||||
clsag proveRctCLSAGSimple(const key &, const ctkeyV &, const ctkey &, const key &, const key &, unsigned int, hw::device &);
|
||||
bool verRctCLSAGSimple(const key &, const clsag &, const ctkeyV &, const key &);
|
||||
|
||||
clsagCarrot CLSAG_Gen_Carrot(const key &message, const keyV & P, const key & x, const key & y, const keyV & C, const key & z, const keyV & C_nonzero, const key & C_offset, const unsigned int l, hw::device &hwdev);
|
||||
clsagCarrot proveRctCLSAGSimpleCarrot(const key &message, const ctkeyV &pubs, const key &x, const key &y, const key &mask, const key &a, const key &Cout, unsigned int index, hw::device &hwdev);
|
||||
bool verRctCLSAGSimpleCarrot(const key &message, const clsagCarrot &sig, const ctkeyV & pubs, const key & C_offset);
|
||||
tclsag TCLSAG_Gen(const key &message, const keyV & P, const key & x, const key & y, const keyV & C, const key & z, const keyV & C_nonzero, const key & C_offset, const unsigned int l, hw::device &hwdev);
|
||||
tclsag proveRctTCLSAGSimple(const key &message, const ctkeyV &pubs, const key &x, const key &y, const key &mask, const key &a, const key &Cout, unsigned int index, hw::device &hwdev);
|
||||
bool verRctTCLSAGSimple(const key &message, const tclsag &sig, const ctkeyV & pubs, const key & C_offset);
|
||||
|
||||
zk_proof PRProof_Gen(const rct::key &difference);
|
||||
bool PRProof_Ver(const rct::key &C, const zk_proof &proof);
|
||||
|
||||
zk_proof SAProof_Gen(const key &P, const key &x_change, const key &key_yF);
|
||||
zk_proof SAProof_Gen(const key &P, const key &x_change, const key &y_change, const key &key_yF);
|
||||
bool SAProof_Ver(const zk_proof &proof, const key &P, const key &key_yF);
|
||||
|
||||
//proveRange and verRange
|
||||
@@ -138,6 +138,27 @@ namespace rct {
|
||||
// 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, 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 int mixin, const RCTConfig &rct_config, hw::device &hwdev);
|
||||
rctSig genRctSimpleCarrot(
|
||||
const key & message,
|
||||
const carrot_ctkeyV & inSk,
|
||||
const ctkeyV & inPk,
|
||||
const keyV & destinations,
|
||||
const cryptonote::transaction_type tx_type,
|
||||
const std::string& in_asset_type,
|
||||
const std::vector<std::string> & destination_asset_types,
|
||||
const std::vector<xmr_amount> & inamounts,
|
||||
const std::vector<xmr_amount> & outamounts,
|
||||
const keyV &amount_keys,
|
||||
xmr_amount txnFee,
|
||||
unsigned int mixin,
|
||||
const RCTConfig &rct_config,
|
||||
hw::device &hwdev,
|
||||
const rct::salvium_data_t &salvium_data,
|
||||
const key &x_change = rct::zero(),
|
||||
const key &y_change = rct::zero(),
|
||||
const size_t change_index = 0,
|
||||
const key &key_yF = rct::zero()
|
||||
);
|
||||
rctSig genRctSimple(
|
||||
const key & message,
|
||||
const ctkeyV & inSk,
|
||||
|
||||
@@ -198,6 +198,7 @@ namespace rct {
|
||||
case RCTTypeCLSAG:
|
||||
case RCTTypeBulletproofPlus:
|
||||
case RCTTypeFullProofs:
|
||||
case RCTTypeSalviumZero:
|
||||
case RCTTypeSalviumOne:
|
||||
return true;
|
||||
default:
|
||||
@@ -224,6 +225,7 @@ namespace rct {
|
||||
{
|
||||
case RCTTypeBulletproofPlus:
|
||||
case RCTTypeFullProofs:
|
||||
case RCTTypeSalviumZero:
|
||||
case RCTTypeSalviumOne:
|
||||
return true;
|
||||
default:
|
||||
@@ -250,6 +252,18 @@ namespace rct {
|
||||
case RCTTypeCLSAG:
|
||||
case RCTTypeBulletproofPlus:
|
||||
case RCTTypeFullProofs:
|
||||
case RCTTypeSalviumZero:
|
||||
return true;
|
||||
case RCTTypeSalviumOne:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_rct_tclsag(int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case RCTTypeSalviumOne:
|
||||
return true;
|
||||
default:
|
||||
@@ -265,6 +279,7 @@ namespace rct {
|
||||
case RCTTypeCLSAG:
|
||||
case RCTTypeBulletproofPlus:
|
||||
case RCTTypeFullProofs:
|
||||
case RCTTypeSalviumZero:
|
||||
case RCTTypeSalviumOne:
|
||||
return true;
|
||||
case RCTTypeNull:
|
||||
|
||||
+65
-111
@@ -223,8 +223,8 @@ namespace rct {
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
// CLSAG signature
|
||||
struct clsagCarrot {
|
||||
// TCLSAG signature
|
||||
struct tclsag {
|
||||
keyV sx; // x scalars(responses)
|
||||
keyV sy; // y scalars(responses)
|
||||
key c1;
|
||||
@@ -352,7 +352,8 @@ namespace rct {
|
||||
RCTTypeCLSAG = 5,
|
||||
RCTTypeBulletproofPlus = 6,
|
||||
RCTTypeFullProofs = 7,
|
||||
RCTTypeSalviumOne = 8
|
||||
RCTTypeSalviumZero = 8,
|
||||
RCTTypeSalviumOne = 9
|
||||
};
|
||||
enum RangeProofType { RangeProofBorromean, RangeProofBulletproof, RangeProofMultiOutputBulletproof, RangeProofPaddedBulletproof };
|
||||
struct RCTConfig {
|
||||
@@ -366,7 +367,7 @@ namespace rct {
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
enum SalviumDataType { SalviumNormal=0, SalviumAudit=1 };
|
||||
enum SalviumDataType { SalviumZero=0, SalviumZeroAudit=1, SalviumOne=2 };
|
||||
struct salvium_input_data_t {
|
||||
crypto::key_derivation aR;
|
||||
xmr_amount amount;
|
||||
@@ -400,7 +401,7 @@ namespace rct {
|
||||
VARINT_FIELD(salvium_data_type)
|
||||
FIELD(pr_proof)
|
||||
FIELD(sa_proof)
|
||||
if (salvium_data_type == SalviumAudit)
|
||||
if (salvium_data_type == SalviumZeroAudit)
|
||||
{
|
||||
FIELD(cz_proof)
|
||||
FIELD(input_verification_data)
|
||||
@@ -431,27 +432,12 @@ namespace rct {
|
||||
FIELD(type)
|
||||
if (type == RCTTypeNull)
|
||||
return ar.good();
|
||||
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus && type != RCTTypeFullProofs && type != RCTTypeSalviumOne)
|
||||
if (type != RCTTypeBulletproofPlus && type != RCTTypeFullProofs && type != RCTTypeSalviumZero && type != RCTTypeSalviumOne)
|
||||
return false;
|
||||
VARINT_FIELD(txnFee)
|
||||
// inputs/outputs not saved, only here for serialization help
|
||||
// FIELD(message) - not serialized, it can be reconstructed
|
||||
// FIELD(mixRing) - not serialized, it can be reconstructed
|
||||
if (type == RCTTypeSimple) // moved to prunable with bulletproofs
|
||||
{
|
||||
ar.tag("pseudoOuts");
|
||||
ar.begin_array();
|
||||
PREPARE_CUSTOM_VECTOR_SERIALIZATION(inputs, pseudoOuts);
|
||||
if (pseudoOuts.size() != inputs)
|
||||
return false;
|
||||
for (size_t i = 0; i < inputs; ++i)
|
||||
{
|
||||
FIELDS(pseudoOuts[i])
|
||||
if (inputs - i > 1)
|
||||
ar.delimit_array();
|
||||
}
|
||||
ar.end_array();
|
||||
}
|
||||
|
||||
ar.tag("ecdhInfo");
|
||||
ar.begin_array();
|
||||
@@ -460,7 +446,7 @@ namespace rct {
|
||||
return false;
|
||||
for (size_t i = 0; i < outputs; ++i)
|
||||
{
|
||||
if (type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumOne)
|
||||
if (type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumZero)
|
||||
{
|
||||
// Since RCTTypeBulletproof2 enote types, we don't serialize the blinding factor, and only serialize the
|
||||
// first 8 bytes of ecdhInfo[i].amount
|
||||
@@ -497,7 +483,7 @@ namespace rct {
|
||||
}
|
||||
ar.end_array();
|
||||
FIELD(p_r)
|
||||
if (type == RCTTypeSalviumOne)
|
||||
if (type == RCTTypeSalviumZero)
|
||||
{
|
||||
FIELD(salvium_data)
|
||||
}
|
||||
@@ -518,7 +504,7 @@ namespace rct {
|
||||
FIELD(outPk)
|
||||
VARINT_FIELD(txnFee)
|
||||
FIELD(p_r)
|
||||
if (type == RCTTypeSalviumOne)
|
||||
if (type == RCTTypeSalviumZero)
|
||||
{
|
||||
FIELD(salvium_data)
|
||||
}
|
||||
@@ -535,6 +521,7 @@ namespace rct {
|
||||
std::vector<BulletproofPlus> bulletproofs_plus;
|
||||
std::vector<mgSig> MGs; // simple rct has N, full has 1
|
||||
std::vector<clsag> CLSAGs;
|
||||
std::vector<tclsag> TCLSAGs;
|
||||
keyV pseudoOuts; //C - for simple rct
|
||||
|
||||
// when changing this function, update cryptonote::get_pruned_transaction_weight
|
||||
@@ -549,9 +536,8 @@ namespace rct {
|
||||
return false;
|
||||
if (type == RCTTypeNull)
|
||||
return ar.good();
|
||||
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus && type != RCTTypeFullProofs && type != RCTTypeSalviumOne)
|
||||
if (type != RCTTypeBulletproofPlus && type != RCTTypeFullProofs && type != RCTTypeSalviumZero && type != RCTTypeSalviumOne)
|
||||
return false;
|
||||
if (type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumOne)
|
||||
{
|
||||
uint32_t nbp = bulletproofs_plus.size();
|
||||
VARINT_FIELD(nbp)
|
||||
@@ -570,45 +556,61 @@ namespace rct {
|
||||
return false;
|
||||
ar.end_array();
|
||||
}
|
||||
else if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG)
|
||||
|
||||
if (type == RCTTypeSalviumOne)
|
||||
{
|
||||
uint32_t nbp = bulletproofs.size();
|
||||
if (type == RCTTypeBulletproof2 || type == RCTTypeCLSAG)
|
||||
VARINT_FIELD(nbp)
|
||||
else
|
||||
FIELD(nbp)
|
||||
ar.tag("bp");
|
||||
ar.tag("TCLSAGs");
|
||||
ar.begin_array();
|
||||
if (nbp > outputs)
|
||||
PREPARE_CUSTOM_VECTOR_SERIALIZATION(inputs, TCLSAGs);
|
||||
if (TCLSAGs.size() != inputs)
|
||||
return false;
|
||||
PREPARE_CUSTOM_VECTOR_SERIALIZATION(nbp, bulletproofs);
|
||||
for (size_t i = 0; i < nbp; ++i)
|
||||
for (size_t i = 0; i < inputs; ++i)
|
||||
{
|
||||
FIELDS(bulletproofs[i])
|
||||
if (nbp - i > 1)
|
||||
ar.delimit_array();
|
||||
// we save the TCLSAGs contents directly, because we want it to save its
|
||||
// arrays without the size prefixes, and the load can't know what size
|
||||
// to expect if it's not in the data
|
||||
ar.begin_object();
|
||||
ar.tag("sx");
|
||||
ar.begin_array();
|
||||
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mixin + 1, TCLSAGs[i].sx);
|
||||
if (TCLSAGs[i].sx.size() != mixin + 1)
|
||||
return false;
|
||||
for (size_t j = 0; j <= mixin; ++j)
|
||||
{
|
||||
FIELDS(TCLSAGs[i].sx[j])
|
||||
if (mixin + 1 - j > 1)
|
||||
ar.delimit_array();
|
||||
}
|
||||
ar.end_array();
|
||||
|
||||
ar.tag("sy");
|
||||
ar.begin_array();
|
||||
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mixin + 1, TCLSAGs[i].sy);
|
||||
if (TCLSAGs[i].sy.size() != mixin + 1)
|
||||
return false;
|
||||
for (size_t j = 0; j <= mixin; ++j)
|
||||
{
|
||||
FIELDS(TCLSAGs[i].sy[j])
|
||||
if (mixin + 1 - j > 1)
|
||||
ar.delimit_array();
|
||||
}
|
||||
ar.end_array();
|
||||
|
||||
ar.tag("c1");
|
||||
FIELDS(CLSAGs[i].c1)
|
||||
|
||||
// CLSAGs[i].I not saved, it can be reconstructed
|
||||
ar.tag("D");
|
||||
FIELDS(CLSAGs[i].D)
|
||||
ar.end_object();
|
||||
|
||||
if (inputs - i > 1)
|
||||
ar.delimit_array();
|
||||
}
|
||||
if (n_bulletproof_max_amounts(bulletproofs) < outputs)
|
||||
return false;
|
||||
|
||||
ar.end_array();
|
||||
}
|
||||
else
|
||||
{
|
||||
ar.tag("rangeSigs");
|
||||
ar.begin_array();
|
||||
PREPARE_CUSTOM_VECTOR_SERIALIZATION(outputs, rangeSigs);
|
||||
if (rangeSigs.size() != outputs)
|
||||
return false;
|
||||
for (size_t i = 0; i < outputs; ++i)
|
||||
{
|
||||
FIELDS(rangeSigs[i])
|
||||
if (outputs - i > 1)
|
||||
ar.delimit_array();
|
||||
}
|
||||
ar.end_array();
|
||||
}
|
||||
|
||||
if (type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumOne)
|
||||
{
|
||||
ar.tag("CLSAGs");
|
||||
ar.begin_array();
|
||||
@@ -648,58 +650,6 @@ namespace rct {
|
||||
|
||||
ar.end_array();
|
||||
}
|
||||
else
|
||||
{
|
||||
ar.tag("MGs");
|
||||
ar.begin_array();
|
||||
// we keep a byte for size of MGs, because we don't know whether this is
|
||||
// a simple or full rct signature, and it's starting to annoy the hell out of me
|
||||
size_t mg_elements = (type == RCTTypeSimple || type == RCTTypeBulletproof || type == RCTTypeBulletproof2) ? inputs : 1;
|
||||
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_elements, MGs);
|
||||
if (MGs.size() != mg_elements)
|
||||
return false;
|
||||
for (size_t i = 0; i < mg_elements; ++i)
|
||||
{
|
||||
// we save the MGs contents directly, because we want it to save its
|
||||
// arrays and matrices without the size prefixes, and the load can't
|
||||
// know what size to expect if it's not in the data
|
||||
ar.begin_object();
|
||||
ar.tag("ss");
|
||||
ar.begin_array();
|
||||
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mixin + 1, MGs[i].ss);
|
||||
if (MGs[i].ss.size() != mixin + 1)
|
||||
return false;
|
||||
for (size_t j = 0; j < mixin + 1; ++j)
|
||||
{
|
||||
ar.begin_array();
|
||||
size_t mg_ss2_elements = ((type == RCTTypeSimple || type == RCTTypeBulletproof || type == RCTTypeBulletproof2) ? 1 : inputs) + 1;
|
||||
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_ss2_elements, MGs[i].ss[j]);
|
||||
if (MGs[i].ss[j].size() != mg_ss2_elements)
|
||||
return false;
|
||||
for (size_t k = 0; k < mg_ss2_elements; ++k)
|
||||
{
|
||||
FIELDS(MGs[i].ss[j][k])
|
||||
if (mg_ss2_elements - k > 1)
|
||||
ar.delimit_array();
|
||||
}
|
||||
ar.end_array();
|
||||
|
||||
if (mixin + 1 - j > 1)
|
||||
ar.delimit_array();
|
||||
}
|
||||
ar.end_array();
|
||||
|
||||
ar.tag("cc");
|
||||
FIELDS(MGs[i].cc)
|
||||
// MGs[i].II not saved, it can be reconstructed
|
||||
ar.end_object();
|
||||
|
||||
if (mg_elements - i > 1)
|
||||
ar.delimit_array();
|
||||
}
|
||||
ar.end_array();
|
||||
}
|
||||
if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumOne)
|
||||
{
|
||||
ar.tag("pseudoOuts");
|
||||
ar.begin_array();
|
||||
@@ -731,12 +681,12 @@ namespace rct {
|
||||
|
||||
keyV& get_pseudo_outs()
|
||||
{
|
||||
return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumOne ? p.pseudoOuts : pseudoOuts;
|
||||
return type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumZero || type == RCTTypeSalviumOne ? p.pseudoOuts : pseudoOuts;
|
||||
}
|
||||
|
||||
keyV const& get_pseudo_outs() const
|
||||
{
|
||||
return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumOne ? p.pseudoOuts : pseudoOuts;
|
||||
return type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumZero || type == RCTTypeSalviumOne ? p.pseudoOuts : pseudoOuts;
|
||||
}
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
@@ -851,6 +801,7 @@ namespace rct {
|
||||
bool is_rct_bulletproof_plus(int type);
|
||||
bool is_rct_borromean(int type);
|
||||
bool is_rct_clsag(int type);
|
||||
bool is_rct_tclsag(int type);
|
||||
bool is_rct_short_amount(int type);
|
||||
|
||||
static inline const rct::key &pk2rct(const crypto::public_key &pk) { return (const rct::key&)pk; }
|
||||
@@ -908,6 +859,7 @@ VARIANT_TAG(debug_archive, rct::Bulletproof, "rct::bulletproof");
|
||||
VARIANT_TAG(debug_archive, rct::multisig_kLRki, "rct::multisig_kLRki");
|
||||
VARIANT_TAG(debug_archive, rct::multisig_out, "rct::multisig_out");
|
||||
VARIANT_TAG(debug_archive, rct::clsag, "rct::clsag");
|
||||
VARIANT_TAG(debug_archive, rct::tclsag, "rct::tclsag");
|
||||
VARIANT_TAG(debug_archive, rct::BulletproofPlus, "rct::bulletproof_plus");
|
||||
VARIANT_TAG(debug_archive, rct::zk_proof, "rct::zk_proof");
|
||||
VARIANT_TAG(debug_archive, rct::salvium_input_data_t, "rct::salvium_input_data");
|
||||
@@ -933,6 +885,7 @@ VARIANT_TAG(binary_archive, rct::BulletproofPlus, 0xa0);
|
||||
VARIANT_TAG(binary_archive, rct::zk_proof, 0xa1);
|
||||
VARIANT_TAG(binary_archive, rct::salvium_input_data_t, 0xa2);
|
||||
VARIANT_TAG(binary_archive, rct::salvium_data_t, 0xa3);
|
||||
VARIANT_TAG(binary_archive, rct::tclsag, 0xa4);
|
||||
|
||||
VARIANT_TAG(json_archive, rct::key, "rct_key");
|
||||
VARIANT_TAG(json_archive, rct::key64, "rct_key64");
|
||||
@@ -950,6 +903,7 @@ VARIANT_TAG(json_archive, rct::Bulletproof, "rct_bulletproof");
|
||||
VARIANT_TAG(json_archive, rct::multisig_kLRki, "rct_multisig_kLR");
|
||||
VARIANT_TAG(json_archive, rct::multisig_out, "rct_multisig_out");
|
||||
VARIANT_TAG(json_archive, rct::clsag, "rct_clsag");
|
||||
VARIANT_TAG(json_archive, rct::tclsag, "rct_tclsag");
|
||||
VARIANT_TAG(json_archive, rct::BulletproofPlus, "rct_bulletproof_plus");
|
||||
VARIANT_TAG(json_archive, rct::zk_proof, "rct_zk_proof");
|
||||
VARIANT_TAG(json_archive, rct::salvium_input_data_t, "rct_salvium_input_data");
|
||||
|
||||
@@ -1220,6 +1220,7 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig&
|
||||
INSERT_INTO_JSON_OBJECT(dest, bulletproofs_plus, sig.p.bulletproofs_plus);
|
||||
INSERT_INTO_JSON_OBJECT(dest, mlsags, sig.p.MGs);
|
||||
INSERT_INTO_JSON_OBJECT(dest, clsags, sig.p.CLSAGs);
|
||||
INSERT_INTO_JSON_OBJECT(dest, tclsags, sig.p.TCLSAGs);
|
||||
INSERT_INTO_JSON_OBJECT(dest, pseudo_outs, sig.get_pseudo_outs());
|
||||
|
||||
dest.EndObject();
|
||||
@@ -1263,6 +1264,7 @@ void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig)
|
||||
GET_FROM_JSON_OBJECT(prunable->value, sig.p.bulletproofs_plus, bulletproofs_plus);
|
||||
GET_FROM_JSON_OBJECT(prunable->value, sig.p.MGs, mlsags);
|
||||
GET_FROM_JSON_OBJECT(prunable->value, sig.p.CLSAGs, clsags);
|
||||
GET_FROM_JSON_OBJECT(prunable->value, sig.p.TCLSAGs, tclsags);
|
||||
GET_FROM_JSON_OBJECT(prunable->value, pseudo_outs, pseudo_outs);
|
||||
|
||||
sig.get_pseudo_outs() = std::move(pseudo_outs);
|
||||
@@ -1274,6 +1276,7 @@ void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig)
|
||||
sig.p.bulletproofs_plus.clear();
|
||||
sig.p.MGs.clear();
|
||||
sig.p.CLSAGs.clear();
|
||||
sig.p.TCLSAGs.clear();
|
||||
sig.get_pseudo_outs().clear();
|
||||
}
|
||||
}
|
||||
@@ -1505,6 +1508,31 @@ void fromJsonValue(const rapidjson::Value& val, rct::clsag& sig)
|
||||
GET_FROM_JSON_OBJECT(val, sig.D, D);
|
||||
}
|
||||
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::tclsag& sig)
|
||||
{
|
||||
dest.StartObject();
|
||||
|
||||
INSERT_INTO_JSON_OBJECT(dest, sx, sig.sx);
|
||||
INSERT_INTO_JSON_OBJECT(dest, sy, sig.sy);
|
||||
INSERT_INTO_JSON_OBJECT(dest, c1, sig.c1);
|
||||
INSERT_INTO_JSON_OBJECT(dest, D, sig.D);
|
||||
|
||||
dest.EndObject();
|
||||
}
|
||||
|
||||
void fromJsonValue(const rapidjson::Value& val, rct::tclsag& sig)
|
||||
{
|
||||
if (!val.IsObject())
|
||||
{
|
||||
throw WRONG_TYPE("key64 (rct::key[64])");
|
||||
}
|
||||
|
||||
GET_FROM_JSON_OBJECT(val, sig.sx, sx);
|
||||
GET_FROM_JSON_OBJECT(val, sig.sy, sy);
|
||||
GET_FROM_JSON_OBJECT(val, sig.c1, c1);
|
||||
GET_FROM_JSON_OBJECT(val, sig.D, D);
|
||||
}
|
||||
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::zk_proof& proof)
|
||||
{
|
||||
dest.StartObject();
|
||||
@@ -1567,7 +1595,7 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::salvium_
|
||||
INSERT_INTO_JSON_OBJECT(dest, salvium_data_type, salvium_data.salvium_data_type);
|
||||
INSERT_INTO_JSON_OBJECT(dest, pr_proof, salvium_data.pr_proof);
|
||||
INSERT_INTO_JSON_OBJECT(dest, sa_proof, salvium_data.sa_proof);
|
||||
if (salvium_data.salvium_data_type == rct::SalviumAudit) {
|
||||
if (salvium_data.salvium_data_type == rct::SalviumZeroAudit) {
|
||||
INSERT_INTO_JSON_OBJECT(dest, cz_proof, salvium_data.cz_proof);
|
||||
INSERT_INTO_JSON_OBJECT(dest, input_verification_data, salvium_data.input_verification_data);
|
||||
INSERT_INTO_JSON_OBJECT(dest, spend_pubkey, salvium_data.spend_pubkey);
|
||||
@@ -1587,7 +1615,7 @@ void fromJsonValue(const rapidjson::Value& val, rct::salvium_data_t& salvium_dat
|
||||
GET_FROM_JSON_OBJECT(val, salvium_data.salvium_data_type, salvium_data_type);
|
||||
GET_FROM_JSON_OBJECT(val, salvium_data.pr_proof, pr_proof);
|
||||
GET_FROM_JSON_OBJECT(val, salvium_data.sa_proof, sa_proof);
|
||||
if (salvium_data.salvium_data_type == rct::SalviumAudit) {
|
||||
if (salvium_data.salvium_data_type == rct::SalviumZeroAudit) {
|
||||
GET_FROM_JSON_OBJECT(val, salvium_data.cz_proof, cz_proof);
|
||||
GET_FROM_JSON_OBJECT(val, salvium_data.input_verification_data, input_verification_data);
|
||||
GET_FROM_JSON_OBJECT(val, salvium_data.spend_pubkey, spend_pubkey);
|
||||
|
||||
@@ -310,6 +310,9 @@ void fromJsonValue(const rapidjson::Value& val, rct::mgSig& sig);
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::clsag& sig);
|
||||
void fromJsonValue(const rapidjson::Value& val, rct::clsag& sig);
|
||||
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::tclsag& sig);
|
||||
void fromJsonValue(const rapidjson::Value& val, rct::tclsag& sig);
|
||||
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::zk_proof& p);
|
||||
void fromJsonValue(const rapidjson::Value& val, rct::zk_proof& p);
|
||||
|
||||
|
||||
@@ -969,7 +969,7 @@ cryptonote::transaction finalize_all_proofs_from_transfer_details(
|
||||
crypto::hash tx_prefix_hash;
|
||||
get_transaction_prefix_hash(tx, tx_prefix_hash, hwdev);
|
||||
rct::ctkeyV outSk;
|
||||
tx.rct_signatures = rct::genRctSimple(
|
||||
tx.rct_signatures = rct::genRctSimpleCarrot(
|
||||
rct::hash2rct(tx_prefix_hash),
|
||||
inSk,
|
||||
destinations,
|
||||
@@ -986,6 +986,7 @@ cryptonote::transaction finalize_all_proofs_from_transfer_details(
|
||||
hwdev,
|
||||
salvium_data,
|
||||
rct::sk2rct(x_change),
|
||||
rct::sk2rct(y_change),
|
||||
change_index,
|
||||
key_yF
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user