mirror of
https://git.wownero.com/wownero/wownero.git
synced 2024-08-15 01:03:23 +00:00
Integrate CLSAGs into monero
They are allowed from v12, and MLSAGs are rejected from v13.
This commit is contained in:
parent
8cd1d6df8f
commit
82ee01699c
31 changed files with 1083 additions and 195 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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> {};
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "rct.h"
|
||||
#include "multisig.h"
|
||||
#include "bulletproofs.h"
|
||||
#include "rct2.h"
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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"));
|
||||
|
|
224
tests/core_tests/rct2.cpp
Normal file
224
tests/core_tests/rct2.cpp
Normal file
|
@ -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;
|
||||
});
|
||||
}
|
116
tests/core_tests/rct2.h
Normal file
116
tests/core_tests/rct2.h
Normal file
|
@ -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> {};
|
|
@ -135,7 +135,7 @@ class TransferTest():
|
|||
assert res.fee > 0
|
||||
fee = res.fee
|
||||
assert len(res.tx_blob) > 0
|
||||
blob_size = len(res.tx_blob) // 2
|
||||
tx_weight = res.weight
|
||||
assert len(res.tx_metadata) == 0
|
||||
assert len(res.multisig_txset) == 0
|
||||
assert len(res.unsigned_txset) == 0
|
||||
|
@ -144,7 +144,7 @@ class TransferTest():
|
|||
res = daemon.get_fee_estimate(10)
|
||||
assert res.fee > 0
|
||||
assert res.quantization_mask > 0
|
||||
expected_fee = (res.fee * 1 * blob_size + res.quantization_mask - 1) // res.quantization_mask * res.quantization_mask
|
||||
expected_fee = (res.fee * 1 * tx_weight + res.quantization_mask - 1) // res.quantization_mask * res.quantization_mask
|
||||
assert abs(1 - fee / expected_fee) < 0.01
|
||||
|
||||
self.wallet[0].refresh()
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
P[l] = rct::scalarmultBase(p);
|
||||
C[l] = rct::scalarmultBase(z);
|
||||
|
||||
sig = CLSAG_Gen(rct::identity(),P,p,C,z,l,NULL);
|
||||
sig = CLSAG_Gen(rct::identity(),P,p,C,z,l);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ public:
|
|||
if (ver)
|
||||
return CLSAG_Ver(rct::identity(),P,C,sig);
|
||||
else
|
||||
CLSAG_Gen(rct::identity(),P,p,C,z,l,NULL);
|
||||
CLSAG_Gen(rct::identity(),P,p,C,z,l);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -546,7 +546,7 @@ static void expand_tsx(cryptonote::transaction &tx)
|
|||
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 || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2)
|
||||
else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2 || rv.type == rct::RCTTypeCLSAG)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(rv.p.MGs.size() == tx.vin.size(), "Bad MGs size");
|
||||
for (size_t n = 0; n < tx.vin.size(); ++n)
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "ringct/rctSigs.h"
|
||||
#include "ringct/rctOps.h"
|
||||
#include "device/device.hpp"
|
||||
#include "string_tools.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace crypto;
|
||||
|
@ -137,6 +138,169 @@ TEST(ringct, MG_sigs)
|
|||
ASSERT_FALSE(MLSAG_Ver(message, P, IIccss, R));
|
||||
}
|
||||
|
||||
TEST(ringct, CLSAG)
|
||||
{
|
||||
const size_t ring_size = 11;
|
||||
const size_t idx = 5;
|
||||
keyV P, C;
|
||||
key p, z;
|
||||
const key message = identity();
|
||||
key backup;
|
||||
clsag clsag;
|
||||
|
||||
for (size_t i = 0; i < ring_size; ++i)
|
||||
{
|
||||
key Sk, Pk;
|
||||
skpkGen(Sk, Pk);
|
||||
P.push_back(Pk);
|
||||
skpkGen(Sk, Pk);
|
||||
C.push_back(Pk);
|
||||
}
|
||||
skpkGen(p, P[idx]);
|
||||
skpkGen(z, C[idx]);
|
||||
|
||||
// bad p at creation
|
||||
clsag = CLSAG_Gen(zero(), P, p, C, z, idx); //, hw::get_device("default"));
|
||||
ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag));
|
||||
|
||||
// bad index at creation
|
||||
try
|
||||
{
|
||||
clsag = CLSAG_Gen(message, P, p, C, z, (idx + 1) % ring_size); //, hw::get_device("default"));
|
||||
ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag));
|
||||
}
|
||||
catch (...) { /* either exception, or failure to verify above */ }
|
||||
|
||||
// bad z at creation
|
||||
try
|
||||
{
|
||||
clsag = CLSAG_Gen(message, P, p, C, skGen(), idx); //, hw::get_device("default"));
|
||||
ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag));
|
||||
}
|
||||
catch (...) { /* either exception, or failure to verify above */ }
|
||||
|
||||
// bad C at creation
|
||||
backup = C[idx];
|
||||
C[idx] = scalarmultBase(skGen());
|
||||
try
|
||||
{
|
||||
clsag = CLSAG_Gen(message, P, p, C, z, idx); //, hw::get_device("default"));
|
||||
ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag));
|
||||
}
|
||||
catch (...) { /* either exception, or failure to verify above */ }
|
||||
C[idx] = backup;
|
||||
|
||||
// bad p at creation
|
||||
try
|
||||
{
|
||||
clsag = CLSAG_Gen(message, P, skGen(), C, z, idx); //, hw::get_device("default"));
|
||||
ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag));
|
||||
}
|
||||
catch (...) { /* either exception, or failure to verify above */ }
|
||||
|
||||
// bad P at creation
|
||||
backup = P[idx];
|
||||
P[idx] = scalarmultBase(skGen());
|
||||
try
|
||||
{
|
||||
clsag = CLSAG_Gen(message, P, p, C, z, idx); //, hw::get_device("default"));
|
||||
ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag));
|
||||
}
|
||||
catch (...) { /* either exception, or failure to verify above */ }
|
||||
P[idx] = backup;
|
||||
|
||||
// good
|
||||
clsag = CLSAG_Gen(message, P, p, C, z, idx); //, hw::get_device("default"));
|
||||
ASSERT_TRUE(CLSAG_Ver(message, P, C, clsag));
|
||||
|
||||
// bad message at verification
|
||||
ASSERT_FALSE(CLSAG_Ver(zero(), P, C, clsag));
|
||||
|
||||
// bad real P at verification
|
||||
backup = P[idx];
|
||||
P[idx] = scalarmultBase(skGen());
|
||||
ASSERT_FALSE(CLSAG_Ver(zero(), P, C, clsag));
|
||||
P[idx] = backup;
|
||||
|
||||
// bad fake P at verification
|
||||
backup = P[(idx + 1) % ring_size];
|
||||
P[(idx + 1) % ring_size] = scalarmultBase(skGen());
|
||||
ASSERT_FALSE(CLSAG_Ver(zero(), P, C, clsag));
|
||||
P[(idx + 1) % ring_size] = backup;
|
||||
|
||||
// bad real C at verification
|
||||
backup = C[idx];
|
||||
C[idx] = scalarmultBase(skGen());
|
||||
ASSERT_FALSE(CLSAG_Ver(zero(), P, C, clsag));
|
||||
C[idx] = backup;
|
||||
|
||||
// bad fake C at verification
|
||||
backup = C[(idx + 1) % ring_size];
|
||||
C[(idx + 1) % ring_size] = scalarmultBase(skGen());
|
||||
ASSERT_FALSE(CLSAG_Ver(zero(), P, C, clsag));
|
||||
C[(idx + 1) % ring_size] = backup;
|
||||
|
||||
// empty s
|
||||
auto sbackup = clsag.s;
|
||||
clsag.s.clear();
|
||||
ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag));
|
||||
clsag.s = sbackup;
|
||||
|
||||
// too few s elements
|
||||
backup = clsag.s.back();
|
||||
clsag.s.pop_back();
|
||||
ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag));
|
||||
clsag.s.push_back(backup);
|
||||
|
||||
// too many s elements
|
||||
clsag.s.push_back(skGen());
|
||||
ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag));
|
||||
clsag.s.pop_back();
|
||||
|
||||
// bad s in clsag at verification
|
||||
for (auto &s: clsag.s)
|
||||
{
|
||||
backup = s;
|
||||
s = skGen();
|
||||
ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag));
|
||||
s = backup;
|
||||
}
|
||||
|
||||
// bad c1 in clsag at verification
|
||||
backup = clsag.c1;
|
||||
clsag.c1 = skGen();
|
||||
ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag));
|
||||
clsag.c1 = backup;
|
||||
|
||||
// bad I in clsag at verification
|
||||
backup = clsag.I;
|
||||
clsag.I = scalarmultBase(skGen());
|
||||
ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag));
|
||||
clsag.I = backup;
|
||||
|
||||
// bad D in clsag at verification
|
||||
backup = clsag.D;
|
||||
clsag.D = scalarmultBase(skGen());
|
||||
ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag));
|
||||
clsag.D = backup;
|
||||
|
||||
// D not in main subgroup in clsag at verification
|
||||
backup = clsag.D;
|
||||
rct::key x;
|
||||
ASSERT_TRUE(epee::string_tools::hex_to_pod("c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", x));
|
||||
clsag.D = rct::addKeys(clsag.D, x);
|
||||
ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag));
|
||||
clsag.D = backup;
|
||||
|
||||
// swapped I and D in clsag at verification
|
||||
std::swap(clsag.I, clsag.D);
|
||||
ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag));
|
||||
std::swap(clsag.I, clsag.D);
|
||||
|
||||
// check it's still good, in case we failed to restore
|
||||
ASSERT_TRUE(CLSAG_Ver(message, P, C, clsag));
|
||||
}
|
||||
|
||||
TEST(ringct, range_proofs)
|
||||
{
|
||||
//Ring CT Stuff
|
||||
|
|
|
@ -477,6 +477,7 @@ TEST(Serialization, serializes_ringct_types)
|
|||
rct::ecdhTuple ecdh0, ecdh1;
|
||||
rct::boroSig boro0, boro1;
|
||||
rct::mgSig mg0, mg1;
|
||||
rct::clsag clsag0, clsag1;
|
||||
rct::Bulletproof bp0, bp1;
|
||||
rct::rctSig s0, s1;
|
||||
cryptonote::transaction tx0, tx1;
|
||||
|
@ -592,9 +593,11 @@ TEST(Serialization, serializes_ringct_types)
|
|||
rct::skpkGen(Sk, Pk);
|
||||
destinations.push_back(Pk);
|
||||
//compute rct data with mixin 3
|
||||
const rct::RCTConfig rct_config{ rct::RangeProofPaddedBulletproof, 0 };
|
||||
const rct::RCTConfig rct_config{ rct::RangeProofPaddedBulletproof, 2 };
|
||||
s0 = rct::genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 0, 3, rct_config, hw::get_device("default"));
|
||||
|
||||
ASSERT_FALSE(s0.p.MGs.empty());
|
||||
ASSERT_TRUE(s0.p.CLSAGs.empty());
|
||||
mg0 = s0.p.MGs[0];
|
||||
ASSERT_TRUE(serialization::dump_binary(mg0, blob));
|
||||
ASSERT_TRUE(serialization::parse_binary(blob, mg1));
|
||||
|
@ -614,6 +617,23 @@ TEST(Serialization, serializes_ringct_types)
|
|||
ASSERT_TRUE(serialization::parse_binary(blob, bp1));
|
||||
bp1.V = bp0.V; // this is not saved, as it is reconstructed from other tx data
|
||||
ASSERT_EQ(bp0, bp1);
|
||||
|
||||
const rct::RCTConfig rct_config_clsag{ rct::RangeProofPaddedBulletproof, 3 };
|
||||
s0 = rct::genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 0, 3, rct_config_clsag, hw::get_device("default"));
|
||||
|
||||
ASSERT_FALSE(s0.p.CLSAGs.empty());
|
||||
ASSERT_TRUE(s0.p.MGs.empty());
|
||||
clsag0 = s0.p.CLSAGs[0];
|
||||
ASSERT_TRUE(serialization::dump_binary(clsag0, blob));
|
||||
ASSERT_TRUE(serialization::parse_binary(blob, clsag1));
|
||||
ASSERT_TRUE(clsag0.s.size() == clsag1.s.size());
|
||||
for (size_t n = 0; n < clsag0.s.size(); ++n)
|
||||
{
|
||||
ASSERT_TRUE(clsag0.s[n] == clsag1.s[n]);
|
||||
}
|
||||
ASSERT_TRUE(clsag0.c1 == clsag1.c1);
|
||||
// I is not serialized, they are meant to be reconstructed
|
||||
ASSERT_TRUE(clsag0.D == clsag1.D);
|
||||
}
|
||||
|
||||
TEST(Serialization, portability_wallet)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue