diff options
Diffstat (limited to 'src/ringct')
-rw-r--r-- | src/ringct/rctSigs.cpp | 91 | ||||
-rw-r--r-- | src/ringct/rctTypes.h | 40 |
2 files changed, 90 insertions, 41 deletions
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index ddd26e3ad..cfb4aaf97 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -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; diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index aa906c0ef..50dfdb432 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -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,18 +284,18 @@ 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 (type == RCTTypeSimpleBulletproof || type == RCTTypeFullBulletproof) { - if (rangeSigs.size() != outputs) + ar.tag("bp"); + ar.begin_array(); + PREPARE_CUSTOM_VECTOR_SERIALIZATION(outputs, bulletproofs); + if (bulletproofs.size() != outputs) return false; for (size_t i = 0; i < outputs; ++i) { - FIELDS(rangeSigs[i]) + FIELDS(bulletproofs[i]) if (outputs - i > 1) ar.delimit_array(); } @@ -299,14 +303,14 @@ namespace rct { } else { - ar.tag("bp"); + ar.tag("rangeSigs"); ar.begin_array(); - PREPARE_CUSTOM_VECTOR_SERIALIZATION(outputs, bulletproofs); - if (bulletproofs.size() != outputs) + PREPARE_CUSTOM_VECTOR_SERIALIZATION(outputs, rangeSigs); + if (rangeSigs.size() != outputs) return false; for (size_t i = 0; i < outputs; ++i) { - FIELDS(bulletproofs[i]) + FIELDS(rangeSigs[i]) if (outputs - i > 1) ar.delimit_array(); } @@ -317,7 +321,7 @@ namespace rct { 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; |