1
0
Fork 0
forked from lthn/blockchain

coretests: escrow_balance test added for more careful balance checking in contracts (related to #47)

This commit is contained in:
sowle 2019-11-07 13:39:46 +03:00
parent db38a029fd
commit c8138225d2
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
4 changed files with 542 additions and 0 deletions

View file

@ -765,6 +765,7 @@ int main(int argc, char* argv[])
// GENERATE_AND_PLAY(escrow_proposal_acceptance_in_alt_chain); -- work in progress
GENERATE_AND_PLAY(escrow_zero_amounts);
GENERATE_AND_PLAY(escrow_acceptance_and_balance);
GENERATE_AND_PLAY(escrow_balance);
GENERATE_AND_PLAY(escrow_altchain_meta_test<0>);
GENERATE_AND_PLAY(escrow_altchain_meta_test<1>);

View file

@ -3292,3 +3292,490 @@ bool escrow_acceptance_and_balance::check_balance_after_acceptance_confirmed(cur
return true;
}
//------------------------------------------------------------------------------
escrow_balance::escrow_balance()
: m_alice_bob_start_amount(0)
, m_alice_bob_start_chunk_amount(0)
{
REGISTER_CALLBACK_METHOD(escrow_balance, c1);
}
bool escrow_balance::generate(std::vector<test_event_entry>& events) const
{
// Test idea: carefull check balances on each stage of escrow contract (including cancellation req and acc):
// 1) within wallet callback in the middle of contract function call
// 2) after tx was sent to network but not yet confirmed
// 3) after tx was confirmed
m_accounts.resize(TOTAL_ACCS_COUNT);
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate();
account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate();
account_base& bob_acc = m_accounts[BOB_ACC_IDX]; bob_acc.generate();
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time());
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
m_alice_bob_start_amount = MK_TEST_COINS(200);
uint64_t amount_chunks = 10;
m_alice_bob_start_chunk_amount = m_alice_bob_start_amount / 10;
transaction tx_0 = AUTO_VAL_INIT(tx_0);
bool r = construct_tx_with_many_outputs(events, blk_0r, miner_acc.get_keys(), alice_acc.get_public_address(), m_alice_bob_start_amount, 10, TESTS_DEFAULT_FEE, tx_0);
CHECK_AND_ASSERT_MES(r, false, "construct_tx_with_many_outputs failed");
events.push_back(tx_0);
transaction tx_1 = AUTO_VAL_INIT(tx_1);
r = construct_tx_with_many_outputs(events, blk_0r, miner_acc.get_keys(), bob_acc.get_public_address(), m_alice_bob_start_amount, 10, TESTS_DEFAULT_FEE, tx_1);
CHECK_AND_ASSERT_MES(r, false, "construct_tx_with_many_outputs failed");
events.push_back(tx_1);
MAKE_NEXT_BLOCK_TX_LIST(events, blk_1, blk_0r, miner_acc, std::list<transaction>({tx_0, tx_1}));
REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, WALLET_DEFAULT_TX_SPENDABLE_AGE);
DO_CALLBACK(events, "c1");
return true;
}
bool escrow_balance::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
bool r = false, stub_bool = false;
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]);
auto alice_bc = std::make_shared<wallet_callback_balance_checker>("Alice");
alice_wlt->callback(alice_bc);
std::shared_ptr<tools::wallet2> bob_wlt = init_playtime_test_wallet(events, c, m_accounts[BOB_ACC_IDX]);
auto bob_bc = std::make_shared<wallet_callback_balance_checker>("Bob");
bob_wlt->callback(bob_bc);
alice_bc->expect_balance(m_alice_bob_start_amount, 0);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt,
m_alice_bob_start_amount, // total
true, UINT64_MAX,
m_alice_bob_start_amount, // unlocked
0, // mined
0, // awaited in
0 // awainted out
), false, "");
CHECK_AND_ASSERT_MES(alice_bc->check(), false, "balance callback check failed, see above");
bob_bc->expect_balance(m_alice_bob_start_amount, 0);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt,
m_alice_bob_start_amount, // total
true, UINT64_MAX,
m_alice_bob_start_amount, // unlocked
0, // mined
0, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(bob_bc->check(), false, "balance callback check failed, see above");
//
// escrow proposal
//
bc_services::contract_private_details cpd = AUTO_VAL_INIT(cpd);
cpd.amount_a_pledge = MK_TEST_COINS(7);
cpd.amount_b_pledge = MK_TEST_COINS(5);
cpd.amount_to_pay = MK_TEST_COINS(3);
cpd.a_addr = m_accounts[ALICE_ACC_IDX].get_public_address();
cpd.b_addr = m_accounts[BOB_ACC_IDX].get_public_address();
uint64_t alice_proposal_fee = MK_TEST_COINS(4);
uint64_t bob_acceptace_fee = MK_TEST_COINS(2);
uint64_t bob_release_fee = MK_TEST_COINS(9); // Alice states that Bob should pay this much money for upcoming contract release (which will be sent by Alice)
uint64_t alice_cancellation_request_fee = MK_TEST_COINS(1);
alice_bc->expect_balance(m_alice_bob_start_amount - alice_proposal_fee, m_alice_bob_start_amount - 2 * m_alice_bob_start_chunk_amount); // balace after sending the proposal
transaction proposal_tx = AUTO_VAL_INIT(proposal_tx);
transaction escrow_template_tx = AUTO_VAL_INIT(escrow_template_tx);
uint64_t expiration_time = test_core_time::get_time() + 60;
LOG_PRINT_GREEN("\n" "alice_wlt->send_escrow_proposal()", LOG_LEVEL_0);
alice_wlt->send_escrow_proposal(cpd, 0, 0, expiration_time, alice_proposal_fee, bob_release_fee, "", proposal_tx, escrow_template_tx);
CHECK_AND_ASSERT_MES(alice_bc->check(), false, "balance callback check failed, see above");
tools::wallet2::escrow_contracts_container contracts;
r = alice_wlt->get_contracts(contracts);
CHECK_AND_ASSERT_MES(r && contracts.size() == 1, false, "get_contracts() for Alice failed");
crypto::hash contract_id = contracts.begin()->first;
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
// proposal tx is not confirmed yet
alice_bc->expect_balance();
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt,
m_alice_bob_start_amount - alice_proposal_fee, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 2 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
0 // awainted out
), false, "");
CHECK_AND_ASSERT_MES(!alice_bc->called(), false, "balance callback check failed");
// Bob's balance should not change
bob_bc->expect_balance(m_alice_bob_start_amount, m_alice_bob_start_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt,
m_alice_bob_start_amount, // total
true, UINT64_MAX,
m_alice_bob_start_amount, // unlocked
0, // mined
0, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(bob_bc->check(), false, "balance callback check failed, see above");
// mine a block to confirm escrow proposal tx
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
// proposal tx is confirmed (balances should stay the same)
alice_bc->expect_balance(m_alice_bob_start_amount - alice_proposal_fee, m_alice_bob_start_amount - 2 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt,
m_alice_bob_start_amount - alice_proposal_fee, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 2 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
0 // awainted out
), false, "");
CHECK_AND_ASSERT_MES(alice_bc->check(), false, "balance callback check failed, see above");
bob_bc->expect_balance(m_alice_bob_start_amount, m_alice_bob_start_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt,
m_alice_bob_start_amount, // total
true, UINT64_MAX,
m_alice_bob_start_amount, // unlocked
0, // mined
0, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(bob_bc->check(), false, "balance callback check failed, see above");
//
// proposal acceptance
//
bob_bc->expect_balance(m_alice_bob_start_amount - cpd.amount_b_pledge - bob_release_fee - bob_acceptace_fee, m_alice_bob_start_amount - m_alice_bob_start_chunk_amount);
LOG_PRINT_GREEN("\n" "bob_wlt->accept_proposal()", LOG_LEVEL_0);
bob_wlt->accept_proposal(contract_id, bob_acceptace_fee);
CHECK_AND_ASSERT_MES(bob_bc->check(), false, "balance callback check failed, see above");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
// acceptance tx is not confirmed yet
alice_bc->expect_balance(m_alice_bob_start_amount - alice_proposal_fee - cpd.amount_a_pledge - cpd.amount_to_pay, m_alice_bob_start_amount - 2 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt,
m_alice_bob_start_amount - alice_proposal_fee - cpd.amount_a_pledge - cpd.amount_to_pay, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 2 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
cpd.amount_a_pledge + cpd.amount_to_pay // awaited out
), false, "");
CHECK_AND_ASSERT_MES(alice_bc->check(), false, "balance callback check failed, see above");
bob_bc->expect_balance();
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt,
m_alice_bob_start_amount - cpd.amount_b_pledge - bob_release_fee - bob_acceptace_fee, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 1 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
cpd.amount_b_pledge + bob_release_fee // awaited out
), false, "");
CHECK_AND_ASSERT_MES(!bob_bc->called(), false, "balance callback check failed");
// mine a block containing contract acceptance
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
// acceptance tx is confirmed
alice_bc->expect_balance(m_alice_bob_start_amount - alice_proposal_fee - cpd.amount_a_pledge - cpd.amount_to_pay, m_alice_bob_start_amount - 2 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt,
m_alice_bob_start_amount - alice_proposal_fee - cpd.amount_a_pledge - cpd.amount_to_pay, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 2 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(alice_bc->check(), false, "balance callback check failed, see above");
bob_bc->expect_balance(m_alice_bob_start_amount - cpd.amount_b_pledge - bob_release_fee - bob_acceptace_fee, m_alice_bob_start_amount - 1 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt,
m_alice_bob_start_amount - cpd.amount_b_pledge - bob_release_fee - bob_acceptace_fee, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 1 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(bob_bc->check(), false, "balance callback check failed, see above");
//
// cancellation request
//
alice_bc->expect_balance(m_alice_bob_start_amount - alice_proposal_fee - cpd.amount_a_pledge - cpd.amount_to_pay - alice_cancellation_request_fee, m_alice_bob_start_amount - 3 * m_alice_bob_start_chunk_amount);
LOG_PRINT_GREEN("\n" "alice_wlt->request_cancel_contract()", LOG_LEVEL_0);
alice_wlt->request_cancel_contract(contract_id, alice_cancellation_request_fee, 60 * 60);
CHECK_AND_ASSERT_MES(alice_bc->check(), false, "balance callback check failed, see above");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
// cancellation request is not confirmed yet
alice_bc->expect_balance();
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt,
m_alice_bob_start_amount - alice_proposal_fee - cpd.amount_a_pledge - cpd.amount_to_pay - alice_cancellation_request_fee, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 3 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(!alice_bc->called(), false, "balance callback check failed");
bob_bc->expect_balance(m_alice_bob_start_amount - cpd.amount_b_pledge - bob_release_fee - bob_acceptace_fee, m_alice_bob_start_amount - 1 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt,
m_alice_bob_start_amount - cpd.amount_b_pledge - bob_release_fee - bob_acceptace_fee, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 1 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(bob_bc->check(), false, "balance callback check failed, see above");
// mine a block containing cancellation request
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
// cancellation request is confirmed
alice_bc->expect_balance(m_alice_bob_start_amount - alice_proposal_fee - cpd.amount_a_pledge - cpd.amount_to_pay - alice_cancellation_request_fee, m_alice_bob_start_amount - 3 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt,
m_alice_bob_start_amount - alice_proposal_fee - cpd.amount_a_pledge - cpd.amount_to_pay - alice_cancellation_request_fee, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 3 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(alice_bc->check(), false, "balance callback check failed, see above");
bob_bc->expect_balance(m_alice_bob_start_amount - cpd.amount_b_pledge - bob_release_fee - bob_acceptace_fee, m_alice_bob_start_amount - 1 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt,
m_alice_bob_start_amount - cpd.amount_b_pledge - bob_release_fee - bob_acceptace_fee, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 1 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(bob_bc->check(), false, "balance callback check failed, see above");
//
// cancellation acceptance
//
bob_bc->expect_balance();
LOG_PRINT_GREEN("\n" "bob_wlt->accept_cancel_contract()", LOG_LEVEL_0);
bob_wlt->accept_cancel_contract(contract_id);
CHECK_AND_ASSERT_MES(!bob_bc->called(), false, "balance callback check failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
// cancellation acceptance is not confirmed yet
alice_bc->expect_balance(m_alice_bob_start_amount - alice_proposal_fee - alice_cancellation_request_fee, m_alice_bob_start_amount - 3 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt,
m_alice_bob_start_amount - alice_proposal_fee - alice_cancellation_request_fee, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 3 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
cpd.amount_a_pledge + cpd.amount_to_pay, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(alice_bc->check(), false, "balance callback check failed, see above");
bob_bc->expect_balance(m_alice_bob_start_amount - bob_release_fee - bob_acceptace_fee, m_alice_bob_start_amount - 1 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt,
m_alice_bob_start_amount - bob_release_fee - bob_acceptace_fee, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 1 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
cpd.amount_b_pledge, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(bob_bc->check(), false, "balance callback check failed, see above");
// mine a block containing cancellation acceptance
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
// cancellation acceptance is confirmed
alice_bc->expect_balance(m_alice_bob_start_amount - alice_proposal_fee - alice_cancellation_request_fee, m_alice_bob_start_amount - 3 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt,
m_alice_bob_start_amount - alice_proposal_fee - alice_cancellation_request_fee, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 3 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(alice_bc->check(), false, "balance callback check failed, see above");
bob_bc->expect_balance(m_alice_bob_start_amount - bob_release_fee - bob_acceptace_fee, m_alice_bob_start_amount - 1 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt,
m_alice_bob_start_amount - bob_release_fee - bob_acceptace_fee, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 1 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(bob_bc->check(), false, "balance callback check failed, see above");
//
// Stage 2 : check normal contract workflow
// don't check balances on request and accept as it was checked above
//
uint64_t alice_balance_before_stage_2 = m_alice_bob_start_amount - alice_proposal_fee - alice_cancellation_request_fee;
uint64_t bob_balance_before_stage_2 = m_alice_bob_start_amount - bob_release_fee - bob_acceptace_fee;
alice_bc->expect_balance(alice_balance_before_stage_2 - alice_proposal_fee, m_alice_bob_start_amount - 5 * m_alice_bob_start_chunk_amount);
LOG_PRINT_GREEN("\n" "stage2: alice_wlt->send_escrow_proposal()", LOG_LEVEL_0);
proposal_tx = AUTO_VAL_INIT(proposal_tx);
escrow_template_tx = AUTO_VAL_INIT(escrow_template_tx);
alice_wlt->send_escrow_proposal(cpd, 0, 0, expiration_time, alice_proposal_fee, bob_release_fee, "", proposal_tx, escrow_template_tx);
CHECK_AND_ASSERT_MES(alice_bc->check(), false, "balance callback check failed, see above");
contracts.clear();
r = alice_wlt->get_contracts(contracts);
CHECK_AND_ASSERT_MES(r && contracts.size() == 2, false, "get_contracts() for Alice failed");
// get new contract id
if (contract_id != contracts.begin()->first)
contract_id = contracts.begin()->first;
else
contract_id = (++contracts.begin())->first;
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
bob_wlt->refresh();
bob_bc->expect_balance(bob_balance_before_stage_2 - cpd.amount_b_pledge - bob_release_fee - bob_acceptace_fee, m_alice_bob_start_amount - 2 * m_alice_bob_start_chunk_amount);
LOG_PRINT_GREEN("\n" "stage2: bob_wlt->accept_proposal()", LOG_LEVEL_0);
bob_wlt->accept_proposal(contract_id, bob_acceptace_fee);
CHECK_AND_ASSERT_MES(bob_bc->check(), false, "balance callback check failed, see above");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
alice_bc->expect_balance(alice_balance_before_stage_2 - alice_proposal_fee - cpd.amount_a_pledge - cpd.amount_to_pay, m_alice_bob_start_amount - 5 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt,
alice_balance_before_stage_2 - alice_proposal_fee - cpd.amount_a_pledge - cpd.amount_to_pay, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 5 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(alice_bc->check(), false, "balance callback check failed");
bob_bc->expect_balance(bob_balance_before_stage_2 - cpd.amount_b_pledge - bob_release_fee - bob_acceptace_fee, m_alice_bob_start_amount - 2 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt,
bob_balance_before_stage_2 - cpd.amount_b_pledge - bob_release_fee - bob_acceptace_fee, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 2 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(bob_bc->check(), false, "balance callback check failed, see above");
//
// contract release
//
alice_bc->expect_balance();
alice_wlt->finish_contract(contract_id, BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_NORMAL);
CHECK_AND_ASSERT_MES(!alice_bc->called(), false, "balance callback check failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
// contract release tx is unconfirmed
alice_bc->expect_balance(alice_balance_before_stage_2 - alice_proposal_fee - cpd.amount_to_pay, m_alice_bob_start_amount - 5 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt,
alice_balance_before_stage_2 - alice_proposal_fee - cpd.amount_to_pay, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 5 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
cpd.amount_a_pledge, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(alice_bc->check(), false, "balance callback check failed, see above");
bob_bc->expect_balance(bob_balance_before_stage_2 - bob_release_fee - bob_acceptace_fee + cpd.amount_to_pay, m_alice_bob_start_amount - 2 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt,
bob_balance_before_stage_2 - bob_release_fee - bob_acceptace_fee + cpd.amount_to_pay, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 2 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
cpd.amount_b_pledge + cpd.amount_to_pay, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(bob_bc->check(), false, "balance callback check failed, see above");
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
// contract release tx is confirmed
alice_bc->expect_balance(alice_balance_before_stage_2 - alice_proposal_fee - cpd.amount_to_pay, m_alice_bob_start_amount - 5 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt,
alice_balance_before_stage_2 - alice_proposal_fee - cpd.amount_to_pay, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 5 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(alice_bc->check(), false, "balance callback check failed, see above");
bob_bc->expect_balance(bob_balance_before_stage_2 - bob_release_fee - bob_acceptace_fee + cpd.amount_to_pay, m_alice_bob_start_amount - 2 * m_alice_bob_start_chunk_amount);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt,
bob_balance_before_stage_2 - bob_release_fee - bob_acceptace_fee + cpd.amount_to_pay, // total
true, UINT64_MAX,
m_alice_bob_start_amount - 2 * m_alice_bob_start_chunk_amount, // unlocked
0, // mined
0, // awaited in
0 // awaited out
), false, "");
CHECK_AND_ASSERT_MES(bob_bc->check(), false, "balance callback check failed, see above");
return true;
}

View file

@ -158,3 +158,13 @@ struct escrow_acceptance_and_balance : public wallet_test
mutable uint64_t m_bob_fee_accept;
mutable bc_services::contract_private_details m_cpd;
};
struct escrow_balance : public wallet_test
{
escrow_balance();
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);
mutable uint64_t m_alice_bob_start_amount;
mutable uint64_t m_alice_bob_start_chunk_amount;
};

View file

@ -43,3 +43,47 @@ protected:
mutable test_generator generator;
std::shared_ptr<tools::i_core_proxy> m_core_proxy;
};
// wallet callback helper to check balance in wallet callbacks
// see escrow_balance test for usage example
struct wallet_callback_balance_checker : public tools::i_wallet2_callback
{
wallet_callback_balance_checker(const std::string& label) : m_label(label), m_result(true), m_called(false), m_balance(UINT64_MAX), m_unlocked_balance(UINT64_MAX), m_total_mined(UINT64_MAX) {}
void expect_balance(uint64_t balance = UINT64_MAX, uint64_t unlocked_balance = UINT64_MAX, uint64_t total_mined = UINT64_MAX)
{
m_balance = balance;
m_unlocked_balance = unlocked_balance;
m_total_mined = total_mined;
m_called = false;
}
virtual void on_transfer2(const tools::wallet_public::wallet_transfer_info& wti, uint64_t balance, uint64_t unlocked_balance, uint64_t total_mined) override
{
m_called = true;
m_result = false;
CHECK_AND_ASSERT_MES(m_balance == UINT64_MAX || balance == m_balance, (void)(0), m_label << " balance is incorrect: " << currency::print_money_brief(balance) << ", expected: " << currency::print_money_brief(m_balance));
CHECK_AND_ASSERT_MES(m_unlocked_balance == UINT64_MAX || unlocked_balance == m_unlocked_balance, (void)(0), m_label << " unlocked balance is incorrect: " << currency::print_money_brief(unlocked_balance) << ", expected: " << currency::print_money_brief(m_unlocked_balance));
CHECK_AND_ASSERT_MES(m_total_mined == UINT64_MAX || total_mined == m_total_mined, (void)(0), m_label << " total mined is incorrect: " << currency::print_money_brief(total_mined) << ", expected: " << currency::print_money_brief(m_total_mined));
m_result = true;
}
bool check()
{
bool result = m_result;
m_result = false; // clear result to avoid errorneous successive calls to check() without calling except_balance()
return result;
}
bool called()
{
return m_called;
}
bool m_result;
bool m_called;
std::string m_label;
uint64_t m_balance;
uint64_t m_unlocked_balance;
uint64_t m_total_mined;
};