1
0
Fork 0
forked from lthn/blockchain

atomics: started to work on tests + light refactoring

This commit is contained in:
cryptozoidberg 2021-02-04 01:49:38 +01:00
parent a7363cfcd3
commit 41ca8cff41
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
9 changed files with 386 additions and 116 deletions

View file

@ -3121,7 +3121,7 @@ bool blockchain_storage::get_est_height_from_date(uint64_t date, uint64_t& res_h
uint64_t iteration_coun = 0;
uint64_t current_low_boundary = 0;
uint64_t current_hight_boundary = m_db_blocks.size() - 1;
uint64_t current_height_boundary = m_db_blocks.size() - 1;
while (true)
{
iteration_coun++;
@ -3135,10 +3135,10 @@ bool blockchain_storage::get_est_height_from_date(uint64_t date, uint64_t& res_h
{
//we moved too much forward
current_hight_boundary = calculated_estimated_height;
CHECK_AND_ASSERT_MES(current_hight_boundary > current_low_boundary, true,
"Internal error: current_hight_boundary(" << current_hight_boundary << ") > current_low_boundary("<< current_low_boundary << ")");
uint64_t offset = (current_hight_boundary - current_low_boundary)/2;
current_height_boundary = calculated_estimated_height;
CHECK_AND_ASSERT_MES(current_height_boundary > current_low_boundary, true,
"Internal error: current_hight_boundary(" << current_height_boundary << ") > current_low_boundary("<< current_low_boundary << ")");
uint64_t offset = (current_height_boundary - current_low_boundary)/2;
if (offset <= 2)
{
//something really wrong with distribution of blocks, just use current_low_boundary to be sure that we didn't mess any transactions
@ -3154,9 +3154,9 @@ bool blockchain_storage::get_est_height_from_date(uint64_t date, uint64_t& res_h
{
//we too much in past
current_low_boundary = calculated_estimated_height;
CHECK_AND_ASSERT_MES(current_hight_boundary > current_low_boundary, true,
"Internal error: current_hight_boundary(" << current_hight_boundary << ") > current_low_boundary(" << current_low_boundary << ")");
uint64_t offset = (current_hight_boundary - current_low_boundary) / 2;
CHECK_AND_ASSERT_MES(current_height_boundary > current_low_boundary, true,
"Internal error: current_hight_boundary(" << current_height_boundary << ") > current_low_boundary(" << current_low_boundary << ")");
uint64_t offset = (current_height_boundary - current_low_boundary) / 2;
if (offset <= 2)
{
//something really wrong with distribution of blocks, just use current_low_boundary to be sure that we didn't mess any transactions

View file

@ -604,6 +604,12 @@ namespace currency
}
//---------------------------------------------------------------
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, const account_keys& self, uint8_t tx_outs_attr)
{
finalized_tx result = AUTO_VAL_INIT(result);
return construct_tx_out(de, tx_sec_key, output_index, tx, deriv_cache, self, result, tx_outs_attr);
}
//---------------------------------------------------------------
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, const account_keys& self, finalized_tx& result, uint8_t tx_outs_attr)
{
CHECK_AND_ASSERT_MES(de.addr.size() == 1 || (de.addr.size() > 1 && de.minimum_sigs <= de.addr.size()), false, "Invalid destination entry: amount: " << de.amount << " minimum_sigs: " << de.minimum_sigs << " addr.size(): " << de.addr.size());
@ -655,16 +661,17 @@ namespace currency
if (htlc_dest.htlc_hash == null_hash)
{
//we use deterministic origin, to make possible access origin on different wallets copies
std::string hltc_origin = generate_origin_for_htlc(htlc, self);
result.htlc_origin = generate_origin_for_htlc(htlc, self);
//calculate hash
if (htlc.flags&CURRENCY_TXOUT_HTLC_FLAGS_HASH_TYPE_MASK)
{
htlc.htlc_hash = crypto::sha256_hash(hltc_origin.data(), hltc_origin.size());
htlc.htlc_hash = crypto::sha256_hash(result.htlc_origin.data(), result.htlc_origin.size());
}
else
{
crypto::hash160 h160 = crypto::RIPEMD160_hash(hltc_origin.data(), hltc_origin.size());
crypto::hash160 h160 = crypto::RIPEMD160_hash(result.htlc_origin.data(), result.htlc_origin.size());
std::memcpy(&htlc.htlc_hash, &h160, sizeof(h160));
}
}
@ -1076,7 +1083,7 @@ namespace currency
shuffle,
flags);
}
//---------------------------------------------------------------
bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources,
const std::vector<tx_destination_entry>& destinations,
const std::vector<extra_v>& extra,
@ -1090,6 +1097,43 @@ namespace currency
bool shuffle,
uint64_t flags)
{
//extra copy operation, but creating transaction is not sensitive to this
finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
ftp.sources = sources;
ftp.prepared_destinations = destinations;
ftp.extra = extra;
ftp.attachments = attachments;
ftp.unlock_time = unlock_time;
ftp.crypt_address = crypt_destination_addr;
ftp.expiration_time = 0;
ftp.tx_outs_attr = tx_outs_attr;
ftp.shuffle = shuffle;
ftp.flags = flags;
finalized_tx ft = AUTO_VAL_INIT(ft);
bool r = construct_tx(sender_account_keys, ftp, ft);
tx = ft.tx;
one_time_secret_key = ft.one_time_key;
return r;
}
//---------------------------------------------------------------
bool construct_tx(const account_keys& sender_account_keys, const finalize_tx_param& ftp, finalized_tx& result)
{
const std::vector<tx_source_entry>& sources = ftp.sources;
const std::vector<tx_destination_entry>& destinations = ftp.prepared_destinations;
const std::vector<extra_v>& extra = ftp.extra;
const std::vector<attachment_v>& attachments = ftp.attachments;
const uint64_t& unlock_time = ftp.unlock_time;
const account_public_address& crypt_destination_addr = ftp.crypt_address;
const uint64_t& expiration_time = ftp.expiration_time;
const uint8_t& tx_outs_attr = ftp.tx_outs_attr;
const bool& shuffle = ftp.shuffle;
const uint64_t& flags = ftp.flags;
transaction& tx = result.tx;
crypto::secret_key& one_time_secret_key = result.one_time_key;
result.ftp = ftp;
CHECK_AND_ASSERT_MES(destinations.size() <= CURRENCY_TX_MAX_ALLOWED_OUTS, false, "Too many outs (" << destinations.size() << ")! Tx can't be constructed.");
bool watch_only_mode = sender_account_keys.spend_secret_key == null_skey;
@ -1290,7 +1334,7 @@ namespace currency
for(const tx_destination_entry& dst_entr : shuffled_dsts)
{
CHECK_AND_ASSERT_MES(dst_entr.amount > 0, false, "Destination with wrong amount: " << dst_entr.amount);
bool r = construct_tx_out(dst_entr, txkey.sec, output_index, tx, deriv_cache, sender_account_keys, tx_outs_attr);
bool r = construct_tx_out(dst_entr, txkey.sec, output_index, tx, deriv_cache, sender_account_keys, result, tx_outs_attr);
CHECK_AND_ASSERT_MES(r, false, "Failed to construc tx out");
output_index++;
summary_outs_money += dst_entr.amount;

View file

@ -132,9 +132,60 @@ namespace currency
END_KV_SERIALIZE_MAP()
};
struct htlc_info
struct htlc_info
{
bool hltc_our_out_is_before_expiration;
};
struct finalize_tx_param
{
bool hltc_our_out_is_before_expiration;
uint64_t unlock_time;
std::vector<currency::extra_v> extra;
std::vector<currency::attachment_v> attachments;
currency::account_public_address crypt_address;
uint8_t tx_outs_attr;
bool shuffle;
uint8_t flags;
crypto::hash multisig_id;
std::vector<currency::tx_source_entry> sources;
std::vector<uint64_t> selected_transfers;
std::vector<currency::tx_destination_entry> prepared_destinations;
uint64_t expiration_time;
crypto::public_key spend_pub_key; // only for validations
BEGIN_SERIALIZE_OBJECT()
FIELD(unlock_time)
FIELD(extra)
FIELD(attachments)
FIELD(crypt_address)
FIELD(tx_outs_attr)
FIELD(shuffle)
FIELD(flags)
FIELD(multisig_id)
FIELD(sources)
FIELD(selected_transfers)
FIELD(prepared_destinations)
FIELD(expiration_time)
FIELD(spend_pub_key)
END_SERIALIZE()
};
struct finalized_tx
{
currency::transaction tx;
crypto::secret_key one_time_key;
finalize_tx_param ftp;
std::string htlc_origin;
std::vector<serializable_pair<uint64_t, crypto::key_image>> outs_key_images; // pairs (out_index, key_image) for each change output
BEGIN_SERIALIZE_OBJECT()
FIELD(tx)
FIELD(one_time_key)
FIELD(ftp)
FIELD(htlc_origin)
FIELD(outs_key_images)
END_SERIALIZE()
};
@ -163,6 +214,7 @@ namespace currency
//---------------------------------------------------------------
uint64_t get_string_uint64_hash(const std::string& str);
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, const account_keys& self, finalized_tx& result, uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED);
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, const account_keys& self, uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED);
bool validate_alias_name(const std::string& al);
bool validate_password(const std::string& password);
@ -186,6 +238,7 @@ namespace currency
uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED,
bool shuffle = true,
uint64_t flags = 0);
bool construct_tx(const account_keys& sender_account_keys,
const std::vector<tx_source_entry>& sources,
const std::vector<tx_destination_entry>& destinations,
@ -200,6 +253,9 @@ namespace currency
bool shuffle = true,
uint64_t flags = 0);
bool construct_tx(const account_keys& sender_account_keys, const finalize_tx_param& param, finalized_tx& result);
bool sign_multisig_input_in_tx(currency::transaction& tx, size_t ms_input_index, const currency::account_keys& keys, const currency::transaction& source_tx, bool *p_is_input_fully_signed = nullptr);
bool sign_extra_alias_entry(extra_alias_entry& ai, const crypto::public_key& pkey, const crypto::secret_key& skey);

View file

@ -800,7 +800,7 @@ void wallet2::accept_proposal(const crypto::hash& contract_id, uint64_t b_accept
construct_param.extra.push_back(tsa);
//build transaction
finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
prepare_transaction(construct_param, ftp, tx);
mark_transfers_as_spent(ftp.selected_transfers, std::string("contract <") + epee::string_tools::pod_to_hex(contract_id) + "> has been accepted with tx <" + epee::string_tools::pod_to_hex(get_transaction_hash(tx)) + ">");
@ -930,7 +930,7 @@ void wallet2::request_cancel_contract(const crypto::hash& contract_id, uint64_t
construct_param.crypt_address = contr_it->second.private_detailes.b_addr;
construct_param.split_strategy_id = detail::ssi_digit;
finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
prepare_transaction(construct_param, ftp);
currency::transaction tx = AUTO_VAL_INIT(tx);
crypto::secret_key sk = AUTO_VAL_INIT(sk);
@ -2891,7 +2891,7 @@ void wallet2::sign_transfer(const std::string& tx_sources_blob, std::string& sig
std::string decrypted_src_blob = crypto::chacha_crypt(tx_sources_blob, m_account.get_keys().view_secret_key);
// deserialize args
finalized_tx ft = AUTO_VAL_INIT(ft);
currency::finalized_tx ft = AUTO_VAL_INIT(ft);
bool r = t_unserializable_object_from_blob(ft.ftp, decrypted_src_blob);
THROW_IF_FALSE_WALLET_EX(r, error::wallet_common_error, "Failed to decrypt tx sources blob");
@ -2973,7 +2973,7 @@ void wallet2::submit_transfer(const std::string& signed_tx_blob, currency::trans
std::string decrypted_src_blob = crypto::chacha_crypt(signed_tx_blob, m_account.get_keys().view_secret_key);
// deserialize tx data
finalized_tx ft = AUTO_VAL_INIT(ft);
currency::finalized_tx ft = AUTO_VAL_INIT(ft);
bool r = t_unserializable_object_from_blob(ft, decrypted_src_blob);
THROW_IF_FALSE_WALLET_EX(r, error::wallet_common_error, "Failed to decrypt signed tx data");
tx = ft.tx;
@ -3741,7 +3741,7 @@ void wallet2::build_escrow_release_templates(crypto::hash multisig_id,
tsa.instruction = BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_NORMAL;
construct_params.extra.push_back(tsa);
{
finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
prepare_transaction(construct_params, ftp);
crypto::secret_key sk = AUTO_VAL_INIT(sk);
finalize_transaction(ftp, tx_release_template, sk, false);
@ -3757,7 +3757,7 @@ void wallet2::build_escrow_release_templates(crypto::hash multisig_id,
tsa.instruction = BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_BURN;
construct_params.extra.push_back(tsa);
{
finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
prepare_transaction(construct_params, ftp);
crypto::secret_key sk = AUTO_VAL_INIT(sk);
finalize_transaction(ftp, tx_burn_template, sk, false);
@ -3777,7 +3777,7 @@ void wallet2::build_escrow_cancel_template(crypto::hash multisig_id,
"multisig id out amount no more than escrow total amount");
construct_tx_param construct_params = AUTO_VAL_INIT(construct_params);
finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
construct_params.fee = it->second.amount() - (ecrow_details.amount_a_pledge + ecrow_details.amount_to_pay + ecrow_details.amount_b_pledge);
construct_params.multisig_id = multisig_id;
construct_params.split_strategy_id = detail::ssi_digit;
@ -3859,7 +3859,7 @@ void wallet2::build_escrow_template(const bc_services::contract_private_details&
ctp.attachments.push_back(att);
}
finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
prepare_transaction(ctp, ftp, tx);
selected_transfers = ftp.selected_transfers;
@ -3991,7 +3991,7 @@ void wallet2::send_escrow_proposal(const bc_services::contract_private_details&
ctp.tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED;
ctp.unlock_time = unlock_time;
finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
try
{
prepare_transaction(ctp, ftp);
@ -4013,22 +4013,20 @@ void wallet2::send_escrow_proposal(const bc_services::contract_private_details&
print_tx_sent_message(tx, "(from multisig)", fee);
}
//----------------------------------------------------------------------------------------------------
void wallet2::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)
void wallet2::create_htlc_proposal(uint64_t amount, const currency::account_public_address& addr, uint64_t lock_blocks_count, currency::transaction &tx, std::string &origin)
{
std::vector<currency::extra_v> extra;
std::vector<currency::attachment_v> attachments;
std::vector<tx_destination_entry> dst;
dst.resize(1);
dst.back().addr.push_back(addr);
dst.back().amount = amount;
destination_option_htlc_out& htlc_option = dst.back().htlc_options;
construct_tx_param ctp = get_default_construct_tx_param();
ctp.fee = TX_DEFAULT_FEE;
ctp.dsts.resize(1);
ctp.dsts.back().addr.push_back(addr);
ctp.dsts.back().amount = amount;
destination_option_htlc_out& htlc_option = ctp.dsts.back().htlc_options;
htlc_option.expiration = 740; //about 12 hours
htlc_option.htlc_hash = htlc_hash;
htlc_option.htlc_hash = null_hash;
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);
finalized_tx ft = AUTO_VAL_INIT(ft);
this->transfer(ctp, ft, true, nullptr);
origin = ft.htlc_origin;
}
//----------------------------------------------------------------------------------------------------
void wallet2::get_list_of_active_htlc(bool only_redeem_txs, std::list<wallet_public::htlc_entry_info>& htlcs)
@ -4840,7 +4838,7 @@ void wallet2::prepare_tx_destinations(uint64_t needed_money,
}
}
//----------------------------------------------------------------------------------------------------
void wallet2::prepare_transaction(construct_tx_param& ctp, finalize_tx_param& ftp, const currency::transaction& tx_for_mode_separate /* = currency::transaction() */)
void wallet2::prepare_transaction(construct_tx_param& ctp, currency::finalize_tx_param& ftp, const currency::transaction& tx_for_mode_separate /* = currency::transaction() */)
{
TIME_MEASURE_START_MS(get_needed_money_time);
uint64_t needed_money = get_needed_money(ctp.fee, ctp.dsts);
@ -4911,7 +4909,15 @@ void wallet2::prepare_transaction(construct_tx_param& ctp, finalize_tx_param& ft
LOG_LEVEL_0);*/
}
//----------------------------------------------------------------------------------------------------
void wallet2::finalize_transaction(const finalize_tx_param& ftp, currency::transaction& tx, crypto::secret_key& tx_key, bool broadcast_tx, bool store_tx_secret_key /* = true */)
void wallet2::finalize_transaction(const currency::finalize_tx_param& ftp, currency::transaction& tx, crypto::secret_key& tx_key, bool broadcast_tx, bool store_tx_secret_key /* = true */)
{
currency::finalized_tx result = AUTO_VAL_INIT(result);
finalize_transaction(ftp, result, broadcast_tx, store_tx_secret_key);
tx = result.tx;
tx_key = result.one_time_key;
}
//----------------------------------------------------------------------------------------------------
void wallet2::finalize_transaction(const currency::finalize_tx_param& ftp, currency::finalized_tx& result, bool broadcast_tx, bool store_tx_secret_key /* = true */)
{
// NOTE: if broadcast_tx == true callback rise_on_transfer2() may be called at the end of this function.
// That callback may call balance(), so it's important to have all used/spending transfers
@ -4922,18 +4928,7 @@ void wallet2::finalize_transaction(const finalize_tx_param& ftp, currency::trans
//TIME_MEASURE_START_MS(construct_tx_time);
bool r = currency::construct_tx(m_account.get_keys(),
ftp.sources,
ftp.prepared_destinations,
ftp.extra,
ftp.attachments,
tx,
tx_key,
ftp.unlock_time,
ftp.crypt_address,
0, // expiration time
ftp.tx_outs_attr,
ftp.shuffle,
ftp.flags);
ftp, result);
//TIME_MEASURE_FINISH_MS(construct_tx_time);
THROW_IF_FALSE_WALLET_EX(r, error::tx_not_constructed, ftp.sources, ftp.prepared_destinations, ftp.unlock_time);
@ -4946,24 +4941,24 @@ void wallet2::finalize_transaction(const finalize_tx_param& ftp, currency::trans
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it != m_multisig_transfers.end(), "can't find multisig_id: " << ftp.multisig_id);
const currency::transaction& ms_source_tx = it->second.m_ptx_wallet_info->m_tx;
bool is_tx_input_fully_signed = false;
r = sign_multisig_input_in_tx(tx, 0, m_account.get_keys(), ms_source_tx, &is_tx_input_fully_signed); // it's assumed that ms input is the first one (index 0)
r = sign_multisig_input_in_tx(result.tx, 0, m_account.get_keys(), ms_source_tx, &is_tx_input_fully_signed); // it's assumed that ms input is the first one (index 0)
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(r && !is_tx_input_fully_signed, "sign_multisig_input_in_tx failed: r = " << r << ", is_tx_input_fully_signed = " << is_tx_input_fully_signed);
}
//TIME_MEASURE_FINISH_MS(sign_ms_input_time);
THROW_IF_FALSE_WALLET_EX(get_object_blobsize(tx) < CURRENCY_MAX_TRANSACTION_BLOB_SIZE, error::tx_too_big, tx, m_upper_transaction_size_limit);
THROW_IF_FALSE_WALLET_EX(get_object_blobsize(result.tx) < CURRENCY_MAX_TRANSACTION_BLOB_SIZE, error::tx_too_big, result.tx, m_upper_transaction_size_limit);
if (store_tx_secret_key)
m_tx_keys.insert(std::make_pair(get_transaction_hash(tx), tx_key));
m_tx_keys.insert(std::make_pair(get_transaction_hash(result.tx), result.one_time_key));
//TIME_MEASURE_START(send_transaction_to_network_time);
if (broadcast_tx)
send_transaction_to_network(tx);
send_transaction_to_network(result.tx);
//TIME_MEASURE_FINISH(send_transaction_to_network_time);
//TIME_MEASURE_START(add_sent_tx_detailed_info_time);
if (broadcast_tx)
add_sent_tx_detailed_info(tx, ftp.prepared_destinations, ftp.selected_transfers);
add_sent_tx_detailed_info(result.tx, ftp.prepared_destinations, ftp.selected_transfers);
//TIME_MEASURE_FINISH(add_sent_tx_detailed_info_time);
/* TODO
@ -5035,7 +5030,7 @@ const construct_tx_param& wallet2::get_default_construct_tx_param()
return ctp;
}
//----------------------------------------------------------------------------------------------------
bool wallet2::store_unsigned_tx_to_file_and_reserve_transfers(const finalize_tx_param& ftp, const std::string& filename, std::string* p_unsigned_tx_blob_str /* = nullptr */)
bool wallet2::store_unsigned_tx_to_file_and_reserve_transfers(const currency::finalize_tx_param& ftp, const std::string& filename, std::string* p_unsigned_tx_blob_str /* = nullptr */)
{
TIME_MEASURE_START(store_unsigned_tx_time);
blobdata bl = t_serializable_object_to_blob(ftp);
@ -5096,13 +5091,23 @@ void wallet2::transfer(construct_tx_param& ctp,
currency::transaction &tx,
bool send_to_network,
std::string* p_unsigned_filename_or_tx_blob_str)
{
currency::finalized_tx result = AUTO_VAL_INIT(result);
transfer(ctp, result, send_to_network, p_unsigned_filename_or_tx_blob_str);
tx = result.tx;
}
//----------------------------------------------------------------------------------------------------
void wallet2::transfer(construct_tx_param& ctp,
currency::finalized_tx& result,
bool send_to_network,
std::string* p_unsigned_filename_or_tx_blob_str)
{
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(!is_auditable() || !is_watch_only(), "You can't initiate coins transfer using an auditable watch-only wallet."); // btw, watch-only wallets can call transfer() within cold-signing process
check_and_throw_if_self_directed_tx_with_payment_id_requested(ctp);
TIME_MEASURE_START(prepare_transaction_time);
finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
prepare_transaction(ctp, ftp);
TIME_MEASURE_FINISH(prepare_transaction_time);
@ -5115,18 +5120,17 @@ void wallet2::transfer(construct_tx_param& ctp,
}
TIME_MEASURE_START(mark_transfers_as_spent_time);
mark_transfers_as_spent(ftp.selected_transfers, std::string("money transfer, tx: ") + epee::string_tools::pod_to_hex(get_transaction_hash(tx)));
mark_transfers_as_spent(ftp.selected_transfers, std::string("money transfer, tx: ") + epee::string_tools::pod_to_hex(get_transaction_hash(result.tx)));
TIME_MEASURE_FINISH(mark_transfers_as_spent_time);
TIME_MEASURE_START(finalize_transaction_time);
try
{
crypto::secret_key sk = AUTO_VAL_INIT(sk);
finalize_transaction(ftp, tx, sk, send_to_network);
finalize_transaction(ftp, result, send_to_network);
}
catch (...)
{
clear_transfers_from_flag(ftp.selected_transfers, WALLET_TRANSFER_DETAIL_FLAG_SPENT, std::string("exception on money transfer, tx: ") + epee::string_tools::pod_to_hex(get_transaction_hash(tx)));
clear_transfers_from_flag(ftp.selected_transfers, WALLET_TRANSFER_DETAIL_FLAG_SPENT, std::string("exception on money transfer, tx: ") + epee::string_tools::pod_to_hex(get_transaction_hash(result.tx)));
throw;
}
TIME_MEASURE_FINISH(finalize_transaction_time);
@ -5139,7 +5143,7 @@ void wallet2::transfer(construct_tx_param& ctp,
<< ", mark_transfers_as_spent_time: " << print_fixed_decimal_point(mark_transfers_as_spent_time, 3)
, LOG_LEVEL_0);
print_tx_sent_message(tx, std::string() + "(transfer)", ctp.fee);
print_tx_sent_message(result.tx, std::string() + "(transfer)", ctp.fee);
}
//----------------------------------------------------------------------------------------------------
void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public_address& destination_addr, uint64_t threshold_amount, const currency::payment_id_t& payment_id,
@ -5209,7 +5213,7 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public
THROW_IF_FALSE_WALLET_EX(scanty_outs.empty(), error::not_enough_outs_to_mix, scanty_outs, fake_outs_count);
}
finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
if (!payment_id.empty())
set_payment_id_to_tx(ftp.attachments, payment_id);
// put encrypted payer info into the extra
@ -5232,7 +5236,7 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public
{ return t == rc_ok ? "rc_ok" : t == rc_too_few_outputs ? "rc_too_few_outputs" : t == rc_too_many_outputs ? "rc_too_many_outputs" : t == rc_create_tx_failed ? "rc_create_tx_failed" : "unknown"; };
auto try_construct_tx = [this, &selected_transfers, &rpc_get_random_outs_resp, &fake_outs_count, &fee, &destination_addr]
(size_t st_index_upper_boundary, finalize_tx_param& ftp, uint64_t& amount_swept) -> try_construct_result_t
(size_t st_index_upper_boundary, currency::finalize_tx_param& ftp, uint64_t& amount_swept) -> try_construct_result_t
{
// prepare inputs
amount_swept = 0;
@ -5319,7 +5323,7 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public
WLT_LOG_L1("sweep_below: first try of try_construct_tx(" << st_index_upper_boundary << ") returned " << get_result_t_str(res));
size_t low_bound = 0;
size_t high_bound = st_index_upper_boundary;
finalize_tx_param ftp_ok = ftp;
currency::finalize_tx_param ftp_ok = ftp;
for (;;)
{
if (low_bound + 1 >= high_bound)

View file

@ -286,52 +286,52 @@ namespace tools
bool perform_packing;
};
struct finalize_tx_param
{
uint64_t unlock_time;
std::vector<currency::extra_v> extra;
std::vector<currency::attachment_v> attachments;
currency::account_public_address crypt_address;
uint8_t tx_outs_attr;
bool shuffle;
uint8_t flags;
crypto::hash multisig_id;
std::vector<currency::tx_source_entry> sources;
std::vector<uint64_t> selected_transfers;
std::vector<currency::tx_destination_entry> prepared_destinations;
crypto::public_key spend_pub_key; // only for validations
BEGIN_SERIALIZE_OBJECT()
FIELD(unlock_time)
FIELD(extra)
FIELD(attachments)
FIELD(crypt_address)
FIELD(tx_outs_attr)
FIELD(shuffle)
FIELD(flags)
FIELD(multisig_id)
FIELD(sources)
FIELD(selected_transfers)
FIELD(prepared_destinations)
FIELD(spend_pub_key)
END_SERIALIZE()
};
struct finalized_tx
{
currency::transaction tx;
crypto::secret_key one_time_key;
finalize_tx_param ftp;
std::vector<serializable_pair<uint64_t, crypto::key_image>> outs_key_images; // pairs (out_index, key_image) for each change output
BEGIN_SERIALIZE_OBJECT()
FIELD(tx)
FIELD(one_time_key)
FIELD(ftp)
FIELD(outs_key_images)
END_SERIALIZE()
};
// struct currency::finalize_tx_param
// {
// uint64_t unlock_time;
// std::vector<currency::extra_v> extra;
// std::vector<currency::attachment_v> attachments;
// currency::account_public_address crypt_address;
// uint8_t tx_outs_attr;
// bool shuffle;
// uint8_t flags;
// crypto::hash multisig_id;
// std::vector<currency::tx_source_entry> sources;
// std::vector<uint64_t> selected_transfers;
// std::vector<currency::tx_destination_entry> prepared_destinations;
//
// crypto::public_key spend_pub_key; // only for validations
//
// BEGIN_SERIALIZE_OBJECT()
// FIELD(unlock_time)
// FIELD(extra)
// FIELD(attachments)
// FIELD(crypt_address)
// FIELD(tx_outs_attr)
// FIELD(shuffle)
// FIELD(flags)
// FIELD(multisig_id)
// FIELD(sources)
// FIELD(selected_transfers)
// FIELD(prepared_destinations)
// FIELD(spend_pub_key)
// END_SERIALIZE()
// };
//
// struct currency::finalized_tx
// {
// currency::transaction tx;
// crypto::secret_key one_time_key;
// currency::finalize_tx_param ftp;
// std::vector<serializable_pair<uint64_t, crypto::key_image>> outs_key_images; // pairs (out_index, key_image) for each change output
//
// BEGIN_SERIALIZE_OBJECT()
// FIELD(tx)
// FIELD(one_time_key)
// FIELD(ftp)
// FIELD(outs_key_images)
// END_SERIALIZE()
// };
class wallet2
{
@ -580,6 +580,12 @@ namespace tools
currency::transaction &tx,
bool send_to_network,
std::string* p_unsigned_filename_or_tx_blob_str);
void transfer(construct_tx_param& ctp,
currency::finalized_tx& result,
bool send_to_network,
std::string* p_unsigned_filename_or_tx_blob_str);
template<typename destination_split_strategy_t>
void transfer_from_contract(
@ -820,8 +826,10 @@ namespace tools
const std::list<expiration_entry_info>& get_expiration_entries() const { return m_money_expirations; };
bool get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key) const;
void prepare_transaction(construct_tx_param& ctp, finalize_tx_param& ftp, const currency::transaction& tx_for_mode_separate = currency::transaction());
void finalize_transaction(const finalize_tx_param& ftp, currency::transaction& tx, crypto::secret_key& tx_key, bool broadcast_tx, bool store_tx_secret_key = true);
void prepare_transaction(construct_tx_param& ctp, currency::finalize_tx_param& ftp, const currency::transaction& tx_for_mode_separate = currency::transaction());
void finalize_transaction(const currency::finalize_tx_param& ftp, currency::transaction& tx, crypto::secret_key& tx_key, bool broadcast_tx, bool store_tx_secret_key = true);
void finalize_transaction(const currency::finalize_tx_param& ftp, currency::finalized_tx& result, bool broadcast_tx, bool store_tx_secret_key = true );
std::string get_log_prefix() const { return m_log_prefix; }
static uint64_t get_max_unlock_time_from_receive_indices(const currency::transaction& tx, const money_transfer2_details& td);
@ -836,7 +844,7 @@ namespace tools
opener-hash will be given by other side
*/
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 = currency::null_hash);
currency::transaction &tx, std::string &origin);
void get_list_of_active_htlc(bool only_redeem_txs, std::list<wallet_public::htlc_entry_info>& htlcs);
void redeem_htlc(const crypto::hash& htlc_tx_id, std::string origin);
@ -960,7 +968,7 @@ private:
void exception_handler() const;
uint64_t get_minimum_allowed_fee_for_contract(const crypto::hash& ms_id);
bool generate_packing_transaction_if_needed(currency::transaction& tx, uint64_t fake_outputs_number);
bool store_unsigned_tx_to_file_and_reserve_transfers(const finalize_tx_param& ftp, const std::string& filename, std::string* p_unsigned_tx_blob_str = nullptr);
bool store_unsigned_tx_to_file_and_reserve_transfers(const currency::finalize_tx_param& ftp, const std::string& filename, std::string* p_unsigned_tx_blob_str = nullptr);
void check_and_throw_if_self_directed_tx_with_payment_id_requested(const construct_tx_param& ctp);
void push_new_block_id(const crypto::hash& id, uint64_t height);
bool lookup_item_around(uint64_t i, std::pair<uint64_t, crypto::hash>& result);

View file

@ -0,0 +1,136 @@
// Copyright (c) 2014-2021 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "chaingen.h"
#include "escrow_wallet_tests.h"
#include "random_helper.h"
#include "chaingen_helpers.h"
#include "atomic_tests.h"
using namespace epee;
using namespace crypto;
using namespace currency;
//==============================================================================================================================
struct wallet_tests_callback_handler : public tools::i_wallet2_callback
{
virtual void on_transfer2(const tools::wallet_public::wallet_transfer_info& wti, uint64_t balance, uint64_t unlocked_balance, uint64_t total_mined)
{
all_wtis.push_back(wti);
}
std::vector<tools::wallet_public::wallet_transfer_info> all_wtis;
};
atomic_simple_test::atomic_simple_test()
{
REGISTER_CALLBACK_METHOD(atomic_simple_test, c1);
}
bool atomic_simple_test::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_simple_test::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
epee::debug::get_set_enable_assert(true, true);
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler([&](){epee::debug::get_set_enable_assert(true, false); });
/*
let's pretend that we have two different blockchains: A and B
Alice and Bob want to have atomic swap via htlc, both has wallets in blockchain A and B
Steps are following:
1. Alice initiate swap by sending to Bob HTLC in blockchain A
2. Bob see HTLC to his address in blockchain A and create HTLC with
the same hash addressed to Alice in blockchain B
3. Alice see HTLC addressed to her in blockchain B and creates there redeem transaction, which reveals HTLC origin
4. Bob observe origin revealed by Alice in blockchain B and create redeem transaction in blockchain A
5. Everybody check balances and celebrate successful atomic swap
*/
currency::account_base accunt_alice_blockchain_a;
currency::account_base accunt_alice_blockchain_b;
currency::account_base accunt_bob_blockchain_a;
currency::account_base accunt_bob_blockchain_b;
accunt_alice_blockchain_a.generate();
accunt_alice_blockchain_b.generate();
accunt_bob_blockchain_a.generate();
accunt_bob_blockchain_b.generate();
LOG_PRINT_MAGENTA("Mining Address: " << currency::get_account_address_as_str(m_mining_accunt.get_public_address()), LOG_LEVEL_0);
LOG_PRINT_MAGENTA("Alice [A] Address: " << currency::get_account_address_as_str(accunt_alice_blockchain_a.get_public_address()), LOG_LEVEL_0);
LOG_PRINT_MAGENTA("Alice [B] Address: " << currency::get_account_address_as_str(accunt_alice_blockchain_b.get_public_address()), LOG_LEVEL_0);
LOG_PRINT_MAGENTA("Bob [A] Address: " << currency::get_account_address_as_str(accunt_bob_blockchain_a.get_public_address()), LOG_LEVEL_0);
LOG_PRINT_MAGENTA("Bob [B] Address: " << currency::get_account_address_as_str(accunt_bob_blockchain_b.get_public_address()), LOG_LEVEL_0);
#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, accunt_alice_blockchain_a.get_public_address());
LOG_PRINT_MAGENTA("Transaction sent to Alice A: " << transfer_amount, LOG_LEVEL_0);
miner_wlt->transfer(transfer_amount, accunt_bob_blockchain_a.get_public_address());
LOG_PRINT_MAGENTA("Transaction sent to Bob 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");
//create wallet instances and calculate balances
std::shared_ptr<tools::wallet2> alice_a_wlt_instance = init_playtime_test_wallet(events, c, accunt_alice_blockchain_a);
std::shared_ptr<tools::wallet2> alice_b_wlt_instance = init_playtime_test_wallet(events, c, accunt_alice_blockchain_b);
std::shared_ptr<tools::wallet2> bob_a_wlt_instance = init_playtime_test_wallet(events, c, accunt_bob_blockchain_a);
std::shared_ptr<tools::wallet2> bob_b_wlt_instance = init_playtime_test_wallet(events, c, accunt_bob_blockchain_b);
// std::shared_ptr<wallet_tests_callback_handler> backend_mock(new wallet_tests_callback_handler());
// alice_a_wlt_instance->callback(backend_mock);
alice_a_wlt_instance->refresh();
alice_b_wlt_instance->refresh();
bob_a_wlt_instance->refresh();
bob_a_wlt_instance->refresh();
CHECK_AND_FORCE_ASSERT_MES(alice_a_wlt_instance->balance() == transfer_amount, false, "Incorrect balance");
CHECK_AND_FORCE_ASSERT_MES(bob_a_wlt_instance->balance() == transfer_amount, false, "Incorrect balance");
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, bob_a_wlt_instance->get_account().get_public_address(), 20, res_tx, alice_origin);
return r;
}
//------------------------------------------------------------------------------

View file

@ -0,0 +1,19 @@
// Copyright (c) 2014-2021 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include "chaingen.h"
#include "wallet_tests_basic.h"
struct atomic_simple_test : public wallet_test
{
atomic_simple_test();
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;
};

View file

@ -1020,6 +1020,8 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(hard_fork_2_incorrect_alias_update<true>);
GENERATE_AND_PLAY(hard_fork_2_incorrect_alias_update<false>);
// atomics
GENERATE_AND_PLAY(atomic_simple_test);
// GENERATE_AND_PLAY(gen_block_reward);
// END OF TESTS */

View file

@ -38,3 +38,4 @@
#include "hard_fork_1_bad_pos_source.h"
#include "hard_fork_1.h"
#include "hard_fork_2.h"
#include "atomic_tests.h"