aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_core')
-rw-r--r--src/cryptonote_core/blockchain.cpp35
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp19
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.cpp8
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.h2
4 files changed, 50 insertions, 14 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 3d586a704..836856bae 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -127,6 +127,7 @@ static const struct {
{ 5, 802660, 0, 1472415036 + 86400*180 }, // add 5 months on testnet to shut the update warning up since there's a large gap to v6
{ 6, 971400, 0, 1501709789 },
+ { 7, 1057028, 0, 1512211236 },
};
static const uint64_t testnet_hard_fork_version_1_till = 624633;
@@ -2387,8 +2388,10 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ const uint8_t hf_version = m_hardfork->get_current_version();
+
// from hard fork 2, we forbid dust and compound outputs
- if (m_hardfork->get_current_version() >= 2) {
+ if (hf_version >= 2) {
for (auto &o: tx.vout) {
if (tx.version == 1)
{
@@ -2401,7 +2404,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
}
// in a v2 tx, all outputs must have 0 amount
- if (m_hardfork->get_current_version() >= 3) {
+ if (hf_version >= 3) {
if (tx.version >= 2) {
for (auto &o: tx.vout) {
if (o.amount != 0) {
@@ -2413,7 +2416,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
}
// from v4, forbid invalid pubkeys
- if (m_hardfork->get_current_version() >= 4) {
+ if (hf_version >= 4) {
for (const auto &o: tx.vout) {
if (o.target.type() == typeid(txout_to_key)) {
const txout_to_key& out_to_key = boost::get<txout_to_key>(o.target);
@@ -2425,6 +2428,16 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
}
}
+ // from v7, allow bulletproofs
+ if (hf_version < 7 || !m_testnet) {
+ if (!tx.rct_signatures.p.bulletproofs.empty())
+ {
+ MERROR("Bulletproofs are not allowed before v7 or on mainnet");
+ tvc.m_invalid_output = true;
+ return false;
+ }
+ }
+
return true;
}
//------------------------------------------------------------------
@@ -2450,7 +2463,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
rv.message = rct::hash2rct(tx_prefix_hash);
// mixRing - full and simple store it in opposite ways
- if (rv.type == rct::RCTTypeFull)
+ if (rv.type == rct::RCTTypeFull || rv.type == rct::RCTTypeFullBulletproof)
{
rv.mixRing.resize(pubkeys[0].size());
for (size_t m = 0; m < pubkeys[0].size(); ++m)
@@ -2464,7 +2477,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
}
}
}
- else if (rv.type == rct::RCTTypeSimple)
+ else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeSimpleBulletproof)
{
rv.mixRing.resize(pubkeys.size());
for (size_t n = 0; n < pubkeys.size(); ++n)
@@ -2482,14 +2495,14 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
}
// II
- if (rv.type == rct::RCTTypeFull)
+ if (rv.type == rct::RCTTypeFull || rv.type == rct::RCTTypeFullBulletproof)
{
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.p.MGs[0].II[n] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
}
- else if (rv.type == rct::RCTTypeSimple)
+ else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeSimpleBulletproof)
{
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)
@@ -2753,7 +2766,9 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
MERROR_VER("Null rct signature on non-coinbase tx");
return false;
}
- case rct::RCTTypeSimple: {
+ case rct::RCTTypeSimple:
+ case rct::RCTTypeSimpleBulletproof:
+ {
// check all this, either recontructed (so should really pass), or not
{
if (pubkeys.size() != rv.mixRing.size())
@@ -2809,7 +2824,9 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
}
break;
}
- case rct::RCTTypeFull: {
+ case rct::RCTTypeFull:
+ case rct::RCTTypeFullBulletproof:
+ {
// check all this, either recontructed (so should really pass), or not
{
bool size_matches = true;
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 5c181208f..5cfa4b3e9 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -625,6 +625,22 @@ namespace cryptonote
}
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);
+
+ const bool bulletproof = rv.type == rct::RCTTypeFullBulletproof || rv.type == rct::RCTTypeSimpleBulletproof;
+ if (bulletproof)
+ {
+ if (rv.p.bulletproofs.size() != tx.vout.size())
+ {
+ LOG_PRINT_L1("WRONG TRANSACTION BLOB, Bad bulletproofs size in tx " << tx_hash << ", rejected");
+ tvc.m_verifivation_failed = true;
+ 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;
+ }
+ }
}
if (keeped_by_block && get_blockchain_storage().is_within_compiled_block_hash_area())
@@ -828,6 +844,7 @@ namespace cryptonote
MERROR_VER("Unexpected Null rctSig type");
return false;
case rct::RCTTypeSimple:
+ case rct::RCTTypeSimpleBulletproof:
if (!rct::verRctSimple(rv, true))
{
MERROR_VER("rct signature semantics check failed");
@@ -835,6 +852,7 @@ namespace cryptonote
}
break;
case rct::RCTTypeFull:
+ case rct::RCTTypeFullBulletproof:
if (!rct::verRct(rv, true))
{
MERROR_VER("rct signature semantics check failed");
@@ -1329,6 +1347,7 @@ namespace cryptonote
<< "where <level> is between 0 (no details) and 4 (very verbose), or custom category based levels (eg, *:WARNING)" << ENDL
<< ENDL
<< "Use the \"help\" command to see the list of available commands." << ENDL
+ << "Use \"help <command>\" to see a command's documentation." << ENDL
<< "**********************************************************************" << ENDL);
m_starter_message_showed = true;
}
diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp
index feefc1592..4afa669fd 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.cpp
+++ b/src/cryptonote_core/cryptonote_tx_utils.cpp
@@ -160,7 +160,7 @@ namespace cryptonote
return destinations[0].addr.m_view_public_key;
}
//---------------------------------------------------------------
- bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct)
+ bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct, bool bulletproof)
{
std::vector<rct::key> amount_keys;
tx.set_null();
@@ -281,7 +281,7 @@ namespace cryptonote
std::sort(ins_order.begin(), ins_order.end(), [&](const size_t i0, const size_t i1) {
const txin_to_key &tk0 = boost::get<txin_to_key>(tx.vin[i0]);
const txin_to_key &tk1 = boost::get<txin_to_key>(tx.vin[i1]);
- return memcmp(&tk0.k_image, &tk1.k_image, sizeof(tk0.k_image)) < 0;
+ return memcmp(&tk0.k_image, &tk1.k_image, sizeof(tk0.k_image)) > 0;
});
tools::apply_permutation(ins_order, [&] (size_t i0, size_t i1) {
std::swap(tx.vin[i0], tx.vin[i1]);
@@ -552,9 +552,9 @@ namespace cryptonote
get_transaction_prefix_hash(tx, tx_prefix_hash);
rct::ctkeyV outSk;
if (use_simple_rct)
- tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, index, outSk);
+ tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, index, outSk, bulletproof);
else
- tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, amount_keys, sources[0].real_output, outSk); // same index assumption
+ tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, amount_keys, sources[0].real_output, outSk, bulletproof); // same index assumption
CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout");
diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h
index 8d9a1e332..d72f5d13b 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.h
+++ b/src/cryptonote_core/cryptonote_tx_utils.h
@@ -88,7 +88,7 @@ namespace cryptonote
//---------------------------------------------------------------
crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const account_keys &sender_keys);
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time);
- bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false);
+ bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, bool bulletproof = false);
bool generate_genesis_block(
block& bl