From a0d80b1f95cee64edfeba799f4fe9b8fb2ef4f43 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 17 Dec 2020 11:57:53 +0000 Subject: plug bulletproofs plus into consensus --- src/cryptonote_core/blockchain.cpp | 35 +++++++++++++++++++++++++++++---- src/cryptonote_core/cryptonote_core.cpp | 23 +++++++++++++++++++++- 2 files changed, 53 insertions(+), 5 deletions(-) (limited to 'src/cryptonote_core') diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 34031fb7c..cd9972d1e 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -3143,6 +3143,32 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context } } + // from v15, allow bulletproofs plus + if (hf_version < HF_VERSION_BULLETPROOF_PLUS) { + if (tx.version >= 2) { + const bool bulletproof_plus = rct::is_rct_bulletproof_plus(tx.rct_signatures.type); + if (bulletproof_plus || !tx.rct_signatures.p.bulletproofs_plus.empty()) + { + MERROR_VER("Bulletproofs plus are not allowed before v" << std::to_string(HF_VERSION_BULLETPROOF_PLUS)); + tvc.m_invalid_output = true; + return false; + } + } + } + + // from v16, forbid bulletproofs + if (hf_version > HF_VERSION_BULLETPROOF_PLUS) { + if (tx.version >= 2) { + const bool bulletproof = rct::is_rct_bulletproof(tx.rct_signatures.type); + if (bulletproof) + { + MERROR_VER("Bulletproof range proofs are not allowed after v" + std::to_string(HF_VERSION_BULLETPROOF_PLUS)); + tvc.m_invalid_output = true; + return false; + } + } + } + return true; } //------------------------------------------------------------------ @@ -3183,7 +3209,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr } } } - else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2 || rv.type == rct::RCTTypeCLSAG) + else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2 || rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus) { CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys"); rv.mixRing.resize(pubkeys.size()); @@ -3224,7 +3250,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr } } } - else if (rv.type == rct::RCTTypeCLSAG) + else if (rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus) { if (!tx.pruned) { @@ -3516,6 +3542,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, case rct::RCTTypeBulletproof: case rct::RCTTypeBulletproof2: case rct::RCTTypeCLSAG: + case rct::RCTTypeBulletproofPlus: { // check all this, either reconstructed (so should really pass), or not { @@ -3551,7 +3578,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, } } - const size_t n_sigs = rv.type == rct::RCTTypeCLSAG ? rv.p.CLSAGs.size() : rv.p.MGs.size(); + const size_t n_sigs = rct::is_rct_clsag(rv.type) ? rv.p.CLSAGs.size() : rv.p.MGs.size(); if (n_sigs != tx.vin.size()) { MERROR_VER("Failed to check ringct signatures: mismatched MGs/vin sizes"); @@ -3560,7 +3587,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, for (size_t n = 0; n < tx.vin.size(); ++n) { bool error; - if (rv.type == rct::RCTTypeCLSAG) + if (rct::is_rct_clsag(rv.type)) error = memcmp(&boost::get(tx.vin[n]).k_image, &rv.p.CLSAGs[n].I, 32); else error = rv.p.MGs[n].II.empty() || memcmp(&boost::get(tx.vin[n]).k_image, &rv.p.MGs[n].II[0], 32); diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 4c6536318..1da4e2d41 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -879,6 +879,16 @@ namespace cryptonote return true; } //----------------------------------------------------------------------------------------------- + static bool is_canonical_bulletproof_plus_layout(const std::vector &proofs) + { + if (proofs.size() != 1) + return false; + const size_t sz = proofs[0].V.size(); + if (sz == 0 || sz > BULLETPROOF_PLUS_MAX_OUTPUTS) + return false; + return true; + } + //----------------------------------------------------------------------------------------------- bool core::handle_incoming_tx_accumulated_batch(std::vector &tx_info, bool keeped_by_block) { bool ret = true; @@ -943,6 +953,17 @@ namespace cryptonote } rvv.push_back(&rv); // delayed batch verification break; + case rct::RCTTypeBulletproofPlus: + if (!is_canonical_bulletproof_plus_layout(rv.p.bulletproofs_plus)) + { + MERROR_VER("Bulletproof_plus does not have canonical form"); + set_semantics_failed(tx_info[n].tx_hash); + tx_info[n].tvc.m_verifivation_failed = true; + tx_info[n].result = false; + break; + } + rvv.push_back(&rv); // delayed batch verification + break; default: MERROR_VER("Unknown rct type: " << rv.type); set_semantics_failed(tx_info[n].tx_hash); @@ -960,7 +981,7 @@ namespace cryptonote { if (!tx_info[n].result) continue; - if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof2 && tx_info[n].tx->rct_signatures.type != rct::RCTTypeCLSAG) + if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof2 && tx_info[n].tx->rct_signatures.type != rct::RCTTypeCLSAG && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproofPlus) continue; if (assumed_bad || !rct::verRctSemanticsSimple(tx_info[n].tx->rct_signatures)) { -- cgit v1.2.3