aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_basic
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_basic')
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp101
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.h4
-rw-r--r--src/cryptonote_basic/hardfork.cpp18
3 files changed, 108 insertions, 15 deletions
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index ae7c1c0ae..428be1c9c 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -124,6 +124,40 @@ namespace cryptonote
return h;
}
//---------------------------------------------------------------
+ bool expand_transaction_1(transaction &tx, bool base_only)
+ {
+ if (tx.version >= 2 && !is_coinbase(tx))
+ {
+ rct::rctSig &rv = tx.rct_signatures;
+ if (rv.outPk.size() != tx.vout.size())
+ {
+ LOG_PRINT_L1("Failed to parse transaction from blob, bad outPk size in tx " << get_transaction_hash(tx));
+ return false;
+ }
+ for (size_t n = 0; n < tx.rct_signatures.outPk.size(); ++n)
+ rv.outPk[n].dest = rct::pk2rct(boost::get<txout_to_key>(tx.vout[n].target).key);
+
+ if (!base_only)
+ {
+ const bool bulletproof = rv.type == rct::RCTTypeFullBulletproof || rv.type == rct::RCTTypeSimpleBulletproof;
+ if (bulletproof)
+ {
+ if (rv.p.bulletproofs.size() != tx.vout.size())
+ {
+ LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs size in tx " << get_transaction_hash(tx));
+ return false;
+ }
+ for (size_t n = 0; n < rv.outPk.size(); ++n)
+ {
+ rv.p.bulletproofs[n].V.resize(1);
+ rv.p.bulletproofs[n].V[0] = rv.outPk[n].mask;
+ }
+ }
+ }
+ }
+ return true;
+ }
+ //---------------------------------------------------------------
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx)
{
std::stringstream ss;
@@ -131,6 +165,7 @@ namespace cryptonote
binary_archive<false> ba(ss);
bool r = ::serialization::serialize(ba, tx);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
+ CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data");
tx.invalidate_hashes();
return true;
}
@@ -142,6 +177,7 @@ namespace cryptonote
binary_archive<false> ba(ss);
bool r = tx.serialize_base(ba);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
+ CHECK_AND_ASSERT_MES(expand_transaction_1(tx, true), false, "Failed to expand transaction data");
return true;
}
//---------------------------------------------------------------
@@ -152,6 +188,7 @@ namespace cryptonote
binary_archive<false> ba(ss);
bool r = ::serialization::serialize(ba, tx);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
+ CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data");
tx.invalidate_hashes();
//TODO: validate tx
@@ -742,6 +779,61 @@ namespace cryptonote
return get_transaction_hash(t, res, NULL);
}
//---------------------------------------------------------------
+ bool calculate_transaction_prunable_hash(const transaction& t, crypto::hash& res)
+ {
+ if (t.version == 1)
+ return false;
+ transaction &tt = const_cast<transaction&>(t);
+ std::stringstream ss;
+ binary_archive<true> ba(ss);
+ const size_t inputs = t.vin.size();
+ const size_t outputs = t.vout.size();
+ const size_t mixin = t.vin.empty() ? 0 : t.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(t.vin[0]).key_offsets.size() - 1 : 0;
+ bool r = tt.rct_signatures.p.serialize_rctsig_prunable(ba, t.rct_signatures.type, inputs, outputs, mixin);
+ CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures prunable");
+ cryptonote::get_blob_hash(ss.str(), res);
+ return true;
+ }
+ //---------------------------------------------------------------
+ crypto::hash get_transaction_prunable_hash(const transaction& t)
+ {
+ crypto::hash res;
+ CHECK_AND_ASSERT_THROW_MES(calculate_transaction_prunable_hash(t, res), "Failed to calculate tx prunable hash");
+ return res;
+ }
+ //---------------------------------------------------------------
+ crypto::hash get_pruned_transaction_hash(const transaction& t, const crypto::hash &pruned_data_hash)
+ {
+ // v1 transactions hash the entire blob
+ CHECK_AND_ASSERT_THROW_MES(t.version > 1, "Hash for pruned v1 tx cannot be calculated");
+
+ // 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]);
+
+ transaction &tt = const_cast<transaction&>(t);
+
+ // base rct
+ {
+ std::stringstream ss;
+ binary_archive<true> ba(ss);
+ const size_t inputs = t.vin.size();
+ const size_t outputs = t.vout.size();
+ bool r = tt.rct_signatures.serialize_rctsig_base(ba, inputs, outputs);
+ CHECK_AND_ASSERT_THROW_MES(r, "Failed to serialize rct signatures base");
+ cryptonote::get_blob_hash(ss.str(), hashes[1]);
+ }
+
+ // prunable rct
+ hashes[2] = pruned_data_hash;
+
+ // the tx hash is the hash of the 3 hashes
+ crypto::hash res = cn_fast_hash(hashes, sizeof(hashes));
+ return res;
+ }
+ //---------------------------------------------------------------
bool calculate_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size)
{
// v1 transactions hash the entire blob
@@ -777,14 +869,7 @@ namespace cryptonote
}
else
{
- std::stringstream ss;
- binary_archive<true> ba(ss);
- const size_t inputs = t.vin.size();
- const size_t outputs = t.vout.size();
- const size_t mixin = t.vin.empty() ? 0 : t.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(t.vin[0]).key_offsets.size() - 1 : 0;
- bool r = tt.rct_signatures.p.serialize_rctsig_prunable(ba, t.rct_signatures.type, inputs, outputs, mixin);
- CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures prunable");
- cryptonote::get_blob_hash(ss.str(), hashes[2]);
+ CHECK_AND_ASSERT_MES(calculate_transaction_prunable_hash(t, hashes[2]), false, "Failed to get tx prunable hash");
}
// the tx hash is the hash of the 3 hashes
diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h
index 79466e9c4..8a5296d5b 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.h
+++ b/src/cryptonote_basic/cryptonote_format_utils.h
@@ -100,7 +100,11 @@ namespace cryptonote
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);
+ bool calculate_transaction_prunable_hash(const transaction& t, crypto::hash& res);
+ crypto::hash get_transaction_prunable_hash(const transaction& t);
bool calculate_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size);
+ crypto::hash get_pruned_transaction_hash(const transaction& t, const crypto::hash &pruned_data_hash);
+
blobdata get_block_hashing_blob(const block& b);
bool calculate_block_hash(const block& b, crypto::hash& res);
bool get_block_hash(const block& b, crypto::hash& res);
diff --git a/src/cryptonote_basic/hardfork.cpp b/src/cryptonote_basic/hardfork.cpp
index 95f1ecab9..f05b25901 100644
--- a/src/cryptonote_basic/hardfork.cpp
+++ b/src/cryptonote_basic/hardfork.cpp
@@ -379,20 +379,24 @@ uint8_t HardFork::get_ideal_version(uint64_t height) const
uint64_t HardFork::get_earliest_ideal_height_for_version(uint8_t version) const
{
- for (unsigned int n = heights.size() - 1; n > 0; --n) {
- if (heights[n].version <= version)
- return heights[n].height;
+ uint64_t height = std::numeric_limits<uint64_t>::max();
+ for (auto i = heights.rbegin(); i != heights.rend(); ++i) {
+ if (i->version >= version) {
+ height = i->height;
+ } else {
+ break;
+ }
}
- return 0;
+ return height;
}
uint8_t HardFork::get_next_version() const
{
CRITICAL_REGION_LOCAL(lock);
uint64_t height = db.height();
- for (unsigned int n = heights.size() - 1; n > 0; --n) {
- if (height >= heights[n].height) {
- return heights[n < heights.size() - 1 ? n + 1 : n].version;
+ for (auto i = heights.rbegin(); i != heights.rend(); ++i) {
+ if (height >= i->height) {
+ return (i == heights.rbegin() ? i : (i - 1))->version;
}
}
return original_version;