mirror of
https://github.com/monero-project/monero.git
synced 2025-08-07 09:22:19 -04:00
add bulletproofs from v7 on testnet
This commit is contained in:
parent
8620ef0a0d
commit
c83d0b3ee2
11 changed files with 201 additions and 70 deletions
|
@ -47,7 +47,8 @@ namespace rct {
|
|||
{
|
||||
mask = rct::skGen();
|
||||
Bulletproof proof = bulletproof_PROVE(amount, mask);
|
||||
C = proof.V;
|
||||
CHECK_AND_ASSERT_THROW_MES(proof.V.size() == 1, "V has not exactly one element");
|
||||
C = proof.V[0];
|
||||
return proof;
|
||||
}
|
||||
|
||||
|
@ -344,16 +345,41 @@ namespace rct {
|
|||
hashes.push_back(hash2rct(h));
|
||||
|
||||
keyV kv;
|
||||
kv.reserve((64*3+1) * rv.p.rangeSigs.size());
|
||||
for (auto r: rv.p.rangeSigs)
|
||||
if (rv.type == RCTTypeSimpleBulletproof || rv.type == RCTTypeFullBulletproof)
|
||||
{
|
||||
for (size_t n = 0; n < 64; ++n)
|
||||
kv.push_back(r.asig.s0[n]);
|
||||
for (size_t n = 0; n < 64; ++n)
|
||||
kv.push_back(r.asig.s1[n]);
|
||||
kv.push_back(r.asig.ee);
|
||||
for (size_t n = 0; n < 64; ++n)
|
||||
kv.push_back(r.Ci[n]);
|
||||
kv.reserve((6*2+10) * rv.p.bulletproofs.size());
|
||||
for (const auto &p: rv.p.bulletproofs)
|
||||
{
|
||||
for (size_t n = 0; n < p.V.size(); ++n)
|
||||
kv.push_back(p.V[n]);
|
||||
kv.push_back(p.A);
|
||||
kv.push_back(p.S);
|
||||
kv.push_back(p.T1);
|
||||
kv.push_back(p.T2);
|
||||
kv.push_back(p.taux);
|
||||
kv.push_back(p.mu);
|
||||
for (size_t n = 0; n < p.L.size(); ++n)
|
||||
kv.push_back(p.L[n]);
|
||||
for (size_t n = 0; n < p.R.size(); ++n)
|
||||
kv.push_back(p.R[n]);
|
||||
kv.push_back(p.a);
|
||||
kv.push_back(p.b);
|
||||
kv.push_back(p.t);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
kv.reserve((64*3+1) * rv.p.rangeSigs.size());
|
||||
for (const auto &r: rv.p.rangeSigs)
|
||||
{
|
||||
for (size_t n = 0; n < 64; ++n)
|
||||
kv.push_back(r.asig.s0[n]);
|
||||
for (size_t n = 0; n < 64; ++n)
|
||||
kv.push_back(r.asig.s1[n]);
|
||||
kv.push_back(r.asig.ee);
|
||||
for (size_t n = 0; n < 64; ++n)
|
||||
kv.push_back(r.Ci[n]);
|
||||
}
|
||||
}
|
||||
hashes.push_back(cn_fast_hash(kv));
|
||||
return cn_fast_hash(hashes);
|
||||
|
@ -581,10 +607,13 @@ namespace rct {
|
|||
}
|
||||
|
||||
rctSig rv;
|
||||
rv.type = RCTTypeFull;
|
||||
rv.type = bulletproof ? RCTTypeFullBulletproof : RCTTypeFull;
|
||||
rv.message = message;
|
||||
rv.outPk.resize(destinations.size());
|
||||
rv.p.rangeSigs.resize(destinations.size());
|
||||
if (bulletproof)
|
||||
rv.p.bulletproofs.resize(destinations.size());
|
||||
else
|
||||
rv.p.rangeSigs.resize(destinations.size());
|
||||
rv.ecdhInfo.resize(destinations.size());
|
||||
|
||||
size_t i = 0;
|
||||
|
@ -650,7 +679,7 @@ namespace rct {
|
|||
}
|
||||
|
||||
rctSig rv;
|
||||
rv.type = RCTTypeSimple;
|
||||
rv.type = bulletproof ? RCTTypeSimpleBulletproof : RCTTypeSimple;
|
||||
rv.message = message;
|
||||
rv.outPk.resize(destinations.size());
|
||||
if (bulletproof)
|
||||
|
@ -738,10 +767,10 @@ namespace rct {
|
|||
// must know the destination private key to find the correct amount, else will return a random number
|
||||
bool verRct(const rctSig & rv, bool semantics) {
|
||||
PERF_TIMER(verRct);
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "verRct called on non-full rctSig");
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull || rv.type == RCTTypeFullBulletproof, false, "verRct called on non-full rctSig");
|
||||
if (semantics)
|
||||
{
|
||||
if (rv.p.rangeSigs.empty())
|
||||
if (rv.type == RCTTypeFullBulletproof)
|
||||
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.bulletproofs.size(), false, "Mismatched sizes of outPk and rv.p.bulletproofs");
|
||||
else
|
||||
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.p.rangeSigs");
|
||||
|
@ -764,7 +793,7 @@ namespace rct {
|
|||
for (size_t i = 0; i < rv.outPk.size(); i++) {
|
||||
tpool.submit(&waiter, [&, i] {
|
||||
if (rv.p.rangeSigs.empty())
|
||||
results[i] = bulletproof_VERIFY(rv.p.bulletproofs[i]); // TODO
|
||||
results[i] = bulletproof_VERIFY(rv.p.bulletproofs[i]);
|
||||
else
|
||||
results[i] = verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]);
|
||||
});
|
||||
|
@ -806,10 +835,10 @@ namespace rct {
|
|||
{
|
||||
PERF_TIMER(verRctSimple);
|
||||
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple, false, "verRctSimple called on non simple rctSig");
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeSimpleBulletproof, false, "verRctSimple called on non simple rctSig");
|
||||
if (semantics)
|
||||
{
|
||||
if (rv.p.rangeSigs.empty())
|
||||
if (rv.type == RCTTypeSimpleBulletproof)
|
||||
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.bulletproofs.size(), false, "Mismatched sizes of outPk and rv.p.bulletproofs");
|
||||
else
|
||||
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.p.rangeSigs");
|
||||
|
@ -905,9 +934,17 @@ namespace rct {
|
|||
// uses the attached ecdh info to find the amounts represented by each output commitment
|
||||
// must know the destination private key to find the correct amount, else will return a random number
|
||||
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask) {
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "decodeRct called on non-full rctSig");
|
||||
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo");
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull || rv.type == RCTTypeFullBulletproof, false, "decodeRct called on non-full rctSig");
|
||||
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
||||
if (rv.type == RCTTypeFullBulletproof)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(rv.p.bulletproofs.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.p.bulletproofs and rv.ecdhInfo");
|
||||
CHECK_AND_ASSERT_THROW_MES(rv.p.bulletproofs[i].V.size() == 1, "Unexpected sizes of rv.p.bulletproofs[i].V");
|
||||
}
|
||||
else
|
||||
{
|
||||
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];
|
||||
|
@ -933,16 +970,24 @@ namespace rct {
|
|||
}
|
||||
|
||||
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask) {
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple, false, "decodeRct called on non simple rctSig");
|
||||
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo");
|
||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeSimpleBulletproof, false, "decodeRct called on non simple rctSig");
|
||||
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
||||
if (rv.type == RCTTypeSimpleBulletproof)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(rv.p.bulletproofs.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.p.bulletproofs and rv.ecdhInfo");
|
||||
CHECK_AND_ASSERT_THROW_MES(rv.p.bulletproofs[i].V.size() == 1, "Unexpected sizes of rv.p.bulletproofs[i].V");
|
||||
}
|
||||
else
|
||||
{
|
||||
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];
|
||||
ecdhDecode(ecdh_info, sk);
|
||||
mask = ecdh_info.mask;
|
||||
key amount = ecdh_info.amount;
|
||||
key C = rv.outPk[i].mask;
|
||||
key C = (rv.type == RCTTypeSimpleBulletproof) ? rv.p.bulletproofs[i].V.front() : rv.outPk[i].mask;
|
||||
DP("C");
|
||||
DP(C);
|
||||
key Ctmp;
|
||||
|
|
|
@ -164,17 +164,19 @@ namespace rct {
|
|||
|
||||
struct Bulletproof
|
||||
{
|
||||
rct::key V, A, S, T1, T2;
|
||||
rct::keyV V;
|
||||
rct::key A, S, T1, T2;
|
||||
rct::key taux, mu;
|
||||
rct::keyV L, R;
|
||||
rct::key a, b, t;
|
||||
|
||||
Bulletproof() {}
|
||||
Bulletproof(const rct::key &V, const rct::key &A, const rct::key &S, const rct::key &T1, const rct::key &T2, const rct::key &taux, const rct::key &mu, const rct::keyV &L, const rct::keyV &R, const rct::key &a, const rct::key &b, const rct::key &t):
|
||||
V(V), A(A), S(S), T1(T1), T2(T2), taux(taux), mu(mu), L(L), R(R), a(a), b(b), t(t) {}
|
||||
V({V}), A(A), S(S), T1(T1), T2(T2), taux(taux), mu(mu), L(L), R(R), a(a), b(b), t(t) {}
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(V)
|
||||
// Commitments aren't saved, they're restored via outPk
|
||||
// FIELD(V)
|
||||
FIELD(A)
|
||||
FIELD(S)
|
||||
FIELD(T1)
|
||||
|
@ -203,6 +205,8 @@ namespace rct {
|
|||
RCTTypeNull = 0,
|
||||
RCTTypeFull = 1,
|
||||
RCTTypeSimple = 2,
|
||||
RCTTypeFullBulletproof = 3,
|
||||
RCTTypeSimpleBulletproof = 4,
|
||||
};
|
||||
struct rctSigBase {
|
||||
uint8_t type;
|
||||
|
@ -220,13 +224,13 @@ namespace rct {
|
|||
FIELD(type)
|
||||
if (type == RCTTypeNull)
|
||||
return true;
|
||||
if (type != RCTTypeFull && type != RCTTypeSimple)
|
||||
if (type != RCTTypeFull && type != RCTTypeFullBulletproof && type != RCTTypeSimple && type != RCTTypeSimpleBulletproof)
|
||||
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)
|
||||
if (type == RCTTypeSimple || type == RCTTypeSimpleBulletproof)
|
||||
{
|
||||
ar.tag("pseudoOuts");
|
||||
ar.begin_array();
|
||||
|
@ -280,24 +284,9 @@ namespace rct {
|
|||
{
|
||||
if (type == RCTTypeNull)
|
||||
return true;
|
||||
if (type != RCTTypeFull && type != RCTTypeSimple)
|
||||
if (type != RCTTypeFull && type != RCTTypeFullBulletproof && type != RCTTypeSimple && type != RCTTypeSimpleBulletproof)
|
||||
return false;
|
||||
ar.tag("rangeSigs");
|
||||
ar.begin_array();
|
||||
PREPARE_CUSTOM_VECTOR_SERIALIZATION(outputs, rangeSigs);
|
||||
if (!rangeSigs.empty())
|
||||
{
|
||||
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();
|
||||
}
|
||||
else
|
||||
if (type == RCTTypeSimpleBulletproof || type == RCTTypeFullBulletproof)
|
||||
{
|
||||
ar.tag("bp");
|
||||
ar.begin_array();
|
||||
|
@ -312,12 +301,27 @@ namespace rct {
|
|||
}
|
||||
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();
|
||||
}
|
||||
|
||||
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 ? inputs : 1;
|
||||
size_t mg_elements = (type == RCTTypeSimple || type == RCTTypeSimpleBulletproof) ? inputs : 1;
|
||||
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_elements, MGs);
|
||||
if (MGs.size() != mg_elements)
|
||||
return false;
|
||||
|
@ -335,7 +339,7 @@ namespace rct {
|
|||
for (size_t j = 0; j < mixin + 1; ++j)
|
||||
{
|
||||
ar.begin_array();
|
||||
size_t mg_ss2_elements = (type == RCTTypeSimple ? 1 : inputs) + 1;
|
||||
size_t mg_ss2_elements = ((type == RCTTypeSimple || type == RCTTypeSimpleBulletproof) ? 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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue