aboutsummaryrefslogtreecommitdiff
path: root/tests/core_tests
diff options
context:
space:
mode:
authorAlexander Blair <snipa@jagtech.io>2020-08-27 12:03:18 -0700
committerAlexander Blair <snipa@jagtech.io>2020-08-27 12:03:24 -0700
commit39a087406d20e2d2df6e9b66037a1271daef0592 (patch)
treef988a1e1a85cfc2f5db3412315619b61d7746a15 /tests/core_tests
parentMerge pull request #6771 (diff)
parentdraft support of clsag (diff)
downloadmonero-39a087406d20e2d2df6e9b66037a1271daef0592.tar.xz
Merge pull request #6739
1660fe8a2 draft support of clsag (cslashm) 703944c4d CLSAG device support (Sarang Noether) aff87b5f6 Added balance check to MLSAG/CLSAG performance tests (Sarang Noether) f964a92c5 Updated MLSAG and CLSAG tests for consistency (Sarang Noether) 5aa1575e9 CLSAG verification performance test (Sarang Noether) 641b08c92 CLSAG optimizations (Sarang Noether) 82ee01699 Integrate CLSAGs into monero (moneromooo-monero) 8cd1d6df8 unit_tests: add ge_triple_scalarmult_base_vartime test (moneromooo-monero) 4b328c661 CLSAG signatures (Sarang Noether)
Diffstat (limited to 'tests/core_tests')
-rw-r--r--tests/core_tests/CMakeLists.txt2
-rw-r--r--tests/core_tests/bulletproofs.cpp68
-rw-r--r--tests/core_tests/bulletproofs.h56
-rw-r--r--tests/core_tests/chaingen_main.cpp6
-rw-r--r--tests/core_tests/chaingen_tests_list.h1
-rw-r--r--tests/core_tests/multisig.cpp68
-rw-r--r--tests/core_tests/multisig.h2
-rw-r--r--tests/core_tests/rct.cpp2
-rw-r--r--tests/core_tests/rct2.cpp224
-rw-r--r--tests/core_tests/rct2.h116
10 files changed, 466 insertions, 79 deletions
diff --git a/tests/core_tests/CMakeLists.txt b/tests/core_tests/CMakeLists.txt
index ca9a09d82..654233d03 100644
--- a/tests/core_tests/CMakeLists.txt
+++ b/tests/core_tests/CMakeLists.txt
@@ -44,6 +44,7 @@ set(core_tests_sources
v2_tests.cpp
rct.cpp
bulletproofs.cpp
+ rct2.cpp
wallet_tools.cpp)
set(core_tests_headers
@@ -64,6 +65,7 @@ set(core_tests_headers
v2_tests.h
rct.h
bulletproofs.h
+ rct2.h
wallet_tools.h)
add_executable(core_tests
diff --git a/tests/core_tests/bulletproofs.cpp b/tests/core_tests/bulletproofs.cpp
index 04eeb9e01..44adc42e7 100644
--- a/tests/core_tests/bulletproofs.cpp
+++ b/tests/core_tests/bulletproofs.cpp
@@ -42,7 +42,7 @@ using namespace cryptonote;
// Tests
bool gen_bp_tx_validation_base::generate_with(std::vector<test_event_entry>& events,
- size_t mixin, size_t n_txes, const uint64_t *amounts_paid, bool valid, const rct::RCTConfig *rct_config,
+ size_t mixin, size_t n_txes, const uint64_t *amounts_paid, bool valid, const rct::RCTConfig *rct_config, uint8_t hf_version,
const std::function<bool(std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations, size_t tx_idx)> &pre_tx,
const std::function<bool(transaction &tx, size_t tx_idx)> &post_tx) const
{
@@ -157,7 +157,7 @@ bool gen_bp_tx_validation_base::generate_with(std::vector<test_event_entry>& eve
crypto::derivation_to_scalar(derivation, o, amount_key);
rct::key rct_tx_mask;
const uint8_t type = rct_txes.back().rct_signatures.type;
- if (type == rct::RCTTypeSimple || type == rct::RCTTypeBulletproof || type == rct::RCTTypeBulletproof2)
+ if (type == rct::RCTTypeSimple || type == rct::RCTTypeBulletproof || type == rct::RCTTypeBulletproof2 || type == rct::RCTTypeCLSAG)
rct::decodeRctSimple(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default"));
else
rct::decodeRct(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default"));
@@ -173,7 +173,7 @@ bool gen_bp_tx_validation_base::generate_with(std::vector<test_event_entry>& eve
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk_txes, blk_last, miner_account,
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_tx_hashes | test_generator::bf_hf_version | test_generator::bf_max_outs,
- 10, 10, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
+ hf_version, hf_version, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
crypto::hash(), 0, transaction(), starting_rct_tx_hashes, 0, 6, 10),
false, "Failed to generate block");
if (!valid)
@@ -205,13 +205,22 @@ bool gen_bp_tx_validation_base::check_bp(const cryptonote::transaction &tx, size
return true;
}
-bool gen_bp_tx_valid_1::generate(std::vector<test_event_entry>& events) const
+bool gen_bp_tx_valid_1_before_12::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 10;
const uint64_t amounts_paid[] = {10000, (uint64_t)-1};
const size_t bp_sizes[] = {1, (size_t)-1};
- const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 0 } };
- return generate_with(events, mixin, 1, amounts_paid, true, rct_config, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_1"); });
+ const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 2 } };
+ return generate_with(events, mixin, 1, amounts_paid, true, rct_config, 11, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_1_before_12"); });
+}
+
+bool gen_bp_tx_invalid_1_from_12::generate(std::vector<test_event_entry>& events) const
+{
+ const size_t mixin = 10;
+ const uint64_t amounts_paid[] = {10000, (uint64_t)-1};
+ const size_t bp_sizes[] = {1, (size_t)-1};
+ const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 2 } };
+ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, 12, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_invalid_1_from_12"); });
}
bool gen_bp_tx_invalid_1_1::generate(std::vector<test_event_entry>& events) const
@@ -219,7 +228,7 @@ bool gen_bp_tx_invalid_1_1::generate(std::vector<test_event_entry>& events) cons
const size_t mixin = 10;
const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1};
const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof , 0 } };
- return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, NULL);
+ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, NULL);
}
bool gen_bp_tx_valid_2::generate(std::vector<test_event_entry>& events) const
@@ -228,7 +237,7 @@ bool gen_bp_tx_valid_2::generate(std::vector<test_event_entry>& events) const
const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1};
const size_t bp_sizes[] = {2, (size_t)-1};
const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 0 } };
- return generate_with(events, mixin, 1, amounts_paid, true, rct_config, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_2"); });
+ return generate_with(events, mixin, 1, amounts_paid, true, rct_config, HF_VERSION_CLSAG, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_2"); });
}
bool gen_bp_tx_valid_3::generate(std::vector<test_event_entry>& events) const
@@ -237,7 +246,7 @@ bool gen_bp_tx_valid_3::generate(std::vector<test_event_entry>& events) const
const uint64_t amounts_paid[] = {5000, 5000, 5000, (uint64_t)-1};
const size_t bp_sizes[] = {4, (size_t)-1};
const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof , 0 } };
- return generate_with(events, mixin, 1, amounts_paid, true, rct_config, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_3"); });
+ return generate_with(events, mixin, 1, amounts_paid, true, rct_config, HF_VERSION_CLSAG, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_3"); });
}
bool gen_bp_tx_valid_16::generate(std::vector<test_event_entry>& events) const
@@ -246,7 +255,7 @@ bool gen_bp_tx_valid_16::generate(std::vector<test_event_entry>& events) const
const uint64_t amounts_paid[] = {500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, (uint64_t)-1};
const size_t bp_sizes[] = {16, (size_t)-1};
const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof , 0 } };
- return generate_with(events, mixin, 1, amounts_paid, true, rct_config, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_16"); });
+ return generate_with(events, mixin, 1, amounts_paid, true, rct_config, HF_VERSION_CLSAG, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_tx_valid_16"); });
}
bool gen_bp_tx_invalid_4_2_1::generate(std::vector<test_event_entry>& events) const
@@ -254,7 +263,7 @@ bool gen_bp_tx_invalid_4_2_1::generate(std::vector<test_event_entry>& events) co
const size_t mixin = 10;
const uint64_t amounts_paid[] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1};
const rct::RCTConfig rct_config[] = { { rct::RangeProofMultiOutputBulletproof , 0 } };
- return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, NULL);
+ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, NULL);
}
bool gen_bp_tx_invalid_16_16::generate(std::vector<test_event_entry>& events) const
@@ -262,7 +271,7 @@ bool gen_bp_tx_invalid_16_16::generate(std::vector<test_event_entry>& events) co
const size_t mixin = 10;
const uint64_t amounts_paid[] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1};
const rct::RCTConfig rct_config[] = { { rct::RangeProofMultiOutputBulletproof , 0 } };
- return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, NULL);
+ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, NULL);
}
bool gen_bp_txs_valid_2_and_2::generate(std::vector<test_event_entry>& events) const
@@ -271,7 +280,7 @@ bool gen_bp_txs_valid_2_and_2::generate(std::vector<test_event_entry>& events) c
const uint64_t amounts_paid[] = {1000, 1000, (size_t)-1, 1000, 1000, (uint64_t)-1};
const size_t bp_sizes[] = {2, (size_t)-1, 2, (size_t)-1};
const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 0 }, {rct::RangeProofPaddedBulletproof, 0 } };
- return generate_with(events, mixin, 2, amounts_paid, true, rct_config, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_txs_valid_2_and_2"); });
+ return generate_with(events, mixin, 2, amounts_paid, true, rct_config, HF_VERSION_CLSAG, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx){ return check_bp(tx, tx_idx, bp_sizes, "gen_bp_txs_valid_2_and_2"); });
}
bool gen_bp_txs_invalid_2_and_8_2_and_16_16_1::generate(std::vector<test_event_entry>& events) const
@@ -279,7 +288,7 @@ bool gen_bp_txs_invalid_2_and_8_2_and_16_16_1::generate(std::vector<test_event_e
const size_t mixin = 10;
const uint64_t amounts_paid[] = {1000, 1000, (uint64_t)-1, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, (uint64_t)-1};
const rct::RCTConfig rct_config[] = {{rct::RangeProofMultiOutputBulletproof, 0}, {rct::RangeProofMultiOutputBulletproof, 0}, {rct::RangeProofMultiOutputBulletproof, 0}};
- return generate_with(events, mixin, 3, amounts_paid, false, rct_config, NULL, NULL);
+ return generate_with(events, mixin, 3, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, NULL);
}
bool gen_bp_txs_valid_2_and_3_and_2_and_4::generate(std::vector<test_event_entry>& events) const
@@ -288,7 +297,7 @@ bool gen_bp_txs_valid_2_and_3_and_2_and_4::generate(std::vector<test_event_entry
const uint64_t amounts_paid[] = {11111115000, 11111115000, (uint64_t)-1, 11111115000, 11111115000, 11111115001, (uint64_t)-1, 11111115000, 11111115002, (uint64_t)-1, 11111115000, 11111115000, 11111115000, 11111115003, (uint64_t)-1};
const rct::RCTConfig rct_config[] = {{rct::RangeProofPaddedBulletproof, 0}, {rct::RangeProofPaddedBulletproof, 0}, {rct::RangeProofPaddedBulletproof, 0}, {rct::RangeProofPaddedBulletproof, 0}};
const size_t bp_sizes[] = {2, (size_t)-1, 4, (size_t)-1, 2, (size_t)-1, 4, (size_t)-1};
- return generate_with(events, mixin, 4, amounts_paid, true, rct_config, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx) { return check_bp(tx, tx_idx, bp_sizes, "gen_bp_txs_valid_2_and_3_and_2_and_4"); });
+ return generate_with(events, mixin, 4, amounts_paid, true, rct_config, HF_VERSION_CLSAG, NULL, [&](const cryptonote::transaction &tx, size_t tx_idx) { return check_bp(tx, tx_idx, bp_sizes, "gen_bp_txs_valid_2_and_3_and_2_and_4"); });
}
bool gen_bp_tx_invalid_not_enough_proofs::generate(std::vector<test_event_entry>& events) const
@@ -297,8 +306,8 @@ bool gen_bp_tx_invalid_not_enough_proofs::generate(std::vector<test_event_entry>
const size_t mixin = 10;
const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1};
const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 0 } };
- return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, [&](cryptonote::transaction &tx, size_t idx){
- CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2);
+ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, [&](cryptonote::transaction &tx, size_t idx){
+ CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG);
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs.empty());
tx.rct_signatures.p.bulletproofs.pop_back();
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs.empty());
@@ -312,8 +321,8 @@ bool gen_bp_tx_invalid_empty_proofs::generate(std::vector<test_event_entry>& eve
const size_t mixin = 10;
const uint64_t amounts_paid[] = {50000, 50000, (uint64_t)-1};
const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 0 } };
- return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, [&](cryptonote::transaction &tx, size_t idx){
- CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2);
+ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, [&](cryptonote::transaction &tx, size_t idx){
+ CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG);
tx.rct_signatures.p.bulletproofs.clear();
return true;
});
@@ -325,8 +334,8 @@ bool gen_bp_tx_invalid_too_many_proofs::generate(std::vector<test_event_entry>&
const size_t mixin = 10;
const uint64_t amounts_paid[] = {10000, (uint64_t)-1};
const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 0 } };
- return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, [&](cryptonote::transaction &tx, size_t idx){
- CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2);
+ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, [&](cryptonote::transaction &tx, size_t idx){
+ CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG);
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs.empty());
tx.rct_signatures.p.bulletproofs.push_back(tx.rct_signatures.p.bulletproofs.back());
return true;
@@ -339,8 +348,8 @@ bool gen_bp_tx_invalid_wrong_amount::generate(std::vector<test_event_entry>& eve
const size_t mixin = 10;
const uint64_t amounts_paid[] = {10000, (uint64_t)-1};
const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 0 } };
- return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, [&](cryptonote::transaction &tx, size_t idx){
- CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2);
+ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG, NULL, [&](cryptonote::transaction &tx, size_t idx){
+ CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproof || tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG);
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs.empty());
tx.rct_signatures.p.bulletproofs.back() = rct::bulletproof_PROVE(1000, rct::skGen());
return true;
@@ -353,7 +362,18 @@ bool gen_bp_tx_invalid_borromean_type::generate(std::vector<test_event_entry>& e
const size_t mixin = 10;
const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1};
const rct::RCTConfig rct_config[] = { { rct::RangeProofBorromean, 0 } };
- return generate_with(events, mixin, 1, amounts_paid, false, rct_config, NULL, [&](cryptonote::transaction &tx, size_t tx_idx){
+ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, 11, NULL, [&](cryptonote::transaction &tx, size_t tx_idx){
+ return true;
+ });
+}
+
+bool gen_bp_tx_invalid_bulletproof2_type::generate(std::vector<test_event_entry>& events) const
+{
+ DEFINE_TESTS_ERROR_CONTEXT("gen_bp_tx_invalid_bulletproof2_type");
+ const size_t mixin = 10;
+ const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1};
+ const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 2 } };
+ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG + 1, NULL, [&](cryptonote::transaction &tx, size_t tx_idx){
return true;
});
}
diff --git a/tests/core_tests/bulletproofs.h b/tests/core_tests/bulletproofs.h
index 93fe2947f..b30d82e68 100644
--- a/tests/core_tests/bulletproofs.h
+++ b/tests/core_tests/bulletproofs.h
@@ -82,7 +82,7 @@ struct gen_bp_tx_validation_base : public test_chain_unit_base
}
bool generate_with(std::vector<test_event_entry>& events, size_t mixin,
- size_t n_txes, const uint64_t *amounts_paid, bool valid, const rct::RCTConfig *rct_config,
+ size_t n_txes, const uint64_t *amounts_paid, bool valid, const rct::RCTConfig *rct_config, uint8_t hf_version,
const std::function<bool(std::vector<cryptonote::tx_source_entry> &sources, std::vector<cryptonote::tx_destination_entry> &destinations, size_t)> &pre_tx,
const std::function<bool(cryptonote::transaction &tx, size_t)> &post_tx) const;
@@ -95,99 +95,119 @@ private:
template<>
struct get_test_options<gen_bp_tx_validation_base> {
- const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(10, 73), std::make_pair(0, 0)};
+ const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(12, 73), std::make_pair(0, 0)};
+ const cryptonote::test_options test_options = {
+ hard_forks, 0
+ };
+};
+
+template<uint8_t test_version = HF_VERSION_CLSAG>
+struct get_bp_versioned_test_options: public get_test_options<gen_bp_tx_validation_base> {
+ const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(test_version, 73), std::make_pair(0, 0)};
const cryptonote::test_options test_options = {
hard_forks, 0
};
};
// valid
-struct gen_bp_tx_valid_1 : public gen_bp_tx_validation_base
+struct gen_bp_tx_valid_1_before_12 : public gen_bp_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
-template<> struct get_test_options<gen_bp_tx_valid_1>: public get_test_options<gen_bp_tx_validation_base> {};
+template<> struct get_test_options<gen_bp_tx_valid_1_before_12>: public get_bp_versioned_test_options<11> {};
+
+struct gen_bp_tx_invalid_1_from_12 : public gen_bp_tx_validation_base
+{
+ bool generate(std::vector<test_event_entry>& events) const;
+};
+template<> struct get_test_options<gen_bp_tx_invalid_1_from_12>: public get_bp_versioned_test_options<12> {};
struct gen_bp_tx_invalid_1_1 : public gen_bp_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
-template<> struct get_test_options<gen_bp_tx_invalid_1_1>: public get_test_options<gen_bp_tx_validation_base> {};
+template<> struct get_test_options<gen_bp_tx_invalid_1_1>: public get_bp_versioned_test_options<HF_VERSION_CLSAG> {};
struct gen_bp_tx_valid_2 : public gen_bp_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
-template<> struct get_test_options<gen_bp_tx_valid_2>: public get_test_options<gen_bp_tx_validation_base> {};
+template<> struct get_test_options<gen_bp_tx_valid_2>: public get_bp_versioned_test_options<HF_VERSION_CLSAG> {};
struct gen_bp_tx_valid_3 : public gen_bp_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
-template<> struct get_test_options<gen_bp_tx_valid_3>: public get_test_options<gen_bp_tx_validation_base> {};
+template<> struct get_test_options<gen_bp_tx_valid_3>: public get_bp_versioned_test_options<HF_VERSION_CLSAG> {};
struct gen_bp_tx_valid_16 : public gen_bp_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
-template<> struct get_test_options<gen_bp_tx_valid_16>: public get_test_options<gen_bp_tx_validation_base> {};
+template<> struct get_test_options<gen_bp_tx_valid_16>: public get_bp_versioned_test_options<HF_VERSION_CLSAG> {};
struct gen_bp_tx_invalid_4_2_1 : public gen_bp_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
-template<> struct get_test_options<gen_bp_tx_invalid_4_2_1>: public get_test_options<gen_bp_tx_validation_base> {};
+template<> struct get_test_options<gen_bp_tx_invalid_4_2_1>: public get_bp_versioned_test_options<HF_VERSION_CLSAG> {};
struct gen_bp_tx_invalid_16_16 : public gen_bp_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
-template<> struct get_test_options<gen_bp_tx_invalid_16_16>: public get_test_options<gen_bp_tx_validation_base> {};
+template<> struct get_test_options<gen_bp_tx_invalid_16_16>: public get_bp_versioned_test_options<HF_VERSION_CLSAG> {};
struct gen_bp_txs_valid_2_and_2 : public gen_bp_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
-template<> struct get_test_options<gen_bp_txs_valid_2_and_2>: public get_test_options<gen_bp_tx_validation_base> {};
+template<> struct get_test_options<gen_bp_txs_valid_2_and_2>: public get_bp_versioned_test_options<HF_VERSION_CLSAG> {};
struct gen_bp_txs_invalid_2_and_8_2_and_16_16_1 : public gen_bp_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
-template<> struct get_test_options<gen_bp_txs_invalid_2_and_8_2_and_16_16_1>: public get_test_options<gen_bp_tx_validation_base> {};
+template<> struct get_test_options<gen_bp_txs_invalid_2_and_8_2_and_16_16_1>: public get_bp_versioned_test_options<HF_VERSION_CLSAG> {};
struct gen_bp_txs_valid_2_and_3_and_2_and_4 : public gen_bp_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
-template<> struct get_test_options<gen_bp_txs_valid_2_and_3_and_2_and_4>: public get_test_options<gen_bp_tx_validation_base> {};
+template<> struct get_test_options<gen_bp_txs_valid_2_and_3_and_2_and_4>: public get_bp_versioned_test_options<HF_VERSION_CLSAG> {};
struct gen_bp_tx_invalid_not_enough_proofs : public gen_bp_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
-template<> struct get_test_options<gen_bp_tx_invalid_not_enough_proofs>: public get_test_options<gen_bp_tx_validation_base> {};
+template<> struct get_test_options<gen_bp_tx_invalid_not_enough_proofs>: public get_bp_versioned_test_options<HF_VERSION_CLSAG> {};
struct gen_bp_tx_invalid_empty_proofs : public gen_bp_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
-template<> struct get_test_options<gen_bp_tx_invalid_empty_proofs>: public get_test_options<gen_bp_tx_validation_base> {};
+template<> struct get_test_options<gen_bp_tx_invalid_empty_proofs>: public get_bp_versioned_test_options<HF_VERSION_CLSAG> {};
struct gen_bp_tx_invalid_too_many_proofs : public gen_bp_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
-template<> struct get_test_options<gen_bp_tx_invalid_too_many_proofs>: public get_test_options<gen_bp_tx_validation_base> {};
+template<> struct get_test_options<gen_bp_tx_invalid_too_many_proofs>: public get_bp_versioned_test_options<HF_VERSION_CLSAG> {};
struct gen_bp_tx_invalid_wrong_amount : public gen_bp_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
-template<> struct get_test_options<gen_bp_tx_invalid_wrong_amount>: public get_test_options<gen_bp_tx_validation_base> {};
+template<> struct get_test_options<gen_bp_tx_invalid_wrong_amount>: public get_bp_versioned_test_options<HF_VERSION_CLSAG> {};
struct gen_bp_tx_invalid_borromean_type : public gen_bp_tx_validation_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
-template<> struct get_test_options<gen_bp_tx_invalid_borromean_type>: public get_test_options<gen_bp_tx_validation_base> {};
+template<> struct get_test_options<gen_bp_tx_invalid_borromean_type>: public get_bp_versioned_test_options<9> {};
+
+struct gen_bp_tx_invalid_bulletproof2_type : public gen_bp_tx_validation_base
+{
+ bool generate(std::vector<test_event_entry>& events) const;
+};
+template<> struct get_test_options<gen_bp_tx_invalid_bulletproof2_type>: public get_bp_versioned_test_options<HF_VERSION_CLSAG + 1> {};
diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp
index 9895d4814..c55154917 100644
--- a/tests/core_tests/chaingen_main.cpp
+++ b/tests/core_tests/chaingen_main.cpp
@@ -248,7 +248,8 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(gen_multisig_tx_invalid_48_1_no_signers);
GENERATE_AND_PLAY(gen_multisig_tx_invalid_48_1_23_no_threshold);
- GENERATE_AND_PLAY(gen_bp_tx_valid_1);
+ GENERATE_AND_PLAY(gen_bp_tx_valid_1_before_12);
+ GENERATE_AND_PLAY(gen_bp_tx_invalid_1_from_12);
GENERATE_AND_PLAY(gen_bp_tx_invalid_1_1);
GENERATE_AND_PLAY(gen_bp_tx_valid_2);
GENERATE_AND_PLAY(gen_bp_tx_valid_3);
@@ -263,6 +264,9 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(gen_bp_tx_invalid_too_many_proofs);
GENERATE_AND_PLAY(gen_bp_tx_invalid_wrong_amount);
GENERATE_AND_PLAY(gen_bp_tx_invalid_borromean_type);
+ GENERATE_AND_PLAY(gen_bp_tx_invalid_bulletproof2_type);
+
+ GENERATE_AND_PLAY(gen_rct2_tx_clsag_malleability);
GENERATE_AND_PLAY(gen_block_low_coinbase);
diff --git a/tests/core_tests/chaingen_tests_list.h b/tests/core_tests/chaingen_tests_list.h
index 94eb23ce9..db78c3e41 100644
--- a/tests/core_tests/chaingen_tests_list.h
+++ b/tests/core_tests/chaingen_tests_list.h
@@ -43,6 +43,7 @@
#include "rct.h"
#include "multisig.h"
#include "bulletproofs.h"
+#include "rct2.h"
/************************************************************************/
/* */
/************************************************************************/
diff --git a/tests/core_tests/multisig.cpp b/tests/core_tests/multisig.cpp
index 28d43e815..f098e1bce 100644
--- a/tests/core_tests/multisig.cpp
+++ b/tests/core_tests/multisig.cpp
@@ -163,9 +163,9 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
MAKE_GENESIS_BLOCK(events, blk_0, miner_account[creator], ts_start);
- // create 8 miner accounts, and have them mine the next 8 blocks
+ // create 16 miner accounts, and have them mine the next 16 blocks
// they will have a coinbase with a single out that's pseudo rct
- constexpr size_t n_coinbases = 8;
+ constexpr size_t n_coinbases = 16;
cryptonote::account_base miner_accounts[n_coinbases];
const cryptonote::block *prev_block = &blk_0;
cryptonote::block blocks[n_coinbases];
@@ -175,7 +175,7 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
account_base &account = n < inputs ? miner_account[creator] : miner_accounts[n];
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blocks[n], *prev_block, account,
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version | test_generator::bf_max_outs,
- 4, 4, prev_block->timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
+ 10, 10, prev_block->timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 1, 4),
false, "Failed to generate block");
events.push_back(blocks[n]);
@@ -191,7 +191,7 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
cryptonote::block blk;
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk, blk_last, miner_accounts[0],
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version | test_generator::bf_max_outs,
- 4, 4, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
+ 10, 10, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 1, 4),
false, "Failed to generate block");
events.push_back(blk);
@@ -363,7 +363,7 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
#endif
std::vector<crypto::secret_key> additional_tx_secret_keys;
auto sources_copy = sources;
- r = construct_tx_and_get_tx_key(miner_account[creator].get_keys(), subaddresses, sources, destinations, boost::none, std::vector<uint8_t>(), tx, 0, tx_key, additional_tx_secret_keys, true, { rct::RangeProofBorromean, 0 }, msoutp);
+ r = construct_tx_and_get_tx_key(miner_account[creator].get_keys(), subaddresses, sources, destinations, boost::none, std::vector<uint8_t>(), tx, 0, tx_key, additional_tx_secret_keys, true, { rct::RangeProofPaddedBulletproof, 2 }, msoutp);
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
#ifndef NO_MULTISIG
@@ -453,7 +453,7 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
crypto::secret_key scalar1;
crypto::derivation_to_scalar(derivation, n, scalar1);
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n];
- rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2);
+ rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG);
rct::key C = tx.rct_signatures.outPk[n].mask;
rct::addKeys2(Ctmp, ecdh_info.mask, ecdh_info.amount, rct::H);
CHECK_AND_ASSERT_MES(rct::equalKeys(C, Ctmp), false, "Failed to decode amount");
@@ -476,196 +476,196 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
bool gen_multisig_tx_valid_22_1_2::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 2, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_valid_22_1_2_many_inputs::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 4, mixin, amount_paid, true, 2, 2, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_valid_22_2_1::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 2, 2, {1}, NULL, NULL);
}
bool gen_multisig_tx_valid_33_1_23::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 3, 3, 1, {2, 3}, NULL, NULL);
}
bool gen_multisig_tx_valid_33_3_21::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 3, 3, 3, {2, 1}, NULL, NULL);
}
bool gen_multisig_tx_valid_23_1_2::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 3, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_valid_23_1_3::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 3, 1, {3}, NULL, NULL);
}
bool gen_multisig_tx_valid_23_2_1::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 3, 2, {1}, NULL, NULL);
}
bool gen_multisig_tx_valid_23_2_3::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 3, 2, {3}, NULL, NULL);
}
bool gen_multisig_tx_valid_45_1_234::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 4, 5, 1, {2, 3, 4}, NULL, NULL);
}
bool gen_multisig_tx_valid_45_4_135_many_inputs::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 4, mixin, amount_paid, true, 4, 5, 4, {1, 3, 5}, NULL, NULL);
}
bool gen_multisig_tx_valid_89_3_1245789::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 8, 9, 3, {1, 2, 4, 5, 7, 8, 9}, NULL, NULL);
}
bool gen_multisig_tx_valid_24_1_2::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 4, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_valid_24_1_2_many_inputs::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 4, mixin, amount_paid, true, 2, 4, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_valid_25_1_2::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 5, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_valid_25_1_2_many_inputs::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 4, mixin, amount_paid, true, 2, 5, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_valid_48_1_234::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 4, 8, 1, {2, 3, 4}, NULL, NULL);
}
bool gen_multisig_tx_valid_48_1_234_many_inputs::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 4, mixin, amount_paid, true, 4, 8, 1, {2, 3, 4}, NULL, NULL);
}
bool gen_multisig_tx_invalid_22_1__no_threshold::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 2, 2, 1, {}, NULL, NULL);
}
bool gen_multisig_tx_invalid_33_1__no_threshold::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 3, 3, 1, {}, NULL, NULL);
}
bool gen_multisig_tx_invalid_33_1_2_no_threshold::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 3, 3, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_invalid_33_1_3_no_threshold::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 3, 3, 1, {3}, NULL, NULL);
}
bool gen_multisig_tx_invalid_23_1__no_threshold::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 2, 3, 1, {}, NULL, NULL);
}
bool gen_multisig_tx_invalid_45_5_23_no_threshold::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 4, 5, 5, {2, 3}, NULL, NULL);
}
bool gen_multisig_tx_invalid_24_1_no_signers::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 2, 4, 1, {}, NULL, NULL);
}
bool gen_multisig_tx_invalid_25_1_no_signers::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 2, 5, 1, {}, NULL, NULL);
}
bool gen_multisig_tx_invalid_48_1_no_signers::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 4, 8, 1, {}, NULL, NULL);
}
bool gen_multisig_tx_invalid_48_1_23_no_threshold::generate(std::vector<test_event_entry>& events) const
{
- const size_t mixin = 4;
+ const size_t mixin = 10;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 4, 8, 1, {2, 3}, NULL, NULL);
}
diff --git a/tests/core_tests/multisig.h b/tests/core_tests/multisig.h
index 462c74f46..333c4fe38 100644
--- a/tests/core_tests/multisig.h
+++ b/tests/core_tests/multisig.h
@@ -82,7 +82,7 @@ private:
template<>
struct get_test_options<gen_multisig_tx_validation_base> {
- const std::pair<uint8_t, uint64_t> hard_forks[3] = {std::make_pair(1, 0), std::make_pair(4, 1), std::make_pair(0, 0)};
+ const std::pair<uint8_t, uint64_t> hard_forks[3] = {std::make_pair(1, 0), std::make_pair(10, 1), std::make_pair(0, 0)};
const cryptonote::test_options test_options = {
hard_forks, 0
};
diff --git a/tests/core_tests/rct.cpp b/tests/core_tests/rct.cpp
index 6bf708855..6ce99e76e 100644
--- a/tests/core_tests/rct.cpp
+++ b/tests/core_tests/rct.cpp
@@ -133,7 +133,7 @@ bool gen_rct_tx_validation_base::generate_with_full(std::vector<test_event_entry
crypto::secret_key amount_key;
crypto::derivation_to_scalar(derivation, o, amount_key);
const uint8_t type = rct_txes[n].rct_signatures.type;
- if (type == rct::RCTTypeSimple || type == rct::RCTTypeBulletproof || type == rct::RCTTypeBulletproof2)
+ if (type == rct::RCTTypeSimple || type == rct::RCTTypeBulletproof || type == rct::RCTTypeBulletproof2 || type == rct::RCTTypeCLSAG)
rct::decodeRctSimple(rct_txes[n].rct_signatures, rct::sk2rct(amount_key), o, rct_tx_masks[o+n*4], hw::get_device("default"));
else
rct::decodeRct(rct_txes[n].rct_signatures, rct::sk2rct(amount_key), o, rct_tx_masks[o+n*4], hw::get_device("default"));
diff --git a/tests/core_tests/rct2.cpp b/tests/core_tests/rct2.cpp
new file mode 100644
index 000000000..55d700429
--- /dev/null
+++ b/tests/core_tests/rct2.cpp
@@ -0,0 +1,224 @@
+// Copyright (c) 2014-2019, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#include "ringct/rctSigs.h"
+#include "ringct/bulletproofs.h"
+#include "chaingen.h"
+#include "rct2.h"
+#include "device/device.hpp"
+
+using namespace epee;
+using namespace crypto;
+using namespace cryptonote;
+
+//----------------------------------------------------------------------------------------------------------------------
+// Tests
+
+bool gen_rct2_tx_validation_base::generate_with(std::vector<test_event_entry>& events,
+ size_t mixin, size_t n_txes, const uint64_t *amounts_paid, bool valid, const rct::RCTConfig *rct_config, uint8_t hf_version,
+ const std::function<bool(std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations, size_t tx_idx)> &pre_tx,
+ const std::function<bool(transaction &tx, size_t tx_idx)> &post_tx) const
+{
+ uint64_t ts_start = 1338224400;
+
+ GENERATE_ACCOUNT(miner_account);
+ MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
+
+ // create 12 miner accounts, and have them mine the next 12 blocks
+ cryptonote::account_base miner_accounts[12];
+ const cryptonote::block *prev_block = &blk_0;
+ cryptonote::block blocks[12 + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW];
+ for (size_t n = 0; n < 12; ++n) {
+ miner_accounts[n].generate();
+ CHECK_AND_ASSERT_MES(generator.construct_block_manually(blocks[n], *prev_block, miner_accounts[n],
+ test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version,
+ 2, 2, prev_block->timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
+ crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 0, 2),
+ false, "Failed to generate block");
+ events.push_back(blocks[n]);
+ prev_block = blocks + n;
+ LOG_PRINT_L0("Initial miner tx " << n << ": " << obj_to_json_str(blocks[n].miner_tx));
+ }
+
+ // rewind
+ cryptonote::block blk_r, blk_last;
+ {
+ blk_last = blocks[11];
+ for (size_t i = 0; i < CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW; ++i)
+ {
+ CHECK_AND_ASSERT_MES(generator.construct_block_manually(blocks[12+i], blk_last, miner_account,
+ test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version,
+ 2, 2, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
+ crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 0, 2),
+ false, "Failed to generate block");
+ events.push_back(blocks[12+i]);
+ blk_last = blocks[12+i];
+ }
+ blk_r = blk_last;
+ }
+
+ // create 4 txes from these miners in another block, to generate some rct outputs
+ std::vector<transaction> rct_txes;
+ cryptonote::block blk_txes;
+ std::vector<crypto::hash> starting_rct_tx_hashes;
+ static const uint64_t input_amounts_available[] = {5000000000000, 30000000000000, 100000000000, 80000000000};
+ for (size_t n = 0; n < n_txes; ++n)
+ {
+ std::vector<tx_source_entry> sources;
+
+ sources.resize(1);
+ tx_source_entry& src = sources.back();
+
+ const uint64_t needed_amount = input_amounts_available[n];
+ src.amount = input_amounts_available[n];
+ size_t real_index_in_tx = 0;
+ for (size_t m = 0; m <= mixin; ++m) {
+ size_t index_in_tx = 0;
+ for (size_t i = 0; i < blocks[m].miner_tx.vout.size(); ++i)
+ if (blocks[m].miner_tx.vout[i].amount == needed_amount)
+ index_in_tx = i;
+ CHECK_AND_ASSERT_MES(blocks[m].miner_tx.vout[index_in_tx].amount == needed_amount, false, "Expected amount not found");
+ src.push_output(m, boost::get<txout_to_key>(blocks[m].miner_tx.vout[index_in_tx].target).key, src.amount);
+ if (m == n)
+ real_index_in_tx = index_in_tx;
+ }
+ src.real_out_tx_key = cryptonote::get_tx_pub_key_from_extra(blocks[n].miner_tx);
+ src.real_output = n;
+ src.real_output_in_tx_index = real_index_in_tx;
+ src.mask = rct::identity();
+ src.rct = false;
+
+ //fill outputs entry
+ tx_destination_entry td;
+ td.addr = miner_accounts[n].get_keys().m_account_address;
+ std::vector<tx_destination_entry> destinations;
+ for (int o = 0; amounts_paid[o] != (uint64_t)-1; ++o)
+ {
+ td.amount = amounts_paid[o];
+ destinations.push_back(td);
+ }
+
+ if (pre_tx && !pre_tx(sources, destinations, n))
+ {
+ MDEBUG("pre_tx returned failure");
+ return false;
+ }
+
+ crypto::secret_key tx_key;
+ std::vector<crypto::secret_key> additional_tx_keys;
+ std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
+ subaddresses[miner_accounts[n].get_keys().m_account_address.m_spend_public_key] = {0,0};
+ rct_txes.resize(rct_txes.size() + 1);
+ bool r = construct_tx_and_get_tx_key(miner_accounts[n].get_keys(), subaddresses, sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), rct_txes.back(), 0, tx_key, additional_tx_keys, true, rct_config[n]);
+ CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
+
+ if (post_tx && !post_tx(rct_txes.back(), n))
+ {
+ MDEBUG("post_tx returned failure");
+ return false;
+ }
+
+ //events.push_back(rct_txes.back());
+ starting_rct_tx_hashes.push_back(get_transaction_hash(rct_txes.back()));
+ LOG_PRINT_L0("Test tx: " << obj_to_json_str(rct_txes.back()));
+
+ for (int o = 0; amounts_paid[o] != (uint64_t)-1; ++o)
+ {
+ crypto::key_derivation derivation;
+ bool r = crypto::generate_key_derivation(destinations[o].addr.m_view_public_key, tx_key, derivation);
+ CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation");
+ crypto::secret_key amount_key;
+ crypto::derivation_to_scalar(derivation, o, amount_key);
+ rct::key rct_tx_mask;
+ const uint8_t type = rct_txes.back().rct_signatures.type;
+ if (type == rct::RCTTypeSimple || type == rct::RCTTypeBulletproof || type == rct::RCTTypeBulletproof2 || type == rct::RCTTypeCLSAG)
+ rct::decodeRctSimple(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default"));
+ else
+ rct::decodeRct(rct_txes.back().rct_signatures, rct::sk2rct(amount_key), o, rct_tx_mask, hw::get_device("default"));
+ }
+
+ while (amounts_paid[0] != (size_t)-1)
+ ++amounts_paid;
+ ++amounts_paid;
+ }
+ if (!valid)
+ DO_CALLBACK(events, "mark_invalid_tx");
+ events.push_back(rct_txes);
+
+ CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk_txes, blk_last, miner_account,
+ test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_tx_hashes | test_generator::bf_hf_version | test_generator::bf_max_outs,
+ hf_version, hf_version, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
+ crypto::hash(), 0, transaction(), starting_rct_tx_hashes, 0, 6, 10),
+ false, "Failed to generate block");
+ if (!valid)
+ DO_CALLBACK(events, "mark_invalid_block");
+ events.push_back(blk_txes);
+ blk_last = blk_txes;
+
+ return true;
+}
+
+bool gen_rct2_tx_validation_base::check_bp(const cryptonote::transaction &tx, size_t tx_idx, const size_t *sizes, const char *context) const
+{
+ DEFINE_TESTS_ERROR_CONTEXT(context);
+ CHECK_TEST_CONDITION(tx.version >= 2);
+ CHECK_TEST_CONDITION(rct::is_rct_bulletproof(tx.rct_signatures.type));
+ size_t n_sizes = 0, n_amounts = 0;
+ for (size_t n = 0; n < tx_idx; ++n)
+ {
+ while (sizes[0] != (size_t)-1)
+ ++sizes;
+ ++sizes;
+ }
+ while (sizes[n_sizes] != (size_t)-1)
+ n_amounts += sizes[n_sizes++];
+ CHECK_TEST_CONDITION(tx.rct_signatures.p.bulletproofs.size() == n_sizes);
+ CHECK_TEST_CONDITION(rct::n_bulletproof_max_amounts(tx.rct_signatures.p.bulletproofs) == n_amounts);
+ for (size_t n = 0; n < n_sizes; ++n)
+ CHECK_TEST_CONDITION(rct::n_bulletproof_max_amounts(tx.rct_signatures.p.bulletproofs[n]) == sizes[n]);
+ return true;
+}
+
+bool gen_rct2_tx_clsag_malleability::generate(std::vector<test_event_entry>& events) const
+{
+ DEFINE_TESTS_ERROR_CONTEXT("gen_rct_tx_clsag_malleability");
+ const int mixin = 10;
+ const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1};
+ const rct::RCTConfig rct_config[] = { { rct::RangeProofPaddedBulletproof, 3 } };
+ return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_CLSAG + 1, NULL, [&](cryptonote::transaction &tx, size_t tx_idx) {
+ CHECK_TEST_CONDITION(tx.version == 2);
+ CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeCLSAG);
+ CHECK_TEST_CONDITION(!tx.rct_signatures.p.CLSAGs.empty());
+ rct::key x;
+ CHECK_TEST_CONDITION(epee::string_tools::hex_to_pod("c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", x));
+ tx.rct_signatures.p.CLSAGs[0].D = rct::addKeys(tx.rct_signatures.p.CLSAGs[0].D, x);
+ return true;
+ });
+}
diff --git a/tests/core_tests/rct2.h b/tests/core_tests/rct2.h
new file mode 100644
index 000000000..2fe9d6113
--- /dev/null
+++ b/tests/core_tests/rct2.h
@@ -0,0 +1,116 @@
+// Copyright (c) 2014-2019, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#pragma once
+#include "chaingen.h"
+
+struct gen_rct2_tx_validation_base : public test_chain_unit_base
+{
+ gen_rct2_tx_validation_base()
+ : m_invalid_tx_index(0)
+ , m_invalid_block_index(0)
+ {
+ REGISTER_CALLBACK_METHOD(gen_rct2_tx_validation_base, mark_invalid_tx);
+ REGISTER_CALLBACK_METHOD(gen_rct2_tx_validation_base, mark_invalid_block);
+ }
+
+ bool check_tx_verification_context(const cryptonote::tx_verification_context& tvc, bool tx_added, size_t event_idx, const cryptonote::transaction& /*tx*/)
+ {
+ if (m_invalid_tx_index == event_idx)
+ return tvc.m_verifivation_failed;
+ else
+ return !tvc.m_verifivation_failed && tx_added;
+ }
+
+ bool check_tx_verification_context_array(const std::vector<cryptonote::tx_verification_context>& tvcs, size_t tx_added, size_t event_idx, const std::vector<cryptonote::transaction>& /*txs*/)
+ {
+ size_t failed = 0;
+ for (const cryptonote::tx_verification_context &tvc: tvcs)
+ if (tvc.m_verifivation_failed)
+ ++failed;
+ if (m_invalid_tx_index == event_idx)
+ return failed > 0;
+ else
+ return failed == 0 && tx_added == tvcs.size();
+ }
+
+ bool check_block_verification_context(const cryptonote::block_verification_context& bvc, size_t event_idx, const cryptonote::block& /*block*/)
+ {
+ if (m_invalid_block_index == event_idx)
+ return bvc.m_verifivation_failed;
+ else
+ return !bvc.m_verifivation_failed;
+ }
+
+ bool mark_invalid_block(cryptonote::core& /*c*/, size_t ev_index, const std::vector<test_event_entry>& /*events*/)
+ {
+ m_invalid_block_index = ev_index + 1;
+ return true;
+ }
+
+ bool mark_invalid_tx(cryptonote::core& /*c*/, size_t ev_index, const std::vector<test_event_entry>& /*events*/)
+ {
+ m_invalid_tx_index = ev_index + 1;
+ return true;
+ }
+
+ bool generate_with(std::vector<test_event_entry>& events, size_t mixin,
+ size_t n_txes, const uint64_t *amounts_paid, bool valid, const rct::RCTConfig *rct_config, uint8_t hf_version,
+ const std::function<bool(std::vector<cryptonote::tx_source_entry> &sources, std::vector<cryptonote::tx_destination_entry> &destinations, size_t)> &pre_tx,
+ const std::function<bool(cryptonote::transaction &tx, size_t)> &post_tx) const;
+
+ bool check_bp(const cryptonote::transaction &tx, size_t tx_idx, const size_t *sizes, const char *context) const;
+
+private:
+ size_t m_invalid_tx_index;
+ size_t m_invalid_block_index;
+};
+
+template<>
+struct get_test_options<gen_rct2_tx_validation_base> {
+ const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(12, 73), std::make_pair(0, 0)};
+ const cryptonote::test_options test_options = {
+ hard_forks, 0
+ };
+};
+
+template<uint8_t test_version = 12>
+struct get_rct2_versioned_test_options: public get_test_options<gen_rct2_tx_validation_base> {
+ const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(test_version, 73), std::make_pair(0, 0)};
+ const cryptonote::test_options test_options = {
+ hard_forks, 0
+ };
+};
+
+struct gen_rct2_tx_clsag_malleability : public gen_rct2_tx_validation_base
+{
+ bool generate(std::vector<test_event_entry>& events) const;
+};
+template<> struct get_test_options<gen_rct2_tx_clsag_malleability>: public get_rct2_versioned_test_options<HF_VERSION_CLSAG + 1> {};