parent
ada527558f
commit
106e3dc3d4
@ -0,0 +1,469 @@
|
|||||||
|
// Copyright (c) 2014-2016, 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 "chaingen.h"
|
||||||
|
#include "chaingen_tests_list.h"
|
||||||
|
|
||||||
|
using namespace epee;
|
||||||
|
using namespace crypto;
|
||||||
|
using namespace cryptonote;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
// Tests
|
||||||
|
|
||||||
|
bool gen_rct_tx_validation_base::generate_with(std::vector<test_event_entry>& events,
|
||||||
|
const int *out_idx, int mixin, uint64_t amount_paid, bool valid,
|
||||||
|
const std::function<void(std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations)> &pre_tx,
|
||||||
|
const std::function<void(transaction &tx)> &post_tx) const
|
||||||
|
{
|
||||||
|
uint64_t ts_start = 1338224400;
|
||||||
|
|
||||||
|
GENERATE_ACCOUNT(miner_account);
|
||||||
|
MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
|
||||||
|
|
||||||
|
// create 4 miner accounts, and have them mine the next 4 blocks
|
||||||
|
cryptonote::account_base miner_accounts[4];
|
||||||
|
const cryptonote::block *prev_block = &blk_0;
|
||||||
|
cryptonote::block blocks[4];
|
||||||
|
for (size_t n = 0; n < 4; ++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,
|
||||||
|
3, 3, prev_block->timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
|
||||||
|
crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 0, 3),
|
||||||
|
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[3];
|
||||||
|
for (size_t i = 0; i < CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW; ++i)
|
||||||
|
{
|
||||||
|
cryptonote::block blk;
|
||||||
|
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk, blk_last, miner_account,
|
||||||
|
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version,
|
||||||
|
3, 3, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
|
||||||
|
crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 0, 3),
|
||||||
|
false, "Failed to generate block");
|
||||||
|
events.push_back(blk);
|
||||||
|
blk_last = blk;
|
||||||
|
}
|
||||||
|
blk_r = blk_last;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create 4 txes from these miners in another block, to generate some rct outputs
|
||||||
|
transaction rct_txes[4];
|
||||||
|
rct::key rct_tx_masks[16];
|
||||||
|
cryptonote::block blk_txes[4];
|
||||||
|
for (size_t n = 0; n < 4; ++n)
|
||||||
|
{
|
||||||
|
std::vector<crypto::hash> starting_rct_tx_hashes;
|
||||||
|
std::vector<tx_source_entry> sources;
|
||||||
|
|
||||||
|
sources.resize(1);
|
||||||
|
tx_source_entry& src = sources.back();
|
||||||
|
|
||||||
|
const size_t index_in_tx = 5;
|
||||||
|
src.amount = 30000000000000;
|
||||||
|
for (int m = 0; m < 4; ++m) {
|
||||||
|
src.push_output(m, boost::get<txout_to_key>(blocks[m].miner_tx.vout[index_in_tx].target).key, src.amount);
|
||||||
|
}
|
||||||
|
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 = index_in_tx;
|
||||||
|
src.mask = rct::identity();
|
||||||
|
|
||||||
|
//fill outputs entry
|
||||||
|
tx_destination_entry td;
|
||||||
|
td.addr = miner_accounts[n].get_keys().m_account_address;
|
||||||
|
td.amount = 7390000000000;
|
||||||
|
std::vector<tx_destination_entry> destinations;
|
||||||
|
destinations.push_back(td);
|
||||||
|
destinations.push_back(td);
|
||||||
|
destinations.push_back(td);
|
||||||
|
destinations.push_back(td); // 30 -> 7.39 * 4
|
||||||
|
|
||||||
|
crypto::secret_key tx_key;
|
||||||
|
bool r = construct_tx_and_get_tx_key(miner_accounts[n].get_keys(), sources, destinations, std::vector<uint8_t>(), rct_txes[n], 0, tx_key, true);
|
||||||
|
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
|
||||||
|
events.push_back(rct_txes[n]);
|
||||||
|
starting_rct_tx_hashes.push_back(get_transaction_hash(rct_txes[n]));
|
||||||
|
|
||||||
|
crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(rct_txes[n]);
|
||||||
|
for (size_t o = 0; o < 4; ++o)
|
||||||
|
{
|
||||||
|
cryptonote::keypair in_ephemeral;
|
||||||
|
crypto::key_image ki;
|
||||||
|
cryptonote::generate_key_image_helper(miner_accounts[n].get_keys(), tx_pub_key, o, in_ephemeral, ki);
|
||||||
|
rct::decodeRct(rct_txes[n].rct_signatures, rct::sk2rct(in_ephemeral.sec), o, rct_tx_masks[o+n*4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk_txes[n], 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,
|
||||||
|
3, 3, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
|
||||||
|
crypto::hash(), 0, transaction(), starting_rct_tx_hashes, 0, 0, 3),
|
||||||
|
false, "Failed to generate block");
|
||||||
|
events.push_back(blk_txes[n]);
|
||||||
|
blk_last = blk_txes[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
// rewind
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW; ++i)
|
||||||
|
{
|
||||||
|
cryptonote::block blk;
|
||||||
|
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk, blk_last, miner_account,
|
||||||
|
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version,
|
||||||
|
3, 3, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
|
||||||
|
crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 0, 3),
|
||||||
|
false, "Failed to generate block");
|
||||||
|
events.push_back(blk);
|
||||||
|
blk_last = blk;
|
||||||
|
}
|
||||||
|
blk_r = blk_last;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a tx from the requested ouputs
|
||||||
|
std::vector<tx_source_entry> sources;
|
||||||
|
size_t rct_idx = 0, pre_rct_idx = 0;
|
||||||
|
for (size_t out_idx_idx = 0; out_idx[out_idx_idx] >= 0; ++out_idx_idx) {
|
||||||
|
sources.resize(sources.size()+1);
|
||||||
|
tx_source_entry& src = sources.back();
|
||||||
|
|
||||||
|
src.real_output = 0;
|
||||||
|
if (out_idx[out_idx_idx]) {
|
||||||
|
// rct
|
||||||
|
src.amount = 7390000000000;
|
||||||
|
src.real_out_tx_key = get_tx_pub_key_from_extra(rct_txes[rct_idx/4]);
|
||||||
|
src.real_output_in_tx_index = rct_idx&3;
|
||||||
|
src.mask = rct_tx_masks[rct_idx];
|
||||||
|
for (int m = 0; m <= mixin; ++m) {
|
||||||
|
rct::ctkey ctkey;
|
||||||
|
ctkey.dest = rct::pk2rct(boost::get<txout_to_key>(rct_txes[rct_idx/4].vout[rct_idx&3].target).key);
|
||||||
|
ctkey.mask = rct_txes[rct_idx/4].rct_signatures.outPk[rct_idx&3].mask;
|
||||||
|
src.outputs.push_back(std::make_pair(rct_idx, ctkey));
|
||||||
|
++rct_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// pre rct
|
||||||
|
src.amount = 5000000000000;
|
||||||
|
src.real_out_tx_key = cryptonote::get_tx_pub_key_from_extra(blocks[pre_rct_idx].miner_tx);
|
||||||
|
src.real_output_in_tx_index = 4;
|
||||||
|
src.mask = rct::identity();
|
||||||
|
for (int m = 0; m <= mixin; ++m) {
|
||||||
|
src.push_output(m, boost::get<txout_to_key>(blocks[pre_rct_idx].miner_tx.vout[4].target).key, src.amount);
|
||||||
|
++pre_rct_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//fill outputs entry
|
||||||
|
tx_destination_entry td;
|
||||||
|
td.addr = miner_account.get_keys().m_account_address;
|
||||||
|
td.amount = amount_paid;
|
||||||
|
std::vector<tx_destination_entry> destinations;
|
||||||
|
destinations.push_back(td);
|
||||||
|
|
||||||
|
if (pre_tx)
|
||||||
|
pre_tx(sources, destinations);
|
||||||
|
|
||||||
|
transaction tx;
|
||||||
|
crypto::secret_key tx_key;
|
||||||
|
bool r = construct_tx_and_get_tx_key(miner_accounts[0].get_keys(), sources, destinations, std::vector<uint8_t>(), tx, 0, tx_key, true);
|
||||||
|
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
|
||||||
|
|
||||||
|
if (post_tx)
|
||||||
|
post_tx(tx);
|
||||||
|
|
||||||
|
if (!valid)
|
||||||
|
DO_CALLBACK(events, "mark_invalid_tx");
|
||||||
|
events.push_back(tx);
|
||||||
|
LOG_PRINT_L0("Test tx: " << obj_to_json_str(tx));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_valid_from_pre_rct::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {0, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, true, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_valid_from_rct::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, true, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_valid_from_mixed::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, 0, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, true, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_pre_rct_bad_real_dest::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {0, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
bool tx_creation_succeeded = false;
|
||||||
|
// in the case, the tx will fail to create, due to mismatched sk/pk
|
||||||
|
bool ret = generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
[](std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations) {rct::key sk; rct::skpkGen(sk, sources[0].outputs[0].second.dest);},
|
||||||
|
[&tx_creation_succeeded](const transaction &tx){tx_creation_succeeded=true;});
|
||||||
|
return !ret && !tx_creation_succeeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_pre_rct_bad_real_mask::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {0, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
[](std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations) {sources[0].outputs[0].second.mask = rct::zeroCommit(99999);},
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_pre_rct_bad_fake_dest::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {0, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
[](std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations) {rct::key sk; rct::skpkGen(sk, sources[0].outputs[1].second.dest);},
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_pre_rct_bad_fake_mask::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {0, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
[](std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations) {sources[0].outputs[1].second.mask = rct::zeroCommit(99999);},
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_rct_bad_real_dest::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
bool tx_creation_succeeded = false;
|
||||||
|
// in the case, the tx will fail to create, due to mismatched sk/pk
|
||||||
|
bool ret = generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
[](std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations) {rct::key sk; rct::skpkGen(sk, sources[0].outputs[0].second.dest);},
|
||||||
|
[&tx_creation_succeeded](const transaction &tx){tx_creation_succeeded=true;});
|
||||||
|
return !ret && !tx_creation_succeeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_rct_bad_real_mask::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
[](std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations) {sources[0].outputs[0].second.mask = rct::zeroCommit(99999);},
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_rct_bad_fake_dest::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
[](std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations) {rct::key sk; rct::skpkGen(sk, sources[0].outputs[1].second.dest);},
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_rct_bad_fake_mask::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
[](std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations) {sources[0].outputs[1].second.mask = rct::zeroCommit(99999);},
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_rct_spend_with_zero_commit::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
[](std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations) {sources[0].outputs[0].second.mask = rct::zeroCommit(sources[0].amount); sources[0].mask = rct::identity();},
|
||||||
|
[](transaction &tx){boost::get<txin_to_key>(tx.vin[0]).amount = 0;});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_pre_rct_zero_vin_amount::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {0, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
NULL, [](transaction &tx) {boost::get<txin_to_key>(tx.vin[0]).amount = 0;});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_rct_non_zero_vin_amount::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
NULL, [](transaction &tx) {boost::get<txin_to_key>(tx.vin[0]).amount = 5000000000000;}); // one that we know exists
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_non_zero_vout_amount::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
NULL, [](transaction &tx) {tx.vout[0].amount = 5000000000000;}); // one that we know exists
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_pre_rct_duplicate_key_image::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {0, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
NULL, [&events](transaction &tx) {boost::get<txin_to_key>(tx.vin[0]).k_image = boost::get<txin_to_key>(boost::get<transaction>(events[67]).vin[0]).k_image;});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_rct_duplicate_key_image::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
NULL, [&events](transaction &tx) {boost::get<txin_to_key>(tx.vin[0]).k_image = boost::get<txin_to_key>(boost::get<transaction>(events[67]).vin[0]).k_image;});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_pre_rct_wrong_key_image::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {0, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
// some random key image from the monero blockchain, so we get something that is a valid key image
|
||||||
|
static const uint8_t k_image[33] = "\x49\x3b\x56\x16\x54\x76\xa8\x75\xb7\xf4\xa8\x51\xf5\x55\xd3\x44\xe7\x3e\xea\x73\xee\xc1\x06\x7c\x7d\xb6\x57\x28\x46\x85\xe1\x07";
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
NULL, [](transaction &tx) {memcpy(&boost::get<txin_to_key>(tx.vin[0]).k_image, k_image, 32);});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_rct_wrong_key_image::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
// some random key image from the monero blockchain, so we get something that is a valid key image
|
||||||
|
static const uint8_t k_image[33] = "\x49\x3b\x56\x16\x54\x76\xa8\x75\xb7\xf4\xa8\x51\xf5\x55\xd3\x44\xe7\x3e\xea\x73\xee\xc1\x06\x7c\x7d\xb6\x57\x28\x46\x85\xe1\x07";
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
NULL, [](transaction &tx) {memcpy(&boost::get<txin_to_key>(tx.vin[0]).k_image, k_image, 32);});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_pre_rct_wrong_fee::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {0, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
NULL, [](transaction &tx) {tx.rct_signatures.txnFee++;});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_rct_wrong_fee::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
NULL, [](transaction &tx) {tx.rct_signatures.txnFee++;});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_pre_rct_increase_vin_and_fee::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {0, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
NULL, [](transaction &tx) {boost::get<txin_to_key>(tx.vin[0]).amount++;tx.rct_signatures.txnFee++;});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_pre_rct_remove_vin::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
NULL, [](transaction &tx) {tx.vin.pop_back();});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_rct_remove_vin::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
NULL, [](transaction &tx) {tx.vin.pop_back();});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_pre_rct_add_vout::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
NULL, [](transaction &tx) {tx.vout.push_back(tx.vout.back());});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gen_rct_tx_rct_add_vout::generate(std::vector<test_event_entry>& events) const
|
||||||
|
{
|
||||||
|
const int mixin = 2;
|
||||||
|
const int out_idx[] = {1, -1};
|
||||||
|
const uint64_t amount_paid = 10000;
|
||||||
|
return generate_with(events, out_idx, mixin, amount_paid, false,
|
||||||
|
NULL, [](transaction &tx) {tx.vout.push_back(tx.vout.back());});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,251 @@
|
|||||||
|
// Copyright (c) 2014-2016, 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_rct_tx_validation_base : public test_chain_unit_base
|
||||||
|
{
|
||||||
|
gen_rct_tx_validation_base()
|
||||||
|
: m_invalid_tx_index(0)
|
||||||
|
, m_invalid_block_index(0)
|
||||||
|
{
|
||||||
|
REGISTER_CALLBACK_METHOD(gen_rct_tx_validation_base, mark_invalid_tx);
|
||||||
|
REGISTER_CALLBACK_METHOD(gen_rct_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_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, const int *out_idx, int mixin,
|
||||||
|
uint64_t amount_paid, bool valid,
|
||||||
|
const std::function<void(std::vector<cryptonote::tx_source_entry> &sources, std::vector<cryptonote::tx_destination_entry> &destinations)> &pre_tx,
|
||||||
|
const std::function<void(cryptonote::transaction &tx)> &post_tx) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t m_invalid_tx_index;
|
||||||
|
size_t m_invalid_block_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct get_test_options<gen_rct_tx_validation_base> {
|
||||||
|
const std::pair<uint8_t, uint64_t> hard_forks[2] = {std::make_pair(1, 0), std::make_pair(3, 1)};
|
||||||
|
const cryptonote::test_options test_options = {
|
||||||
|
hard_forks
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// valid
|
||||||
|
struct gen_rct_tx_valid_from_pre_rct : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_valid_from_pre_rct>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_valid_from_rct : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_valid_from_rct>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_valid_from_mixed : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_valid_from_mixed>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
// altered commitment/dest
|
||||||
|
struct gen_rct_tx_pre_rct_bad_real_dest : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_pre_rct_bad_real_dest>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_pre_rct_bad_real_mask : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_pre_rct_bad_real_mask>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_pre_rct_bad_fake_dest : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_pre_rct_bad_fake_dest>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_pre_rct_bad_fake_mask : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_pre_rct_bad_fake_mask>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_rct_bad_real_dest : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_rct_bad_real_dest>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_rct_bad_real_mask : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_rct_bad_real_mask>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_rct_bad_fake_dest : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_rct_bad_fake_dest>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_rct_bad_fake_mask : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_rct_bad_fake_mask>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_rct_spend_with_zero_commit : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_rct_spend_with_zero_commit>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
// altered amounts
|
||||||
|
struct gen_rct_tx_pre_rct_zero_vin_amount : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_pre_rct_zero_vin_amount>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_rct_non_zero_vin_amount : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_rct_non_zero_vin_amount>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_non_zero_vout_amount : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_non_zero_vout_amount>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
// key image
|
||||||
|
struct gen_rct_tx_pre_rct_duplicate_key_image : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_pre_rct_duplicate_key_image>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_rct_duplicate_key_image : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_rct_duplicate_key_image>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_pre_rct_wrong_key_image : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_pre_rct_wrong_key_image>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_rct_wrong_key_image : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_rct_wrong_key_image>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
// fee
|
||||||
|
struct gen_rct_tx_pre_rct_wrong_fee : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_pre_rct_wrong_fee>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_rct_wrong_fee : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_rct_wrong_fee>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_pre_rct_increase_vin_and_fee : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_pre_rct_increase_vin_and_fee>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
// modify vin/vout
|
||||||
|
struct gen_rct_tx_pre_rct_remove_vin : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_pre_rct_remove_vin>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_rct_remove_vin : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_rct_remove_vin>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_pre_rct_add_vout : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_pre_rct_add_vout>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
||||||
|
struct gen_rct_tx_rct_add_vout : public gen_rct_tx_validation_base
|
||||||
|
{
|
||||||
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
|
};
|
||||||
|
template<> struct get_test_options<gen_rct_tx_rct_add_vout>: public get_test_options<gen_rct_tx_validation_base> {};
|
||||||
|
|
Loading…
Reference in new issue