rct: rework v2 txes into prunable and non prunable data
Nothing is pruned, but this allows easier changes later.
This commit is contained in:
parent
d93746b6d3
commit
93f5c625f0
8 changed files with 154 additions and 91 deletions
|
@ -2279,17 +2279,18 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
|
||||||
// II
|
// II
|
||||||
if (rv.type == rct::RCTTypeFull)
|
if (rv.type == rct::RCTTypeFull)
|
||||||
{
|
{
|
||||||
rv.MG.II.resize(tx.vin.size());
|
rv.p.MGs.resize(1);
|
||||||
|
rv.p.MGs[0].II.resize(tx.vin.size());
|
||||||
for (size_t n = 0; n < tx.vin.size(); ++n)
|
for (size_t n = 0; n < tx.vin.size(); ++n)
|
||||||
rv.MG.II[n] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
|
rv.p.MGs[0].II[n] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
|
||||||
}
|
}
|
||||||
else if (rv.type == rct::RCTTypeSimple)
|
else if (rv.type == rct::RCTTypeSimple)
|
||||||
{
|
{
|
||||||
CHECK_AND_ASSERT_MES(rv.MGs.size() == tx.vin.size(), false, "Bad MGs size");
|
CHECK_AND_ASSERT_MES(rv.p.MGs.size() == tx.vin.size(), false, "Bad MGs size");
|
||||||
for (size_t n = 0; n < tx.vin.size(); ++n)
|
for (size_t n = 0; n < tx.vin.size(); ++n)
|
||||||
{
|
{
|
||||||
rv.MGs[n].II.resize(1);
|
rv.p.MGs[n].II.resize(1);
|
||||||
rv.MGs[n].II[0] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
|
rv.p.MGs[n].II[0] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2577,14 +2578,14 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rv.MGs.size() != tx.vin.size())
|
if (rv.p.MGs.size() != tx.vin.size())
|
||||||
{
|
{
|
||||||
LOG_PRINT_L1("Failed to check ringct signatures: mismatched MGs/vin sizes");
|
LOG_PRINT_L1("Failed to check ringct signatures: mismatched MGs/vin sizes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (size_t n = 0; n < tx.vin.size(); ++n)
|
for (size_t n = 0; n < tx.vin.size(); ++n)
|
||||||
{
|
{
|
||||||
if (memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.MGs[n].II[0], 32))
|
if (memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.MGs[n].II[0], 32))
|
||||||
{
|
{
|
||||||
LOG_PRINT_L1("Failed to check ringct signatures: mismatched key image");
|
LOG_PRINT_L1("Failed to check ringct signatures: mismatched key image");
|
||||||
return false;
|
return false;
|
||||||
|
@ -2630,14 +2631,19 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rv.MG.II.size() != tx.vin.size())
|
if (rv.p.MGs.size() != 1)
|
||||||
|
{
|
||||||
|
LOG_PRINT_L1("Failed to check ringct signatures: Bad MGs size");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rv.p.MGs[0].II.size() != tx.vin.size())
|
||||||
{
|
{
|
||||||
LOG_PRINT_L1("Failed to check ringct signatures: mismatched II/vin sizes");
|
LOG_PRINT_L1("Failed to check ringct signatures: mismatched II/vin sizes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (size_t n = 0; n < tx.vin.size(); ++n)
|
for (size_t n = 0; n < tx.vin.size(); ++n)
|
||||||
{
|
{
|
||||||
if (memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.MG.II[n], 32))
|
if (memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.MGs[0].II[n], 32))
|
||||||
{
|
{
|
||||||
LOG_PRINT_L1("Failed to check ringct signatures: mismatched II/vin sizes");
|
LOG_PRINT_L1("Failed to check ringct signatures: mismatched II/vin sizes");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -246,17 +246,12 @@ namespace boost
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
inline void serialize(Archive &a, rct::rctSig &x, const boost::serialization::version_type ver)
|
inline void serialize(Archive &a, rct::rctSigBase &x, const boost::serialization::version_type ver)
|
||||||
{
|
{
|
||||||
a & x.type;
|
a & x.type;
|
||||||
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple)
|
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple)
|
||||||
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
|
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
|
||||||
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
|
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
|
||||||
a & x.rangeSigs;
|
|
||||||
if (x.type == rct::RCTTypeSimple)
|
|
||||||
a & x.MGs;
|
|
||||||
if (x.type == rct::RCTTypeFull)
|
|
||||||
a & x.MG;
|
|
||||||
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
|
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
|
||||||
if (x.type == rct::RCTTypeSimple)
|
if (x.type == rct::RCTTypeSimple)
|
||||||
a & x.pseudoOuts;
|
a & x.pseudoOuts;
|
||||||
|
@ -264,6 +259,24 @@ namespace boost
|
||||||
serializeOutPk(a, x.outPk, ver);
|
serializeOutPk(a, x.outPk, ver);
|
||||||
a & x.txnFee;
|
a & x.txnFee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
inline void serialize(Archive &a, rct::rctSig &x, const boost::serialization::version_type ver)
|
||||||
|
{
|
||||||
|
a & x.type;
|
||||||
|
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple)
|
||||||
|
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
|
||||||
|
if (x.type == rct::RCTTypeSimple)
|
||||||
|
a & x.pseudoOuts;
|
||||||
|
a & x.ecdhInfo;
|
||||||
|
serializeOutPk(a, x.outPk, ver);
|
||||||
|
a & x.txnFee;
|
||||||
|
//--------------
|
||||||
|
a & x.p.rangeSigs;
|
||||||
|
a & x.p.MGs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ namespace cryptonote
|
||||||
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
|
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
|
||||||
//TODO: validate tx
|
//TODO: validate tx
|
||||||
|
|
||||||
crypto::cn_fast_hash(tx_blob.data(), tx_blob.size(), tx_hash);
|
get_transaction_hash(tx, tx_hash);
|
||||||
get_transaction_prefix_hash(tx, tx_prefix_hash);
|
get_transaction_prefix_hash(tx, tx_prefix_hash);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -905,20 +905,49 @@ namespace cryptonote
|
||||||
crypto::hash get_transaction_hash(const transaction& t)
|
crypto::hash get_transaction_hash(const transaction& t)
|
||||||
{
|
{
|
||||||
crypto::hash h = null_hash;
|
crypto::hash h = null_hash;
|
||||||
size_t blob_size = 0;
|
get_transaction_hash(t, h, NULL);
|
||||||
get_object_hash(t, h, blob_size);
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
bool get_transaction_hash(const transaction& t, crypto::hash& res)
|
bool get_transaction_hash(const transaction& t, crypto::hash& res)
|
||||||
{
|
{
|
||||||
size_t blob_size = 0;
|
return get_transaction_hash(t, res, NULL);
|
||||||
return get_object_hash(t, res, blob_size);
|
}
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size)
|
||||||
|
{
|
||||||
|
// v1 transactions hash the entire blob
|
||||||
|
if (t.version == 1)
|
||||||
|
{
|
||||||
|
size_t ignored_blob_size, &blob_size_ref = blob_size ? *blob_size : ignored_blob_size;
|
||||||
|
return get_object_hash(t, res, blob_size_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
// v2 transactions hash different parts together, than hash the set of those hashes
|
||||||
|
crypto::hash hashes[3];
|
||||||
|
|
||||||
|
// prefix
|
||||||
|
get_transaction_prefix_hash(t, hashes[0]);
|
||||||
|
|
||||||
|
// base rct data
|
||||||
|
get_blob_hash(t_serializable_object_to_blob((const rct::rctSigBase&)t.rct_signatures), hashes[1]);
|
||||||
|
|
||||||
|
// prunable rct data
|
||||||
|
get_blob_hash(t_serializable_object_to_blob(t.rct_signatures.p), hashes[2]);
|
||||||
|
|
||||||
|
// the tx hash is the hash of the 3 hashes
|
||||||
|
res = cn_fast_hash(hashes, sizeof(hashes));
|
||||||
|
|
||||||
|
// we still need the size
|
||||||
|
if (blob_size)
|
||||||
|
*blob_size = get_object_blobsize(t);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size)
|
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size)
|
||||||
{
|
{
|
||||||
return get_object_hash(t, res, blob_size);
|
return get_transaction_hash(t, res, &blob_size);
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
blobdata get_block_hashing_blob(const block& b)
|
blobdata get_block_hashing_blob(const block& b)
|
||||||
|
|
|
@ -111,6 +111,7 @@ namespace cryptonote
|
||||||
crypto::hash get_transaction_hash(const transaction& t);
|
crypto::hash get_transaction_hash(const transaction& t);
|
||||||
bool get_transaction_hash(const transaction& t, crypto::hash& res);
|
bool get_transaction_hash(const transaction& t, crypto::hash& res);
|
||||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size);
|
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size);
|
||||||
|
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size);
|
||||||
blobdata get_block_hashing_blob(const block& b);
|
blobdata get_block_hashing_blob(const block& b);
|
||||||
bool get_block_hash(const block& b, crypto::hash& res);
|
bool get_block_hash(const block& b, crypto::hash& res);
|
||||||
crypto::hash get_block_hash(const block& b);
|
crypto::hash get_block_hash(const block& b);
|
||||||
|
|
|
@ -346,7 +346,7 @@ namespace rct {
|
||||||
keyV kv;
|
keyV kv;
|
||||||
kv.push_back(d2h(rv.type));
|
kv.push_back(d2h(rv.type));
|
||||||
kv.push_back(rv.message);
|
kv.push_back(rv.message);
|
||||||
for (auto r: rv.rangeSigs)
|
for (auto r: rv.p.rangeSigs)
|
||||||
{
|
{
|
||||||
for (size_t n = 0; n < 64; ++n)
|
for (size_t n = 0; n < 64; ++n)
|
||||||
kv.push_back(r.asig.L1[n]);
|
kv.push_back(r.asig.L1[n]);
|
||||||
|
@ -593,8 +593,9 @@ namespace rct {
|
||||||
|
|
||||||
rctSig rv;
|
rctSig rv;
|
||||||
rv.type = RCTTypeFull;
|
rv.type = RCTTypeFull;
|
||||||
|
rv.message = message;
|
||||||
rv.outPk.resize(destinations.size());
|
rv.outPk.resize(destinations.size());
|
||||||
rv.rangeSigs.resize(destinations.size());
|
rv.p.rangeSigs.resize(destinations.size());
|
||||||
rv.ecdhInfo.resize(destinations.size());
|
rv.ecdhInfo.resize(destinations.size());
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
@ -604,9 +605,9 @@ namespace rct {
|
||||||
//add destination to sig
|
//add destination to sig
|
||||||
rv.outPk[i].dest = copy(destinations[i]);
|
rv.outPk[i].dest = copy(destinations[i]);
|
||||||
//compute range proof
|
//compute range proof
|
||||||
rv.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, amounts[i]);
|
rv.p.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, amounts[i]);
|
||||||
#ifdef DBG
|
#ifdef DBG
|
||||||
CHECK_AND_ASSERT_THROW_MES(verRange(rv.outPk[i].mask, rv.rangeSigs[i]), "verRange failed on newly created proof");
|
CHECK_AND_ASSERT_THROW_MES(verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]), "verRange failed on newly created proof");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//mask amount and mask
|
//mask amount and mask
|
||||||
|
@ -628,7 +629,7 @@ namespace rct {
|
||||||
key txnFeeKey = scalarmultH(d2h(rv.txnFee));
|
key txnFeeKey = scalarmultH(d2h(rv.txnFee));
|
||||||
|
|
||||||
rv.mixRing = mixRing;
|
rv.mixRing = mixRing;
|
||||||
rv.MG = proveRctMG(get_pre_mlsag_hash(rv), rv.mixRing, inSk, outSk, rv.outPk, index, txnFeeKey);
|
rv.p.MGs.push_back(proveRctMG(get_pre_mlsag_hash(rv), rv.mixRing, inSk, outSk, rv.outPk, index, txnFeeKey));
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,8 +655,9 @@ namespace rct {
|
||||||
|
|
||||||
rctSig rv;
|
rctSig rv;
|
||||||
rv.type = RCTTypeSimple;
|
rv.type = RCTTypeSimple;
|
||||||
|
rv.message = message;
|
||||||
rv.outPk.resize(destinations.size());
|
rv.outPk.resize(destinations.size());
|
||||||
rv.rangeSigs.resize(destinations.size());
|
rv.p.rangeSigs.resize(destinations.size());
|
||||||
rv.ecdhInfo.resize(destinations.size());
|
rv.ecdhInfo.resize(destinations.size());
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@ -667,9 +669,9 @@ namespace rct {
|
||||||
//add destination to sig
|
//add destination to sig
|
||||||
rv.outPk[i].dest = copy(destinations[i]);
|
rv.outPk[i].dest = copy(destinations[i]);
|
||||||
//compute range proof
|
//compute range proof
|
||||||
rv.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, outamounts[i]);
|
rv.p.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, outamounts[i]);
|
||||||
#ifdef DBG
|
#ifdef DBG
|
||||||
verRange(rv.outPk[i].mask, rv.rangeSigs[i]);
|
verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sc_add(sumout.bytes, outSk[i].mask.bytes, sumout.bytes);
|
sc_add(sumout.bytes, outSk[i].mask.bytes, sumout.bytes);
|
||||||
|
@ -686,7 +688,7 @@ namespace rct {
|
||||||
// key txnFeeKey = scalarmultH(d2h(rv.txnFee));
|
// key txnFeeKey = scalarmultH(d2h(rv.txnFee));
|
||||||
rv.mixRing = mixRing;
|
rv.mixRing = mixRing;
|
||||||
rv.pseudoOuts.resize(inamounts.size());
|
rv.pseudoOuts.resize(inamounts.size());
|
||||||
rv.MGs.resize(inamounts.size());
|
rv.p.MGs.resize(inamounts.size());
|
||||||
key sumpouts = zero(); //sum pseudoOut masks
|
key sumpouts = zero(); //sum pseudoOut masks
|
||||||
keyV a(inamounts.size());
|
keyV a(inamounts.size());
|
||||||
for (i = 0 ; i < inamounts.size() - 1; i++) {
|
for (i = 0 ; i < inamounts.size() - 1; i++) {
|
||||||
|
@ -701,7 +703,7 @@ namespace rct {
|
||||||
|
|
||||||
key full_message = get_pre_mlsag_hash(rv);
|
key full_message = get_pre_mlsag_hash(rv);
|
||||||
for (i = 0 ; i < inamounts.size(); i++) {
|
for (i = 0 ; i < inamounts.size(); i++) {
|
||||||
rv.MGs[i] = proveRctMGSimple(full_message, rv.mixRing[i], inSk[i], a[i], rv.pseudoOuts[i], index[i]);
|
rv.p.MGs[i] = proveRctMGSimple(full_message, rv.mixRing[i], inSk[i], a[i], rv.pseudoOuts[i], index[i]);
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -731,8 +733,9 @@ namespace rct {
|
||||||
// must know the destination private key to find the correct amount, else will return a random number
|
// must know the destination private key to find the correct amount, else will return a random number
|
||||||
bool verRct(const rctSig & rv) {
|
bool verRct(const rctSig & rv) {
|
||||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "verRct called on non-full rctSig");
|
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "verRct called on non-full rctSig");
|
||||||
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.rangeSigs");
|
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.p.rangeSigs");
|
||||||
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo");
|
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo");
|
||||||
|
CHECK_AND_ASSERT_MES(rv.p.MGs.size() == 1, false, "full rctSig has not one MG");
|
||||||
|
|
||||||
// some rct ops can throw
|
// some rct ops can throw
|
||||||
try
|
try
|
||||||
|
@ -742,13 +745,13 @@ namespace rct {
|
||||||
bool tmp;
|
bool tmp;
|
||||||
DP("range proofs verified?");
|
DP("range proofs verified?");
|
||||||
for (i = 0; i < rv.outPk.size(); i++) {
|
for (i = 0; i < rv.outPk.size(); i++) {
|
||||||
tmp = verRange(rv.outPk[i].mask, rv.rangeSigs[i]);
|
tmp = verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]);
|
||||||
DP(tmp);
|
DP(tmp);
|
||||||
rvb = (rvb && tmp);
|
rvb = (rvb && tmp);
|
||||||
}
|
}
|
||||||
//compute txn fee
|
//compute txn fee
|
||||||
key txnFeeKey = scalarmultH(d2h(rv.txnFee));
|
key txnFeeKey = scalarmultH(d2h(rv.txnFee));
|
||||||
bool mgVerd = verRctMG(rv.MG, rv.mixRing, rv.outPk, txnFeeKey, get_pre_mlsag_hash(rv));
|
bool mgVerd = verRctMG(rv.p.MGs[0], rv.mixRing, rv.outPk, txnFeeKey, get_pre_mlsag_hash(rv));
|
||||||
DP("mg sig verified?");
|
DP("mg sig verified?");
|
||||||
DP(mgVerd);
|
DP(mgVerd);
|
||||||
|
|
||||||
|
@ -767,14 +770,14 @@ namespace rct {
|
||||||
bool rvb = true;
|
bool rvb = true;
|
||||||
|
|
||||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple, false, "verRctSimple called on non simple rctSig");
|
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple, false, "verRctSimple called on non simple rctSig");
|
||||||
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.rangeSigs");
|
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.p.rangeSigs");
|
||||||
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo");
|
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo");
|
||||||
CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.MGs.size(), false, "Mismatched sizes of rv.pseudoOuts and rv.MGs");
|
CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.p.MGs.size(), false, "Mismatched sizes of rv.pseudoOuts and rv.p.MGs");
|
||||||
CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.pseudoOuts and mixRing");
|
CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.pseudoOuts and mixRing");
|
||||||
|
|
||||||
key sumOutpks = identity();
|
key sumOutpks = identity();
|
||||||
for (i = 0; i < rv.outPk.size(); i++) {
|
for (i = 0; i < rv.outPk.size(); i++) {
|
||||||
if (!verRange(rv.outPk[i].mask, rv.rangeSigs[i])) {
|
if (!verRange(rv.outPk[i].mask, rv.p.rangeSigs[i])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
addKeys(sumOutpks, sumOutpks, rv.outPk[i].mask);
|
addKeys(sumOutpks, sumOutpks, rv.outPk[i].mask);
|
||||||
|
@ -787,7 +790,7 @@ namespace rct {
|
||||||
key message = get_pre_mlsag_hash(rv);
|
key message = get_pre_mlsag_hash(rv);
|
||||||
key sumPseudoOuts = identity();
|
key sumPseudoOuts = identity();
|
||||||
for (i = 0 ; i < rv.mixRing.size() ; i++) {
|
for (i = 0 ; i < rv.mixRing.size() ; i++) {
|
||||||
tmpb = verRctMGSimple(message, rv.MGs[i], rv.mixRing[i], rv.pseudoOuts[i]);
|
tmpb = verRctMGSimple(message, rv.p.MGs[i], rv.mixRing[i], rv.pseudoOuts[i]);
|
||||||
addKeys(sumPseudoOuts, sumPseudoOuts, rv.pseudoOuts[i]);
|
addKeys(sumPseudoOuts, sumPseudoOuts, rv.pseudoOuts[i]);
|
||||||
DP(tmpb);
|
DP(tmpb);
|
||||||
if (!tmpb) {
|
if (!tmpb) {
|
||||||
|
@ -820,8 +823,8 @@ namespace rct {
|
||||||
// must know the destination private key to find the correct amount, else will return a random number
|
// must know the destination private key to find the correct amount, else will return a random number
|
||||||
static xmr_amount decodeRctMain(const rctSig & rv, const key & sk, unsigned int i, key & mask, void (*decode)(ecdhTuple&, const key&)) {
|
static xmr_amount decodeRctMain(const rctSig & rv, const key & sk, unsigned int i, key & mask, void (*decode)(ecdhTuple&, const key&)) {
|
||||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "decodeRct called on non-full rctSig");
|
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "decodeRct called on non-full rctSig");
|
||||||
CHECK_AND_ASSERT_THROW_MES(rv.rangeSigs.size() > 0, "Empty rv.rangeSigs");
|
CHECK_AND_ASSERT_THROW_MES(rv.p.rangeSigs.size() > 0, "Empty rv.p.rangeSigs");
|
||||||
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.rangeSigs");
|
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.p.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.p.rangeSigs");
|
||||||
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
||||||
|
|
||||||
//mask amount and mask
|
//mask amount and mask
|
||||||
|
@ -857,8 +860,8 @@ namespace rct {
|
||||||
|
|
||||||
static xmr_amount decodeRctSimpleMain(const rctSig & rv, const key & sk, unsigned int i, key &mask, void (*decode)(ecdhTuple &ecdh, const key&)) {
|
static xmr_amount decodeRctSimpleMain(const rctSig & rv, const key & sk, unsigned int i, key &mask, void (*decode)(ecdhTuple &ecdh, const key&)) {
|
||||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple, false, "decodeRct called on non simple rctSig");
|
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple, false, "decodeRct called on non simple rctSig");
|
||||||
CHECK_AND_ASSERT_THROW_MES(rv.rangeSigs.size() > 0, "Empty rv.rangeSigs");
|
CHECK_AND_ASSERT_THROW_MES(rv.p.rangeSigs.size() > 0, "Empty rv.p.rangeSigs");
|
||||||
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.rangeSigs");
|
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.p.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.p.rangeSigs");
|
||||||
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
||||||
|
|
||||||
//mask amount and mask
|
//mask amount and mask
|
||||||
|
|
|
@ -177,12 +177,9 @@ namespace rct {
|
||||||
RCTTypeFull = 0,
|
RCTTypeFull = 0,
|
||||||
RCTTypeSimple = 1,
|
RCTTypeSimple = 1,
|
||||||
};
|
};
|
||||||
struct rctSig {
|
struct rctSigBase {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
key message;
|
key message;
|
||||||
vector<rangeSig> rangeSigs;
|
|
||||||
mgSig MG; // for non simple rct
|
|
||||||
vector<mgSig> MGs; // for simple rct
|
|
||||||
ctkeyM mixRing; //the set of all pubkeys / copy
|
ctkeyM mixRing; //the set of all pubkeys / copy
|
||||||
//pairs that you mix with
|
//pairs that you mix with
|
||||||
keyV pseudoOuts; //C - for simple rct
|
keyV pseudoOuts; //C - for simple rct
|
||||||
|
@ -190,14 +187,9 @@ namespace rct {
|
||||||
ctkeyV outPk;
|
ctkeyV outPk;
|
||||||
xmr_amount txnFee; // contains b
|
xmr_amount txnFee; // contains b
|
||||||
|
|
||||||
BEGIN_SERIALIZE_OBJECT()
|
BEGIN_SERIALIZE()
|
||||||
FIELD(type)
|
FIELD(type)
|
||||||
// FIELD(message) - not serialized, it can be reconstructed
|
// FIELD(message) - not serialized, it can be reconstructed
|
||||||
FIELD(rangeSigs)
|
|
||||||
if (type == RCTTypeSimple)
|
|
||||||
FIELD(MGs)
|
|
||||||
else
|
|
||||||
FIELD(MG)
|
|
||||||
// FIELD(mixRing) - not serialized, it can be reconstructed
|
// FIELD(mixRing) - not serialized, it can be reconstructed
|
||||||
if (type == RCTTypeSimple)
|
if (type == RCTTypeSimple)
|
||||||
FIELD(pseudoOuts)
|
FIELD(pseudoOuts)
|
||||||
|
@ -218,6 +210,23 @@ namespace rct {
|
||||||
FIELD(txnFee)
|
FIELD(txnFee)
|
||||||
END_SERIALIZE()
|
END_SERIALIZE()
|
||||||
};
|
};
|
||||||
|
struct rctSigPrunable {
|
||||||
|
vector<rangeSig> rangeSigs;
|
||||||
|
vector<mgSig> MGs; // simple rct has N, full has 1
|
||||||
|
|
||||||
|
BEGIN_SERIALIZE()
|
||||||
|
FIELD(rangeSigs)
|
||||||
|
FIELD(MGs)
|
||||||
|
END_SERIALIZE()
|
||||||
|
};
|
||||||
|
struct rctSig: public rctSigBase {
|
||||||
|
rctSigPrunable p;
|
||||||
|
|
||||||
|
BEGIN_SERIALIZE_OBJECT()
|
||||||
|
FIELDS(*static_cast<rctSigBase *>(this))
|
||||||
|
FIELDS(p);
|
||||||
|
END_SERIALIZE()
|
||||||
|
};
|
||||||
|
|
||||||
//other basepoint H = toPoint(cn_fast_hash(G)), G the basepoint
|
//other basepoint H = toPoint(cn_fast_hash(G)), G the basepoint
|
||||||
static const key H = { {0x8b, 0x65, 0x59, 0x70, 0x15, 0x37, 0x99, 0xaf, 0x2a, 0xea, 0xdc, 0x9f, 0xf1, 0xad, 0xd0, 0xea, 0x6c, 0x72, 0x51, 0xd5, 0x41, 0x54, 0xcf, 0xa9, 0x2c, 0x17, 0x3a, 0x0d, 0xd3, 0x9c, 0x1f, 0x94} };
|
static const key H = { {0x8b, 0x65, 0x59, 0x70, 0x15, 0x37, 0x99, 0xaf, 0x2a, 0xea, 0xdc, 0x9f, 0xf1, 0xad, 0xd0, 0xea, 0x6c, 0x72, 0x51, 0xd5, 0x41, 0x54, 0xcf, 0xa9, 0x2c, 0x17, 0x3a, 0x0d, 0xd3, 0x9c, 0x1f, 0x94} };
|
||||||
|
|
|
@ -985,18 +985,19 @@ TEST(ringct, rctSig_##name) \
|
||||||
ASSERT_FALSE(rct::verRct(sig)); \
|
ASSERT_FALSE(rct::verRct(sig)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_rctSig_elements(rangeSigs_empty, sig.rangeSigs.resize(0));
|
TEST_rctSig_elements(rangeSigs_empty, sig.p.rangeSigs.resize(0));
|
||||||
TEST_rctSig_elements(rangeSigs_too_many, sig.rangeSigs.push_back(sig.rangeSigs.back()));
|
TEST_rctSig_elements(rangeSigs_too_many, sig.p.rangeSigs.push_back(sig.p.rangeSigs.back()));
|
||||||
TEST_rctSig_elements(rangeSigs_too_few, sig.rangeSigs.pop_back());
|
TEST_rctSig_elements(rangeSigs_too_few, sig.p.rangeSigs.pop_back());
|
||||||
TEST_rctSig_elements(mgSig_ss_empty, sig.MG.ss.resize(0));
|
TEST_rctSig_elements(mgSig_MG_empty, sig.p.MGs.resize(0));
|
||||||
TEST_rctSig_elements(mgSig_ss_too_many, sig.MG.ss.push_back(sig.MG.ss.back()));
|
TEST_rctSig_elements(mgSig_ss_empty, sig.p.MGs[0].ss.resize(0));
|
||||||
TEST_rctSig_elements(mgSig_ss_too_few, sig.MG.ss.pop_back());
|
TEST_rctSig_elements(mgSig_ss_too_many, sig.p.MGs[0].ss.push_back(sig.p.MGs[0].ss.back()));
|
||||||
TEST_rctSig_elements(mgSig_ss0_empty, sig.MG.ss[0].resize(0));
|
TEST_rctSig_elements(mgSig_ss_too_few, sig.p.MGs[0].ss.pop_back());
|
||||||
TEST_rctSig_elements(mgSig_ss0_too_many, sig.MG.ss[0].push_back(sig.MG.ss[0].back()));
|
TEST_rctSig_elements(mgSig_ss0_empty, sig.p.MGs[0].ss[0].resize(0));
|
||||||
TEST_rctSig_elements(mgSig_ss0_too_few, sig.MG.ss[0].pop_back());
|
TEST_rctSig_elements(mgSig_ss0_too_many, sig.p.MGs[0].ss[0].push_back(sig.p.MGs[0].ss[0].back()));
|
||||||
TEST_rctSig_elements(mgSig_II_empty, sig.MG.II.resize(0));
|
TEST_rctSig_elements(mgSig_ss0_too_few, sig.p.MGs[0].ss[0].pop_back());
|
||||||
TEST_rctSig_elements(mgSig_II_too_many, sig.MG.II.push_back(sig.MG.II.back()));
|
TEST_rctSig_elements(mgSig_II_empty, sig.p.MGs[0].II.resize(0));
|
||||||
TEST_rctSig_elements(mgSig_II_too_few, sig.MG.II.pop_back());
|
TEST_rctSig_elements(mgSig_II_too_many, sig.p.MGs[0].II.push_back(sig.p.MGs[0].II.back()));
|
||||||
|
TEST_rctSig_elements(mgSig_II_too_few, sig.p.MGs[0].II.pop_back());
|
||||||
TEST_rctSig_elements(mixRing_empty, sig.mixRing.resize(0));
|
TEST_rctSig_elements(mixRing_empty, sig.mixRing.resize(0));
|
||||||
TEST_rctSig_elements(mixRing_too_many, sig.mixRing.push_back(sig.mixRing.back()));
|
TEST_rctSig_elements(mixRing_too_many, sig.mixRing.push_back(sig.mixRing.back()));
|
||||||
TEST_rctSig_elements(mixRing_too_few, sig.mixRing.pop_back());
|
TEST_rctSig_elements(mixRing_too_few, sig.mixRing.pop_back());
|
||||||
|
@ -1021,21 +1022,21 @@ TEST(ringct, rctSig_##name##_simple) \
|
||||||
ASSERT_FALSE(rct::verRctSimple(sig)); \
|
ASSERT_FALSE(rct::verRctSimple(sig)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_rctSig_elements_simple(rangeSigs_empty, sig.rangeSigs.resize(0));
|
TEST_rctSig_elements_simple(rangeSigs_empty, sig.p.rangeSigs.resize(0));
|
||||||
TEST_rctSig_elements_simple(rangeSigs_too_many, sig.rangeSigs.push_back(sig.rangeSigs.back()));
|
TEST_rctSig_elements_simple(rangeSigs_too_many, sig.p.rangeSigs.push_back(sig.p.rangeSigs.back()));
|
||||||
TEST_rctSig_elements_simple(rangeSigs_too_few, sig.rangeSigs.pop_back());
|
TEST_rctSig_elements_simple(rangeSigs_too_few, sig.p.rangeSigs.pop_back());
|
||||||
TEST_rctSig_elements_simple(mgSig_empty, sig.MGs.resize(0));
|
TEST_rctSig_elements_simple(mgSig_empty, sig.p.MGs.resize(0));
|
||||||
TEST_rctSig_elements_simple(mgSig_too_many, sig.MGs.push_back(sig.MGs.back()));
|
TEST_rctSig_elements_simple(mgSig_too_many, sig.p.MGs.push_back(sig.p.MGs.back()));
|
||||||
TEST_rctSig_elements_simple(mgSig_too_few, sig.MGs.pop_back());
|
TEST_rctSig_elements_simple(mgSig_too_few, sig.p.MGs.pop_back());
|
||||||
TEST_rctSig_elements_simple(mgSig0_ss_empty, sig.MGs[0].ss.resize(0));
|
TEST_rctSig_elements_simple(mgSig0_ss_empty, sig.p.MGs[0].ss.resize(0));
|
||||||
TEST_rctSig_elements_simple(mgSig0_ss_too_many, sig.MGs[0].ss.push_back(sig.MGs[0].ss.back()));
|
TEST_rctSig_elements_simple(mgSig0_ss_too_many, sig.p.MGs[0].ss.push_back(sig.p.MGs[0].ss.back()));
|
||||||
TEST_rctSig_elements_simple(mgSig0_ss_too_few, sig.MGs[0].ss.pop_back());
|
TEST_rctSig_elements_simple(mgSig0_ss_too_few, sig.p.MGs[0].ss.pop_back());
|
||||||
TEST_rctSig_elements_simple(mgSig_ss0_empty, sig.MGs[0].ss[0].resize(0));
|
TEST_rctSig_elements_simple(mgSig_ss0_empty, sig.p.MGs[0].ss[0].resize(0));
|
||||||
TEST_rctSig_elements_simple(mgSig_ss0_too_many, sig.MGs[0].ss[0].push_back(sig.MGs[0].ss[0].back()));
|
TEST_rctSig_elements_simple(mgSig_ss0_too_many, sig.p.MGs[0].ss[0].push_back(sig.p.MGs[0].ss[0].back()));
|
||||||
TEST_rctSig_elements_simple(mgSig_ss0_too_few, sig.MGs[0].ss[0].pop_back());
|
TEST_rctSig_elements_simple(mgSig_ss0_too_few, sig.p.MGs[0].ss[0].pop_back());
|
||||||
TEST_rctSig_elements_simple(mgSig0_II_empty, sig.MGs[0].II.resize(0));
|
TEST_rctSig_elements_simple(mgSig0_II_empty, sig.p.MGs[0].II.resize(0));
|
||||||
TEST_rctSig_elements_simple(mgSig0_II_too_many, sig.MGs[0].II.push_back(sig.MGs[0].II.back()));
|
TEST_rctSig_elements_simple(mgSig0_II_too_many, sig.p.MGs[0].II.push_back(sig.p.MGs[0].II.back()));
|
||||||
TEST_rctSig_elements_simple(mgSig0_II_too_few, sig.MGs[0].II.pop_back());
|
TEST_rctSig_elements_simple(mgSig0_II_too_few, sig.p.MGs[0].II.pop_back());
|
||||||
TEST_rctSig_elements_simple(mixRing_empty, sig.mixRing.resize(0));
|
TEST_rctSig_elements_simple(mixRing_empty, sig.mixRing.resize(0));
|
||||||
TEST_rctSig_elements_simple(mixRing_too_many, sig.mixRing.push_back(sig.mixRing.back()));
|
TEST_rctSig_elements_simple(mixRing_too_many, sig.mixRing.push_back(sig.mixRing.back()));
|
||||||
TEST_rctSig_elements_simple(mixRing_too_few, sig.mixRing.pop_back());
|
TEST_rctSig_elements_simple(mixRing_too_few, sig.mixRing.pop_back());
|
||||||
|
|
|
@ -571,7 +571,7 @@ TEST(Serialization, serializes_ringct_types)
|
||||||
//compute rct data with mixin 500
|
//compute rct data with mixin 500
|
||||||
s0 = rct::genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, 3);
|
s0 = rct::genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, 3);
|
||||||
|
|
||||||
mg0 = s0.MG;
|
mg0 = s0.p.MGs[0];
|
||||||
ASSERT_TRUE(serialization::dump_binary(mg0, blob));
|
ASSERT_TRUE(serialization::dump_binary(mg0, blob));
|
||||||
ASSERT_TRUE(serialization::parse_binary(blob, mg1));
|
ASSERT_TRUE(serialization::parse_binary(blob, mg1));
|
||||||
ASSERT_TRUE(mg0.ss.size() == mg1.ss.size());
|
ASSERT_TRUE(mg0.ss.size() == mg1.ss.size());
|
||||||
|
@ -584,7 +584,7 @@ TEST(Serialization, serializes_ringct_types)
|
||||||
// mixRing and II are not serialized, they are meant to be reconstructed
|
// mixRing and II are not serialized, they are meant to be reconstructed
|
||||||
ASSERT_TRUE(mg1.II.empty());
|
ASSERT_TRUE(mg1.II.empty());
|
||||||
|
|
||||||
rg0 = s0.rangeSigs.front();
|
rg0 = s0.p.rangeSigs.front();
|
||||||
ASSERT_TRUE(serialization::dump_binary(rg0, blob));
|
ASSERT_TRUE(serialization::dump_binary(rg0, blob));
|
||||||
ASSERT_TRUE(serialization::parse_binary(blob, rg1));
|
ASSERT_TRUE(serialization::parse_binary(blob, rg1));
|
||||||
ASSERT_TRUE(!memcmp(&rg0, &rg1, sizeof(rg0)));
|
ASSERT_TRUE(!memcmp(&rg0, &rg1, sizeof(rg0)));
|
||||||
|
@ -592,19 +592,20 @@ TEST(Serialization, serializes_ringct_types)
|
||||||
ASSERT_TRUE(serialization::dump_binary(s0, blob));
|
ASSERT_TRUE(serialization::dump_binary(s0, blob));
|
||||||
ASSERT_TRUE(serialization::parse_binary(blob, s1));
|
ASSERT_TRUE(serialization::parse_binary(blob, s1));
|
||||||
ASSERT_TRUE(s0.type == s1.type);
|
ASSERT_TRUE(s0.type == s1.type);
|
||||||
ASSERT_TRUE(s0.rangeSigs.size() == s1.rangeSigs.size());
|
ASSERT_TRUE(s0.p.rangeSigs.size() == s1.p.rangeSigs.size());
|
||||||
for (size_t n = 0; n < s0.rangeSigs.size(); ++n)
|
for (size_t n = 0; n < s0.p.rangeSigs.size(); ++n)
|
||||||
{
|
{
|
||||||
ASSERT_TRUE(!memcmp(&s0.rangeSigs[n], &s1.rangeSigs[n], sizeof(s0.rangeSigs[n])));
|
ASSERT_TRUE(!memcmp(&s0.p.rangeSigs[n], &s1.p.rangeSigs[n], sizeof(s0.p.rangeSigs[n])));
|
||||||
}
|
}
|
||||||
ASSERT_TRUE(s0.MG.ss.size() == s1.MG.ss.size());
|
ASSERT_TRUE(s0.p.MGs.size() == s1.p.MGs.size());
|
||||||
for (size_t n = 0; n < s0.MG.ss.size(); ++n)
|
ASSERT_TRUE(s0.p.MGs[0].ss.size() == s1.p.MGs[0].ss.size());
|
||||||
|
for (size_t n = 0; n < s0.p.MGs[0].ss.size(); ++n)
|
||||||
{
|
{
|
||||||
ASSERT_TRUE(s0.MG.ss[n] == s1.MG.ss[n]);
|
ASSERT_TRUE(s0.p.MGs[0].ss[n] == s1.p.MGs[0].ss[n]);
|
||||||
}
|
}
|
||||||
ASSERT_TRUE(s0.MG.cc == s1.MG.cc);
|
ASSERT_TRUE(s0.p.MGs[0].cc == s1.p.MGs[0].cc);
|
||||||
// mixRing and II are not serialized, they are meant to be reconstructed
|
// mixRing and II are not serialized, they are meant to be reconstructed
|
||||||
ASSERT_TRUE(s1.MGs[0].II.empty());
|
ASSERT_TRUE(s1.p.MGs[0].II.empty());
|
||||||
|
|
||||||
// mixRing and II are not serialized, they are meant to be reconstructed
|
// mixRing and II are not serialized, they are meant to be reconstructed
|
||||||
ASSERT_TRUE(s1.mixRing.size() == 0);
|
ASSERT_TRUE(s1.mixRing.size() == 0);
|
||||||
|
@ -631,10 +632,10 @@ TEST(Serialization, serializes_ringct_types)
|
||||||
tx0.vin.push_back(txin_to_key2);
|
tx0.vin.push_back(txin_to_key2);
|
||||||
tx0.vout.push_back(cryptonote::tx_out());
|
tx0.vout.push_back(cryptonote::tx_out());
|
||||||
tx0.rct_signatures = s0;
|
tx0.rct_signatures = s0;
|
||||||
ASSERT_EQ(tx0.rct_signatures.rangeSigs.size(), 2);
|
ASSERT_EQ(tx0.rct_signatures.p.rangeSigs.size(), 2);
|
||||||
ASSERT_TRUE(serialization::dump_binary(tx0, blob));
|
ASSERT_TRUE(serialization::dump_binary(tx0, blob));
|
||||||
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
|
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
|
||||||
ASSERT_EQ(tx1.rct_signatures.rangeSigs.size(), 2);
|
ASSERT_EQ(tx1.rct_signatures.p.rangeSigs.size(), 2);
|
||||||
std::string blob2;
|
std::string blob2;
|
||||||
ASSERT_TRUE(serialization::dump_binary(tx1, blob2));
|
ASSERT_TRUE(serialization::dump_binary(tx1, blob2));
|
||||||
ASSERT_TRUE(blob == blob2);
|
ASSERT_TRUE(blob == blob2);
|
||||||
|
|
Loading…
Reference in a new issue