aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2016-08-09 21:34:09 +0100
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2016-08-28 21:30:18 +0100
commit93f5c625f058ee1f81c02c8bb03744b28bbde90a (patch)
tree3f8fd5da151bc7000963a50b6f29b0256a762eff /src
parentrct: rework the verification preparation process (diff)
downloadmonero-93f5c625f058ee1f81c02c8bb03744b28bbde90a.tar.xz
rct: rework v2 txes into prunable and non prunable data
Nothing is pruned, but this allows easier changes later.
Diffstat (limited to '')
-rw-r--r--src/cryptonote_core/blockchain.cpp24
-rw-r--r--src/cryptonote_core/cryptonote_boost_serialization.h23
-rw-r--r--src/cryptonote_core/cryptonote_format_utils.cpp41
-rw-r--r--src/cryptonote_core/cryptonote_format_utils.h1
-rw-r--r--src/ringct/rctSigs.cpp45
-rw-r--r--src/ringct/rctTypes.h29
6 files changed, 112 insertions, 51 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 08cb85a55..44dde7759 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -2279,17 +2279,18 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
// II
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)
- 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)
{
- 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)
{
- rv.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.resize(1);
+ rv.p.MGs[n].II[0] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
}
}
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");
return false;
}
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");
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");
return false;
}
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");
return false;
diff --git a/src/cryptonote_core/cryptonote_boost_serialization.h b/src/cryptonote_core/cryptonote_boost_serialization.h
index 7a7cf8588..09e9a7fa7 100644
--- a/src/cryptonote_core/cryptonote_boost_serialization.h
+++ b/src/cryptonote_core/cryptonote_boost_serialization.h
@@ -246,23 +246,36 @@ namespace boost
}
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;
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.rangeSigs;
+ // a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
if (x.type == rct::RCTTypeSimple)
- a & x.MGs;
- if (x.type == rct::RCTTypeFull)
- a & x.MG;
+ a & x.pseudoOuts;
+ a & x.ecdhInfo;
+ serializeOutPk(a, x.outPk, ver);
+ 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;
}
}
}
diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp
index ddcab4f05..8f4020829 100644
--- a/src/cryptonote_core/cryptonote_format_utils.cpp
+++ b/src/cryptonote_core/cryptonote_format_utils.cpp
@@ -101,7 +101,7 @@ namespace cryptonote
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
//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);
return true;
}
@@ -905,20 +905,49 @@ namespace cryptonote
crypto::hash get_transaction_hash(const transaction& t)
{
crypto::hash h = null_hash;
- size_t blob_size = 0;
- get_object_hash(t, h, blob_size);
+ get_transaction_hash(t, h, NULL);
return h;
}
//---------------------------------------------------------------
bool get_transaction_hash(const transaction& t, crypto::hash& res)
{
- size_t blob_size = 0;
- return get_object_hash(t, res, blob_size);
+ return get_transaction_hash(t, res, NULL);
+ }
+ //---------------------------------------------------------------
+ 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)
{
- return get_object_hash(t, res, blob_size);
+ return get_transaction_hash(t, res, &blob_size);
}
//---------------------------------------------------------------
blobdata get_block_hashing_blob(const block& b)
diff --git a/src/cryptonote_core/cryptonote_format_utils.h b/src/cryptonote_core/cryptonote_format_utils.h
index e0ffbed67..f70b22573 100644
--- a/src/cryptonote_core/cryptonote_format_utils.h
+++ b/src/cryptonote_core/cryptonote_format_utils.h
@@ -111,6 +111,7 @@ namespace cryptonote
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, 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);
bool get_block_hash(const block& b, crypto::hash& res);
crypto::hash get_block_hash(const block& b);
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp
index ca38f13dd..d42be0fcc 100644
--- a/src/ringct/rctSigs.cpp
+++ b/src/ringct/rctSigs.cpp
@@ -346,7 +346,7 @@ namespace rct {
keyV kv;
kv.push_back(d2h(rv.type));
kv.push_back(rv.message);
- for (auto r: rv.rangeSigs)
+ for (auto r: rv.p.rangeSigs)
{
for (size_t n = 0; n < 64; ++n)
kv.push_back(r.asig.L1[n]);
@@ -593,8 +593,9 @@ namespace rct {
rctSig rv;
rv.type = RCTTypeFull;
+ rv.message = message;
rv.outPk.resize(destinations.size());
- rv.rangeSigs.resize(destinations.size());
+ rv.p.rangeSigs.resize(destinations.size());
rv.ecdhInfo.resize(destinations.size());
size_t i = 0;
@@ -604,9 +605,9 @@ namespace rct {
//add destination to sig
rv.outPk[i].dest = copy(destinations[i]);
//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
- 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
//mask amount and mask
@@ -628,7 +629,7 @@ namespace rct {
key txnFeeKey = scalarmultH(d2h(rv.txnFee));
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;
}
@@ -654,8 +655,9 @@ namespace rct {
rctSig rv;
rv.type = RCTTypeSimple;
+ rv.message = message;
rv.outPk.resize(destinations.size());
- rv.rangeSigs.resize(destinations.size());
+ rv.p.rangeSigs.resize(destinations.size());
rv.ecdhInfo.resize(destinations.size());
size_t i;
@@ -667,9 +669,9 @@ namespace rct {
//add destination to sig
rv.outPk[i].dest = copy(destinations[i]);
//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
- verRange(rv.outPk[i].mask, rv.rangeSigs[i]);
+ verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]);
#endif
sc_add(sumout.bytes, outSk[i].mask.bytes, sumout.bytes);
@@ -686,7 +688,7 @@ namespace rct {
// key txnFeeKey = scalarmultH(d2h(rv.txnFee));
rv.mixRing = mixRing;
rv.pseudoOuts.resize(inamounts.size());
- rv.MGs.resize(inamounts.size());
+ rv.p.MGs.resize(inamounts.size());
key sumpouts = zero(); //sum pseudoOut masks
keyV a(inamounts.size());
for (i = 0 ; i < inamounts.size() - 1; i++) {
@@ -701,7 +703,7 @@ namespace rct {
key full_message = get_pre_mlsag_hash(rv);
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;
}
@@ -731,8 +733,9 @@ namespace rct {
// must know the destination private key to find the correct amount, else will return a random number
bool verRct(const rctSig & rv) {
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.p.MGs.size() == 1, false, "full rctSig has not one MG");
// some rct ops can throw
try
@@ -742,13 +745,13 @@ namespace rct {
bool tmp;
DP("range proofs verified?");
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);
rvb = (rvb && tmp);
}
//compute txn fee
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(mgVerd);
@@ -767,14 +770,14 @@ namespace rct {
bool rvb = true;
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.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");
key sumOutpks = identity();
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;
}
addKeys(sumOutpks, sumOutpks, rv.outPk[i].mask);
@@ -787,7 +790,7 @@ namespace rct {
key message = get_pre_mlsag_hash(rv);
key sumPseudoOuts = identity();
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]);
DP(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
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_THROW_MES(rv.rangeSigs.size() > 0, "Empty rv.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.p.rangeSigs.size() > 0, "Empty rv.p.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");
//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&)) {
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.outPk.size() == rv.rangeSigs.size(), "Mismatched sizes of rv.outPk and 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.p.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.p.rangeSigs");
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
//mask amount and mask
diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h
index 98876a08c..8211fbaed 100644
--- a/src/ringct/rctTypes.h
+++ b/src/ringct/rctTypes.h
@@ -177,12 +177,9 @@ namespace rct {
RCTTypeFull = 0,
RCTTypeSimple = 1,
};
- struct rctSig {
+ struct rctSigBase {
uint8_t type;
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
//pairs that you mix with
keyV pseudoOuts; //C - for simple rct
@@ -190,14 +187,9 @@ namespace rct {
ctkeyV outPk;
xmr_amount txnFee; // contains b
- BEGIN_SERIALIZE_OBJECT()
+ BEGIN_SERIALIZE()
FIELD(type)
// 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
if (type == RCTTypeSimple)
FIELD(pseudoOuts)
@@ -218,6 +210,23 @@ namespace rct {
FIELD(txnFee)
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
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} };