forked from lthn/blockchain
htlc: added test for validating before and after expiration conditions
This commit is contained in:
parent
7f902f27c1
commit
71708ca673
6 changed files with 164 additions and 13 deletions
|
|
@ -1633,7 +1633,7 @@ void wallet2::refresh(std::atomic<bool>& stop)
|
|||
refresh(n, f, stop);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc)
|
||||
void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx)
|
||||
{
|
||||
std::vector<currency::extra_v> extra;
|
||||
std::vector<currency::attachment_v> attachments;
|
||||
|
|
@ -1642,9 +1642,13 @@ void wallet2::transfer(uint64_t amount, const currency::account_public_address&
|
|||
dst.resize(1);
|
||||
dst.back().addr.push_back(acc);
|
||||
dst.back().amount = amount;
|
||||
transaction result_tx = AUTO_VAL_INIT(result_tx);
|
||||
this->transfer(dst, 0, 0, TX_DEFAULT_FEE, extra, attachments, tools::detail::ssi_digit, tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD), result_tx);
|
||||
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc)
|
||||
{
|
||||
transaction result_tx = AUTO_VAL_INIT(result_tx);
|
||||
this->transfer(amount, acc, result_tx);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::reset_creation_time(uint64_t timestamp)
|
||||
|
|
@ -4054,7 +4058,13 @@ void wallet2::get_list_of_active_htlc(std::list<wallet_public::htlc_entry_info>&
|
|||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::redeem_htlc(const crypto::hash& htlc_tx_id, std::string origin)
|
||||
void wallet2::redeem_htlc(const crypto::hash& htlc_tx_id, const std::string& origin)
|
||||
{
|
||||
currency::transaction result_tx = AUTO_VAL_INIT(result_tx);
|
||||
return redeem_htlc(htlc_tx_id, origin, result_tx);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::redeem_htlc(const crypto::hash& htlc_tx_id, const std::string& origin, currency::transaction& result_tx)
|
||||
{
|
||||
|
||||
construct_tx_param ctp = get_default_construct_tx_param();
|
||||
|
|
@ -4069,8 +4079,6 @@ void wallet2::redeem_htlc(const crypto::hash& htlc_tx_id, std::string origin)
|
|||
"htlc not found with tx_id = " << htlc_tx_id, API_RETURN_CODE_NOT_FOUND);
|
||||
|
||||
ctp.dsts.back().amount = m_transfers[it->second].amount() - ctp.fee;
|
||||
|
||||
currency::transaction result_tx = AUTO_VAL_INIT(result_tx);
|
||||
this->transfer(ctp, result_tx, true, nullptr);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -549,6 +549,7 @@ namespace tools
|
|||
uint64_t unlocked_balance() const;
|
||||
|
||||
void transfer(uint64_t amount, const currency::account_public_address& acc);
|
||||
void transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx);
|
||||
|
||||
void transfer(const std::vector<currency::tx_destination_entry>& dsts,
|
||||
size_t fake_outputs_count,
|
||||
|
|
@ -858,7 +859,8 @@ namespace tools
|
|||
*/
|
||||
void create_htlc_proposal(uint64_t amount, const currency::account_public_address& addr, uint64_t lock_blocks_count, currency::transaction &tx, const crypto::hash& htlc_hash, std::string &origin);
|
||||
void get_list_of_active_htlc(std::list<wallet_public::htlc_entry_info>& htlcs, bool only_redeem_txs);
|
||||
void redeem_htlc(const crypto::hash& htlc_tx_id, std::string origin);
|
||||
void redeem_htlc(const crypto::hash& htlc_tx_id, const std::string& origin, currency::transaction& result_tx);
|
||||
void redeem_htlc(const crypto::hash& htlc_tx_id, const std::string& origin);
|
||||
bool check_htlc_redeemed(const crypto::hash& htlc_tx_id, std::string& origin);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@ using namespace epee;
|
|||
using namespace crypto;
|
||||
using namespace currency;
|
||||
|
||||
#define INIT_RUNTIME_WALLET(instance_name) \
|
||||
currency::account_base instance_name##acc_base; \
|
||||
instance_name##acc_base.generate(); \
|
||||
LOG_PRINT_MAGENTA(": " << currency::get_account_address_as_str(instance_name##acc_base.get_public_address()), LOG_LEVEL_0); \
|
||||
std::shared_ptr<tools::wallet2> instance_name = init_playtime_test_wallet(events, c, instance_name##acc_base);
|
||||
|
||||
|
||||
//==============================================================================================================================
|
||||
|
||||
struct wallet_tests_callback_handler : public tools::i_wallet2_callback
|
||||
|
|
@ -72,11 +79,6 @@ bool atomic_simple_test::c1(currency::core& c, size_t ev_index, const std::vecto
|
|||
|
||||
LOG_PRINT_MAGENTA("Mining Address: " << currency::get_account_address_as_str(m_mining_accunt.get_public_address()), LOG_LEVEL_0);
|
||||
|
||||
#define INIT_RUNTIME_WALLET(instance_name) \
|
||||
currency::account_base instance_name##acc_base; \
|
||||
instance_name##acc_base.generate(); \
|
||||
LOG_PRINT_MAGENTA(": " << currency::get_account_address_as_str(instance_name##acc_base.get_public_address()), LOG_LEVEL_0); \
|
||||
std::shared_ptr<tools::wallet2> instance_name = init_playtime_test_wallet(events, c, instance_name##acc_base);
|
||||
|
||||
//create wallet instances and calculate balances
|
||||
INIT_RUNTIME_WALLET(alice_a_wlt_instance);
|
||||
|
|
@ -278,4 +280,128 @@ bool atomic_simple_test::c1(currency::core& c, size_t ev_index, const std::vecto
|
|||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
|
||||
atomic_test_wrong_redeem_wrong_refund::atomic_test_wrong_redeem_wrong_refund()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(atomic_test_wrong_redeem_wrong_refund, c1);
|
||||
}
|
||||
|
||||
bool atomic_test_wrong_redeem_wrong_refund::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
epee::debug::get_set_enable_assert(true, true);
|
||||
|
||||
currency::account_base genesis_acc;
|
||||
genesis_acc.generate();
|
||||
m_mining_accunt.generate();
|
||||
|
||||
|
||||
block blk_0 = AUTO_VAL_INIT(blk_0);
|
||||
generator.construct_genesis_block(blk_0, genesis_acc, test_core_time::get_time());
|
||||
events.push_back(blk_0);
|
||||
|
||||
REWIND_BLOCKS_N(events, blk_0r, blk_0, m_mining_accunt, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
epee::debug::get_set_enable_assert(true, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool atomic_test_wrong_redeem_wrong_refund::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
/*
|
||||
we create two HTLC and then we make attempt to spend it:
|
||||
1. spend it as refund when it supposed to be redeem
|
||||
2. spend it as redeem when it supposed to be refund
|
||||
|
||||
*/
|
||||
|
||||
LOG_PRINT_MAGENTA("Mining Address: " << currency::get_account_address_as_str(m_mining_accunt.get_public_address()), LOG_LEVEL_0);
|
||||
|
||||
//create wallet instances and calculate balances
|
||||
INIT_RUNTIME_WALLET(alice_a_wlt_instance);
|
||||
INIT_RUNTIME_WALLET(alice_b_wlt_instance);
|
||||
INIT_RUNTIME_WALLET(alice_c_wlt_instance);
|
||||
|
||||
#define AMOUNT_TO_TRANSFER_HTLC (TESTS_DEFAULT_FEE*10)
|
||||
|
||||
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, m_mining_accunt);
|
||||
|
||||
size_t blocks_fetched = 0;
|
||||
bool received_money = false;
|
||||
std::atomic<bool> atomic_false = ATOMIC_VAR_INIT(false);
|
||||
miner_wlt->refresh(blocks_fetched, received_money, atomic_false);
|
||||
CHECK_AND_FORCE_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
|
||||
|
||||
|
||||
uint64_t transfer_amount = AMOUNT_TO_TRANSFER_HTLC + TESTS_DEFAULT_FEE;
|
||||
miner_wlt->transfer(transfer_amount, alice_a_wlt_instance->get_account().get_public_address());
|
||||
LOG_PRINT_MAGENTA("Transaction sent to Alice A: " << transfer_amount, LOG_LEVEL_0);
|
||||
|
||||
miner_wlt->transfer(transfer_amount, alice_b_wlt_instance->get_account().get_public_address());
|
||||
LOG_PRINT_MAGENTA("Transaction sent to Alice A: " << transfer_amount, LOG_LEVEL_0);
|
||||
|
||||
|
||||
bool r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
|
||||
|
||||
alice_a_wlt_instance->refresh();
|
||||
alice_b_wlt_instance->refresh();
|
||||
alice_c_wlt_instance->refresh();
|
||||
|
||||
std::string alice_origin; //will be deterministically generated by Alice's A wallet
|
||||
currency::transaction res_tx = AUTO_VAL_INIT(res_tx);
|
||||
alice_a_wlt_instance->create_htlc_proposal(transfer_amount - TESTS_DEFAULT_FEE, alice_b_wlt_instance->get_account().get_public_address(), 9, res_tx, currency::null_hash, alice_origin);
|
||||
|
||||
std::string alice_origin_b; //will be deterministically generated by Alice's A wallet
|
||||
currency::transaction res_tx_b = AUTO_VAL_INIT(res_tx_b);
|
||||
alice_b_wlt_instance->create_htlc_proposal(transfer_amount - TESTS_DEFAULT_FEE, alice_c_wlt_instance->get_account().get_public_address(), 12, res_tx, currency::null_hash, alice_origin_b);
|
||||
|
||||
|
||||
//forward blockchain to create redeem transaction
|
||||
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
|
||||
|
||||
alice_a_wlt_instance->refresh();
|
||||
alice_b_wlt_instance->refresh();
|
||||
alice_c_wlt_instance->refresh();
|
||||
|
||||
CHECK_AND_FORCE_ASSERT_MES(alice_a_wlt_instance->balance() == transfer_amount - TESTS_DEFAULT_FEE, false, "Incorrect balance");
|
||||
|
||||
//create refund tx
|
||||
currency::transaction refund_tx = AUTO_VAL_INIT(refund_tx);
|
||||
alice_a_wlt_instance->transfer(transfer_amount - TESTS_DEFAULT_FEE*2, alice_b_wlt_instance->get_account().get_public_address(), refund_tx);
|
||||
|
||||
//create redeem tx
|
||||
std::list<tools::wallet_public::htlc_entry_info> htlcs;
|
||||
alice_c_wlt_instance->get_list_of_active_htlc(htlcs, true);
|
||||
CHECK_AND_FORCE_ASSERT_MES(htlcs.size() == 1, false, "Epected htlc not found");
|
||||
currency::transaction result_redeem_tx = AUTO_VAL_INIT(result_redeem_tx);
|
||||
alice_c_wlt_instance->redeem_htlc(htlcs.front().tx_id, alice_origin_b, result_redeem_tx);
|
||||
|
||||
c.get_blockchain_storage().truncate_blockchain(c.get_blockchain_storage().get_current_blockchain_size() - 8);
|
||||
|
||||
//try to submit wrong transaction that do refund before expiration
|
||||
std::vector<currency::transaction> txs;
|
||||
txs.push_back(refund_tx);
|
||||
r = mine_next_pow_block_in_playtime_with_given_txs(m_mining_accunt.get_public_address(), c, txs);
|
||||
CHECK_AND_FORCE_ASSERT_MES(!r, false, "Blo k with wrong refund tx accepted");
|
||||
|
||||
//forward blockchain and try to submit wrong tx that do redeem after expiration
|
||||
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
|
||||
|
||||
std::vector<currency::transaction> txs2;
|
||||
txs2.push_back(result_redeem_tx);
|
||||
r = mine_next_pow_block_in_playtime_with_given_txs(m_mining_accunt.get_public_address(), c, txs2);
|
||||
CHECK_AND_FORCE_ASSERT_MES(!r, false, "Blo k with wrong refund tx accepted");
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//try to do double spend!!!! (redeem and refund), check if wallet see redeemed tx and don't let it be spent
|
||||
|
|
@ -14,6 +14,15 @@ struct atomic_simple_test : public wallet_test
|
|||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
private:
|
||||
mutable currency::account_base m_mining_accunt;
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct atomic_test_wrong_redeem_wrong_refund : public wallet_test
|
||||
{
|
||||
atomic_test_wrong_redeem_wrong_refund();
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
private:
|
||||
mutable currency::account_base m_mining_accunt;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -109,6 +109,11 @@ inline bool mine_next_pow_block_in_playtime_with_given_txs(const currency::accou
|
|||
CHECK_AND_ASSERT_MES(r, false, "find_nonce_for_given_block failed");
|
||||
|
||||
currency::block_verification_context bvc = AUTO_VAL_INIT(bvc);
|
||||
for (auto& tx : txs)
|
||||
{
|
||||
crypto::hash tx_id = currency::get_transaction_hash(tx);
|
||||
bvc.m_onboard_transactions[tx_id] = tx;
|
||||
}
|
||||
c.handle_incoming_block(t_serializable_object_to_blob(b), bvc);
|
||||
CHECK_AND_NO_ASSERT_MES(!bvc.m_verification_failed && !bvc.m_marked_as_orphaned && !bvc.m_already_exists, false, "block verification context check failed");
|
||||
|
||||
|
|
|
|||
|
|
@ -1022,6 +1022,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
// atomics
|
||||
GENERATE_AND_PLAY(atomic_simple_test);
|
||||
GENERATE_AND_PLAY(atomic_test_wrong_redeem_wrong_refund);
|
||||
|
||||
// GENERATE_AND_PLAY(gen_block_reward);
|
||||
// END OF TESTS */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue