diff options
author | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2016-09-14 20:23:06 +0100 |
---|---|---|
committer | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2016-09-14 20:23:06 +0100 |
commit | 7d413f635fb42f8cfe7567b07e981f3a312f8900 (patch) | |
tree | da4a3fb2f6c3b37b6fdb53632978311b05844d49 /src/ringct | |
parent | core: cleanup some typecasting (diff) | |
download | monero-7d413f635fb42f8cfe7567b07e981f3a312f8900.tar.xz |
rct: rework serialization to avoid storing vector sizes
Diffstat (limited to 'src/ringct')
-rw-r--r-- | src/ringct/rctSigs.cpp | 11 | ||||
-rw-r--r-- | src/ringct/rctTypes.h | 155 |
2 files changed, 130 insertions, 36 deletions
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index f4dbd65c5..ed1f8cc0e 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -350,8 +350,16 @@ namespace rct { keyV hashes; hashes.push_back(rv.message); crypto::hash h; - cryptonote::get_blob_hash(cryptonote::t_serializable_object_to_blob((const rctSigBase&)rv), h); + + std::stringstream ss; + binary_archive<true> ba(ss); + const size_t inputs = rv.pseudoOuts.size(); + const size_t outputs = rv.ecdhInfo.size(); + CHECK_AND_ASSERT_THROW_MES(const_cast<rctSig&>(rv).serialize_rctsig_base(ba, inputs, outputs), + "Failed to serialize rctSigBase"); + cryptonote::get_blob_hash(ss.str(), h); hashes.push_back(hash2rct(h)); + keyV kv; for (auto r: rv.p.rangeSigs) { @@ -364,7 +372,6 @@ namespace rct { kv.push_back(r.Ci[n]); } hashes.push_back(cn_fast_hash(kv)); - return cn_fast_hash(hashes); } diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index f231d30fb..bfafebb83 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -188,49 +188,136 @@ namespace rct { ctkeyV outPk; xmr_amount txnFee; // contains b - BEGIN_SERIALIZE() - FIELD(type) - if (type == RCTTypeNull) - return true; - // FIELD(message) - not serialized, it can be reconstructed - // FIELD(mixRing) - not serialized, it can be reconstructed - if (type == RCTTypeSimple) - FIELD(pseudoOuts) - FIELD(ecdhInfo) - if (typename Archive<W>::is_saving()) { - keyV outPk(this->outPk.size()); - for (size_t n = 0; n < outPk.size(); ++n) - outPk[n] = this->outPk[n].mask; - FIELD(outPk) + template<bool W, template <bool> class Archive> + bool serialize_rctsig_base(Archive<W> &ar, size_t inputs, size_t outputs) + { + FIELD(type) + if (type == RCTTypeNull) + return true; + if (type != RCTTypeFull && type != RCTTypeSimple) + 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) + { + 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(); } - else { - keyV outPk; - FIELD(outPk) - this->outPk.resize(outPk.size()); - for (size_t n = 0; n < outPk.size(); ++n) - this->outPk[n].mask = outPk[n]; - } - VARINT_FIELD(txnFee) - END_SERIALIZE() + ar.end_array(); + } + + ar.tag("ecdhInfo"); + ar.begin_array(); + PREPARE_CUSTOM_VECTOR_SERIALIZATION(outputs, ecdhInfo); + if (ecdhInfo.size() != outputs) + return false; + for (size_t i = 0; i < outputs; ++i) + { + FIELDS(ecdhInfo[i]) + if (outputs - i > 1) + ar.delimit_array(); + } + ar.end_array(); + + ar.tag("outPk"); + ar.begin_array(); + PREPARE_CUSTOM_VECTOR_SERIALIZATION(outputs, outPk); + if (outPk.size() != outputs) + return false; + for (size_t i = 0; i < outputs; ++i) + { + FIELDS(outPk[i].mask) + if (outputs - i > 1) + ar.delimit_array(); + } + ar.end_array(); + return true; + } }; struct rctSigPrunable { vector<rangeSig> rangeSigs; vector<mgSig> MGs; // simple rct has N, full has 1 - BEGIN_SERIALIZE() - FIELD(rangeSigs) - FIELD(MGs) - END_SERIALIZE() + 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) + { + if (type == RCTTypeNull) + return true; + if (type != RCTTypeFull && type != RCTTypeSimple) + return false; + 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; + PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_elements, MGs); + if (MGs.size() != mg_elements) + return false; + for (size_t i = 0; i < mg_elements; ++i) + { + // we save the MGs contents directly, because we want it to save its + // arrays and matrices without the size prefixes, and the load can't + // know what size to expect if it's not in the data + ar.tag("ss"); + ar.begin_array(); + PREPARE_CUSTOM_VECTOR_SERIALIZATION(mixin + 1, MGs[i].ss); + if (MGs[i].ss.size() != mixin + 1) + return false; + for (size_t j = 0; j < mixin + 1; ++j) + { + ar.begin_array(); + size_t mg_ss2_elements = (type == RCTTypeSimple ? 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; + for (size_t k = 0; k < mg_ss2_elements; ++k) + { + FIELDS(MGs[i].ss[j][k]) + if (mg_ss2_elements - j > 1) + ar.delimit_array(); + } + ar.end_array(); + + if (mixin + 1 - j > 1) + ar.delimit_array(); + } + ar.end_array(); + + FIELDS(MGs[i].cc) + // MGs[i].II not saved, it can be reconstructed + if (mg_elements - i > 1) + ar.delimit_array(); + } + ar.end_array(); + return true; + } + }; struct rctSig: public rctSigBase { rctSigPrunable p; - - BEGIN_SERIALIZE_OBJECT() - FIELDS(*static_cast<rctSigBase *>(this)) - if (type == RCTTypeNull) - return true; - FIELDS(p); - END_SERIALIZE() }; //other basepoint H = toPoint(cn_fast_hash(G)), G the basepoint |