mirror of
https://codeberg.org/anoncontributorxmr/monero.git
synced 2024-11-23 11:23:26 +01:00
ringct: pseudoOuts moved to prunable in the simple bulletproof case
Saves 64 bytes non prunable data per typical tx This breaks v7 consensus, will require a testnet reorg from v6
This commit is contained in:
parent
ed67e5c001
commit
b809058993
@ -299,7 +299,7 @@ namespace boost
|
|||||||
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.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 || x.type == rct::RCTTypeSimpleBulletproof)
|
if (x.type == rct::RCTTypeSimple) // moved to prunable with bulletproofs
|
||||||
a & x.pseudoOuts;
|
a & x.pseudoOuts;
|
||||||
a & x.ecdhInfo;
|
a & x.ecdhInfo;
|
||||||
serializeOutPk(a, x.outPk, ver);
|
serializeOutPk(a, x.outPk, ver);
|
||||||
@ -313,6 +313,8 @@ namespace boost
|
|||||||
if (x.rangeSigs.empty())
|
if (x.rangeSigs.empty())
|
||||||
a & x.bulletproofs;
|
a & x.bulletproofs;
|
||||||
a & x.MGs;
|
a & x.MGs;
|
||||||
|
if (x.rangeSigs.empty())
|
||||||
|
a & x.pseudoOuts;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
@ -325,7 +327,7 @@ namespace boost
|
|||||||
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.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 || x.type == rct::RCTTypeSimpleBulletproof)
|
if (x.type == rct::RCTTypeSimple)
|
||||||
a & x.pseudoOuts;
|
a & x.pseudoOuts;
|
||||||
a & x.ecdhInfo;
|
a & x.ecdhInfo;
|
||||||
serializeOutPk(a, x.outPk, ver);
|
serializeOutPk(a, x.outPk, ver);
|
||||||
@ -335,6 +337,8 @@ namespace boost
|
|||||||
if (x.p.rangeSigs.empty())
|
if (x.p.rangeSigs.empty())
|
||||||
a & x.p.bulletproofs;
|
a & x.p.bulletproofs;
|
||||||
a & x.p.MGs;
|
a & x.p.MGs;
|
||||||
|
if (x.type == rct::RCTTypeSimpleBulletproof)
|
||||||
|
a & x.p.pseudoOuts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,30 @@ using namespace std;
|
|||||||
#define MONERO_DEFAULT_LOG_CATEGORY "ringct"
|
#define MONERO_DEFAULT_LOG_CATEGORY "ringct"
|
||||||
|
|
||||||
namespace rct {
|
namespace rct {
|
||||||
|
bool is_simple(int type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case RCTTypeSimple:
|
||||||
|
case RCTTypeSimpleBulletproof:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_bulletproof(int type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case RCTTypeSimpleBulletproof:
|
||||||
|
case RCTTypeFullBulletproof:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Bulletproof proveRangeBulletproof(key &C, key &mask, uint64_t amount)
|
Bulletproof proveRangeBulletproof(key &C, key &mask, uint64_t amount)
|
||||||
{
|
{
|
||||||
mask = rct::skGen();
|
mask = rct::skGen();
|
||||||
@ -357,7 +381,8 @@ namespace rct {
|
|||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
binary_archive<true> ba(ss);
|
binary_archive<true> ba(ss);
|
||||||
const size_t inputs = rv.pseudoOuts.size();
|
CHECK_AND_ASSERT_THROW_MES(!rv.mixRing.empty(), "Empty mixRing");
|
||||||
|
const size_t inputs = is_simple(rv.type) ? rv.mixRing.size() : rv.mixRing[0].size();
|
||||||
const size_t outputs = rv.ecdhInfo.size();
|
const size_t outputs = rv.ecdhInfo.size();
|
||||||
CHECK_AND_ASSERT_THROW_MES(const_cast<rctSig&>(rv).serialize_rctsig_base(ba, inputs, outputs),
|
CHECK_AND_ASSERT_THROW_MES(const_cast<rctSig&>(rv).serialize_rctsig_base(ba, inputs, outputs),
|
||||||
"Failed to serialize rctSigBase");
|
"Failed to serialize rctSigBase");
|
||||||
@ -750,25 +775,26 @@ namespace rct {
|
|||||||
// TODO: unused ??
|
// TODO: unused ??
|
||||||
// key txnFeeKey = scalarmultH(d2h(rv.txnFee));
|
// key txnFeeKey = scalarmultH(d2h(rv.txnFee));
|
||||||
rv.mixRing = mixRing;
|
rv.mixRing = mixRing;
|
||||||
rv.pseudoOuts.resize(inamounts.size());
|
keyV &pseudoOuts = bulletproof ? rv.p.pseudoOuts : rv.pseudoOuts;
|
||||||
|
pseudoOuts.resize(inamounts.size());
|
||||||
rv.p.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++) {
|
||||||
skGen(a[i]);
|
skGen(a[i]);
|
||||||
sc_add(sumpouts.bytes, a[i].bytes, sumpouts.bytes);
|
sc_add(sumpouts.bytes, a[i].bytes, sumpouts.bytes);
|
||||||
genC(rv.pseudoOuts[i], a[i], inamounts[i]);
|
genC(pseudoOuts[i], a[i], inamounts[i]);
|
||||||
}
|
}
|
||||||
rv.mixRing = mixRing;
|
rv.mixRing = mixRing;
|
||||||
sc_sub(a[i].bytes, sumout.bytes, sumpouts.bytes);
|
sc_sub(a[i].bytes, sumout.bytes, sumpouts.bytes);
|
||||||
genC(rv.pseudoOuts[i], a[i], inamounts[i]);
|
genC(pseudoOuts[i], a[i], inamounts[i]);
|
||||||
DP(rv.pseudoOuts[i]);
|
DP(pseudoOuts[i]);
|
||||||
|
|
||||||
key full_message = get_pre_mlsag_hash(rv);
|
key full_message = get_pre_mlsag_hash(rv);
|
||||||
if (msout)
|
if (msout)
|
||||||
msout->c.resize(inamounts.size());
|
msout->c.resize(inamounts.size());
|
||||||
for (i = 0 ; i < inamounts.size(); i++) {
|
for (i = 0 ; i < inamounts.size(); i++) {
|
||||||
rv.p.MGs[i] = proveRctMGSimple(full_message, rv.mixRing[i], inSk[i], a[i], rv.pseudoOuts[i], kLRki ? &(*kLRki)[i]: NULL, msout ? &msout->c[i] : NULL, index[i]);
|
rv.p.MGs[i] = proveRctMGSimple(full_message, rv.mixRing[i], inSk[i], a[i], pseudoOuts[i], kLRki ? &(*kLRki)[i]: NULL, msout ? &msout->c[i] : NULL, index[i]);
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -876,16 +902,26 @@ namespace rct {
|
|||||||
if (semantics)
|
if (semantics)
|
||||||
{
|
{
|
||||||
if (rv.type == RCTTypeSimpleBulletproof)
|
if (rv.type == RCTTypeSimpleBulletproof)
|
||||||
|
{
|
||||||
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.bulletproofs.size(), false, "Mismatched sizes of outPk and rv.p.bulletproofs");
|
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.bulletproofs.size(), false, "Mismatched sizes of outPk and rv.p.bulletproofs");
|
||||||
|
CHECK_AND_ASSERT_MES(rv.p.pseudoOuts.size() == rv.p.MGs.size(), false, "Mismatched sizes of rv.p.pseudoOuts and rv.p.MGs");
|
||||||
|
CHECK_AND_ASSERT_MES(rv.pseudoOuts.empty(), false, "rv.pseudoOuts is not empty");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
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.p.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.p.rangeSigs");
|
||||||
|
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.p.pseudoOuts.empty(), false, "rv.p.pseudoOuts is not empty");
|
||||||
|
}
|
||||||
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.p.MGs.size(), false, "Mismatched sizes of rv.pseudoOuts and rv.p.MGs");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// semantics check is early, and mixRing/MGs aren't resolved yet
|
// semantics check is early, and mixRing/MGs aren't resolved yet
|
||||||
CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.pseudoOuts and mixRing");
|
if (rv.type == RCTTypeSimpleBulletproof)
|
||||||
|
CHECK_AND_ASSERT_MES(rv.p.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.p.pseudoOuts and mixRing");
|
||||||
|
else
|
||||||
|
CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.pseudoOuts and mixRing");
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t threads = std::max(rv.outPk.size(), rv.mixRing.size());
|
const size_t threads = std::max(rv.outPk.size(), rv.mixRing.size());
|
||||||
@ -894,6 +930,8 @@ namespace rct {
|
|||||||
tools::threadpool& tpool = tools::threadpool::getInstance();
|
tools::threadpool& tpool = tools::threadpool::getInstance();
|
||||||
tools::threadpool::waiter waiter;
|
tools::threadpool::waiter waiter;
|
||||||
|
|
||||||
|
const keyV &pseudoOuts = is_bulletproof(rv.type) ? rv.p.pseudoOuts : rv.pseudoOuts;
|
||||||
|
|
||||||
if (semantics) {
|
if (semantics) {
|
||||||
key sumOutpks = identity();
|
key sumOutpks = identity();
|
||||||
for (size_t i = 0; i < rv.outPk.size(); i++) {
|
for (size_t i = 0; i < rv.outPk.size(); i++) {
|
||||||
@ -904,8 +942,8 @@ namespace rct {
|
|||||||
addKeys(sumOutpks, txnFeeKey, sumOutpks);
|
addKeys(sumOutpks, txnFeeKey, sumOutpks);
|
||||||
|
|
||||||
key sumPseudoOuts = identity();
|
key sumPseudoOuts = identity();
|
||||||
for (size_t i = 0 ; i < rv.pseudoOuts.size() ; i++) {
|
for (size_t i = 0 ; i < pseudoOuts.size() ; i++) {
|
||||||
addKeys(sumPseudoOuts, sumPseudoOuts, rv.pseudoOuts[i]);
|
addKeys(sumPseudoOuts, sumPseudoOuts, pseudoOuts[i]);
|
||||||
}
|
}
|
||||||
DP(sumPseudoOuts);
|
DP(sumPseudoOuts);
|
||||||
|
|
||||||
@ -941,7 +979,7 @@ namespace rct {
|
|||||||
results.resize(rv.mixRing.size());
|
results.resize(rv.mixRing.size());
|
||||||
for (size_t i = 0 ; i < rv.mixRing.size() ; i++) {
|
for (size_t i = 0 ; i < rv.mixRing.size() ; i++) {
|
||||||
tpool.submit(&waiter, [&, i] {
|
tpool.submit(&waiter, [&, i] {
|
||||||
results[i] = verRctMGSimple(message, rv.p.MGs[i], rv.mixRing[i], rv.pseudoOuts[i]);
|
results[i] = verRctMGSimple(message, rv.p.MGs[i], rv.mixRing[i], pseudoOuts[i]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
waiter.wait();
|
waiter.wait();
|
||||||
|
@ -246,7 +246,7 @@ namespace rct {
|
|||||||
// inputs/outputs not saved, only here for serialization help
|
// inputs/outputs not saved, only here for serialization help
|
||||||
// FIELD(message) - not serialized, it can be reconstructed
|
// FIELD(message) - not serialized, it can be reconstructed
|
||||||
// FIELD(mixRing) - not serialized, it can be reconstructed
|
// FIELD(mixRing) - not serialized, it can be reconstructed
|
||||||
if (type == RCTTypeSimple || type == RCTTypeSimpleBulletproof)
|
if (type == RCTTypeSimple) // moved to prunable with bulletproofs
|
||||||
{
|
{
|
||||||
ar.tag("pseudoOuts");
|
ar.tag("pseudoOuts");
|
||||||
ar.begin_array();
|
ar.begin_array();
|
||||||
@ -294,6 +294,7 @@ namespace rct {
|
|||||||
std::vector<rangeSig> rangeSigs;
|
std::vector<rangeSig> rangeSigs;
|
||||||
std::vector<Bulletproof> bulletproofs;
|
std::vector<Bulletproof> bulletproofs;
|
||||||
std::vector<mgSig> MGs; // simple rct has N, full has 1
|
std::vector<mgSig> MGs; // simple rct has N, full has 1
|
||||||
|
keyV pseudoOuts; //C - for simple rct
|
||||||
|
|
||||||
template<bool W, template <bool> class Archive>
|
template<bool W, template <bool> class Archive>
|
||||||
bool serialize_rctsig_prunable(Archive<W> &ar, uint8_t type, size_t inputs, size_t outputs, size_t mixin)
|
bool serialize_rctsig_prunable(Archive<W> &ar, uint8_t type, size_t inputs, size_t outputs, size_t mixin)
|
||||||
@ -381,6 +382,21 @@ namespace rct {
|
|||||||
ar.delimit_array();
|
ar.delimit_array();
|
||||||
}
|
}
|
||||||
ar.end_array();
|
ar.end_array();
|
||||||
|
if (type == RCTTypeSimpleBulletproof)
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user