updated RCT functions to support SalviumOne and T-CLSAG use

This commit is contained in:
Some Random Crypto Guy
2025-06-04 13:05:20 +01:00
parent c8314f7b56
commit 7fe9ee0990
10 changed files with 487 additions and 277 deletions
@@ -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)
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+15
View File
@@ -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
View File
@@ -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");
+30 -2
View File
@@ -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);
+3
View File
@@ -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);
+2 -1
View File
@@ -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
);