diff --git a/src/cryptonote_basic/cryptonote_boost_serialization.h b/src/cryptonote_basic/cryptonote_boost_serialization.h index 3a894841c..bcbb4c7ff 100644 --- a/src/cryptonote_basic/cryptonote_boost_serialization.h +++ b/src/cryptonote_basic/cryptonote_boost_serialization.h @@ -423,7 +423,7 @@ namespace boost a & x.p_r; if (x.type == rct::RCTTypeFullProofs) { a & x.pr_proof; - a & x.sa_proofs; + a & x.sa_proof; } } @@ -462,7 +462,7 @@ namespace boost a & x.p_r; if (x.type == rct::RCTTypeFullProofs) { a & x.pr_proof; - a & x.sa_proofs; + a & x.sa_proof; } //-------------- a & x.p.rangeSigs; diff --git a/src/multisig/multisig_tx_builder_ringct.cpp b/src/multisig/multisig_tx_builder_ringct.cpp index 7c07cb465..5b48a83e1 100644 --- a/src/multisig/multisig_tx_builder_ringct.cpp +++ b/src/multisig/multisig_tx_builder_ringct.cpp @@ -926,7 +926,7 @@ static bool set_tx_rct_signatures( else { rv.p.pseudoOuts = unsigned_tx.rct_signatures.p.pseudoOuts; rv.pr_proof = unsigned_tx.rct_signatures.pr_proof; // should verify this during reconstruction - //rv.sa_proofs = unsigned_tx.rct_signatures.sa_proofs; // should verify this during reconstruction + rv.sa_proof = unsigned_tx.rct_signatures.sa_proof; // should verify this during reconstruction rv.p_r = unsigned_tx.rct_signatures.p_r; if (num_sources != rv.p.pseudoOuts.size()) return false; diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index 058d7db8a..3d6112e54 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -1098,90 +1098,58 @@ namespace rct { return index; } - std::vector SAProof_Gen(const keyV &pubkeys, const key &x_change, const size_t change_index, const key &key_yF) { + zk_proof SAProof_Gen(const key &P, const key &x_change, const key &key_yF) { // Declare a return structure - std::vector proofs{}; + zk_proof proof{}; + proof.z2 = rct::zero(); // Sanity checks - CHECK_AND_ASSERT_THROW_MES(pubkeys.size(), "SAProof_Gen() failed - no output pubkeys provided"); - CHECK_AND_ASSERT_THROW_MES(pubkeys.size() > change_index, "SAProof_Gen() failed - invalid change_index provided"); + 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"); - // Iterate over the outputs - rct::keyV scalars; - rct::keyV commitments; - for (size_t j=0; j &proofs, const keyV &pubkeys, const size_t change_index, const key &key_yF) { + bool SAProof_Ver(const zk_proof &proof, const key &P, const key &key_yF) { + // Sanity checks - CHECK_AND_ASSERT_THROW_MES(proofs.size() == pubkeys.size(), "PRProof_Ver() failed - proof count does not match output count"); - CHECK_AND_ASSERT_THROW_MES(change_index < pubkeys.size(), "PRProof_Ver() failed - invalid change index provided"); + CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(P, rct::zero()), "SAProof_Gen() failed - invalid public key provided"); + CHECK_AND_ASSERT_THROW_MES(!rct::equalKeys(key_yF, rct::zero()), "SAProof_Gen() failed - invalid shared secret key provided"); // Recompute the challenge hash keyV challenge_keys; - challenge_keys.reserve(pubkeys.size() * 2 + 1); - for (const auto &proof_entr: proofs) { - challenge_keys.push_back(proof_entr.R); - } - challenge_keys.insert(challenge_keys.end(), pubkeys.begin(), pubkeys.end()); + challenge_keys.reserve(3); + challenge_keys.push_back(proof.R); + challenge_keys.push_back(P); challenge_keys.push_back(key_yF); rct::key c = rct::hash_to_scalar(challenge_keys); sc_reduce32(c.bytes); - // Extract the proof for the change output - we don't care about the others because they're dummy proofs - const auto &proof = proofs[change_index]; - const rct::key &R = proof.R; // Commitment - const rct::key &z_x = proof.z1; // z_x value - const rct::key P = pubkeys[change_index]; - - // Verify the proof for the change output // Recalculate the expected commitment using the formula: z_x * G = R + c * P - rct::key expected_commitment = rct::addKeys(R, rct::scalarmultKey(P, c)); + 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(z_x), expected_commitment)) { + if (!rct::equalKeys(rct::scalarmultBase(proof.z1), expected_commitment)) { return false; // Verification failed } @@ -1446,16 +1414,19 @@ namespace rct { sc_sub(difference.bytes, sumpouts.bytes, sumout.bytes); genC(rv.p_r, difference, 0); DP(rv.p_r); - if (rv.type == RCTTypeFullProofs) + if (rv.type == RCTTypeFullProofs) { rv.pr_proof = PRProof_Gen(difference); +#ifdef DBG + CHECK_AND_ASSERT_THROW_MES(PRProof_Ver(rv.p_r, rv.pr_proof), "PRProof_Ver() failed on recently created proof"); +#endif + } // Check if spend authority proof is needed (only for TRANSFER TXs) - rv.sa_proofs.clear(); if (tx_type == cryptonote::transaction_type::TRANSFER && rv.type == rct::RCTTypeFullProofs) { - rv.sa_proofs = SAProof_Gen(destinations, x_change, change_index, key_yF); - //#ifdef DBG - CHECK_AND_ASSERT_THROW_MES(SAProof_Ver(rv.sa_proofs, destinations, change_index, key_yF), "SAProof_Ver() failed on recently created proof"); - //#endif + rv.sa_proof = SAProof_Gen(destinations[change_index], x_change, key_yF); +#ifdef DBG + CHECK_AND_ASSERT_THROW_MES(SAProof_Ver(rv.sa_proof, destinations[change_index], key_yF), "SAProof_Ver() failed on recently created proof"); +#endif } key full_message = get_pre_mlsag_hash(rv,hwdev); diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index 0c6a88b1a..037be68ac 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -88,8 +88,8 @@ namespace rct { zk_proof PRProof_Gen(const rct::key &difference); bool PRProof_Ver(const rct::key &C, const zk_proof &proof); - std::vector SAProof_Gen(const keyV &pubkeys, const key &x_change, const size_t change_index, const key &key_yF); - bool SAProof_Ver(const std::vector &proofs, const keyV &pubkeys, const size_t change_index, const key &key_yF); + zk_proof SAProof_Gen(const keyV &P, const key &x_change, const key &key_yF); + bool SAProof_Ver(const zk_proof &proof, const key &P, const key &key_yF); //proveRange and verRange //proveRange gives C, and mask such that \sumCi = C diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index 2b1002f76..692b84d36 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -340,10 +340,10 @@ namespace rct { xmr_amount txnFee; // contains b key p_r; zk_proof pr_proof; // p_r - std::vector sa_proofs; // spend authority proofs + zk_proof sa_proof; // spend authority proof rctSigBase() : - type(RCTTypeNull), message{}, mixRing{}, pseudoOuts{}, ecdhInfo{}, outPk{}, txnFee(0), p_r{}, pr_proof{}, sa_proofs{} + type(RCTTypeNull), message{}, mixRing{}, pseudoOuts{}, ecdhInfo{}, outPk{}, txnFee(0), p_r{}, pr_proof{}, sa_proof{} {} template class Archive> @@ -421,23 +421,7 @@ namespace rct { if (type == RCTTypeFullProofs) { FIELD(pr_proof) - FIELD(sa_proofs) - /* - uint32_t nsap = sa_proofs.size(); - VARINT_FIELD(nsap) - ar.tag("sa_proofs"); - ar.begin_array(); - if (nsap > outputs) - return false; - PREPARE_CUSTOM_VECTOR_SERIALIZATION(nsap, sa_proofs); - for (size_t i = 0; i < nsap; ++i) - { - FIELDS(sa_proofs[i]) - if (nsap - i > 1) - ar.delimit_array(); - } - ar.end_array(); - */ + FIELD(sa_proof) } return ar.good(); } @@ -453,7 +437,7 @@ namespace rct { FIELD(p_r) if (type == RCTTypeFullProofs) { FIELD(pr_proof) - FIELD(sa_proofs) + FIELD(sa_proof) } END_SERIALIZE() }; diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp index 5bce34ac5..6b2ab1230 100644 --- a/src/serialization/json_object.cpp +++ b/src/serialization/json_object.cpp @@ -1175,7 +1175,7 @@ void toJsonValue(rapidjson::Writer& dest, const rct::rctSig& INSERT_INTO_JSON_OBJECT(dest, p_r, sig.p_r); if (sig.type == rct::RCTTypeFullProofs) { INSERT_INTO_JSON_OBJECT(dest, pr_proof, sig.pr_proof); - INSERT_INTO_JSON_OBJECT(dest, sa_proofs, sig.sa_proofs); + INSERT_INTO_JSON_OBJECT(dest, sa_proof, sig.sa_proof); } } @@ -1216,7 +1216,7 @@ void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig) GET_FROM_JSON_OBJECT(val, sig.p_r, p_r); if (sig.type == rct::RCTTypeFullProofs) { GET_FROM_JSON_OBJECT(val, sig.pr_proof, pr_proof); - GET_FROM_JSON_OBJECT(val, sig.sa_proofs, sa_proofs); + GET_FROM_JSON_OBJECT(val, sig.sa_proof, sa_proof); } }