1
0
Fork 0
forked from lthn/blockchain

in the middle of prepare_tx_sources_htlc

This commit is contained in:
cryptozoidberg 2021-02-02 19:02:28 +01:00
parent 0b8e651ce2
commit a31670f225
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
8 changed files with 166 additions and 37 deletions

View file

@ -39,3 +39,4 @@
#define API_RETURN_CODE_UNINITIALIZED "UNINITIALIZED"
#define API_RETURN_CODE_TX_IS_TOO_BIG "TX_IS_TOO_BIG"
#define API_RETURN_CODE_TX_REJECTED "TX_REJECTED"
#define API_RETURN_CODE_HTLC_ORIGIN_HASH_MISSMATCHED "HTLC_ORIGIN_HASH_MISSMATCHED"

View file

@ -56,4 +56,12 @@ namespace crypto {
return h;
}
hash RIPEMD160_hash_256(const void *data, size_t length)
{
hash160 h = RIPEMD160_hash(data, length);
hash h256 = AUTO_VAL_INIT(h256);
memcpy(&h256, &h, sizeof(h));
return h256;
}
}

View file

@ -17,6 +17,7 @@ namespace crypto {
void RIPEMD160_hash(const void *data, size_t length, hash160 &h);
hash160 RIPEMD160_hash(const void *data, size_t length);
hash RIPEMD160_hash_256(const void *data, size_t length);
}

View file

@ -591,11 +591,11 @@ namespace currency
// return true;
// }
//---------------------------------------------------------------
std::string generate_origin_for_htlc(const crypto::public_key& redeem, const crypto::public_key& refund, const account_keys& acc_keys)
std::string generate_origin_for_htlc(const txout_htlc& htlc, const account_keys& acc_keys)
{
std::string blob;
string_tools::apped_pod_to_strbuff(blob, redeem);
string_tools::apped_pod_to_strbuff(blob, refund);
string_tools::apped_pod_to_strbuff(blob, htlc.pkey_redeem);
string_tools::apped_pod_to_strbuff(blob, htlc.pkey_refund);
string_tools::apped_pod_to_strbuff(blob, acc_keys.spend_secret_key);
crypto::hash origin_hs = crypto::cn_fast_hash(blob.data(), blob.size());
std::string origin_blob;
@ -635,12 +635,13 @@ namespace currency
tx_out out;
out.amount = de.amount;
if (de.htlc)
if (de.additional_options.type() == typeid(destination_option_htlc_out))
{
const destination_option_htlc_out& htlc_dest = boost::get<destination_option_htlc_out>(de.additional_options);
//out htlc
CHECK_AND_ASSERT_MES(target_keys.size() == 1, false, "Unexpected htl keys count = " << target_keys.size() << ", expected ==1");
txout_htlc htlc = AUTO_VAL_INIT(htlc);
htlc.expiration = de.unlock_time;
htlc.expiration = htlc_dest.expiration;
htlc.flags = 0; //0 - SHA256, 1 - RIPEMD160, by default leave SHA256
//receiver key
htlc.pkey_redeem = *target_keys.begin();
@ -651,10 +652,10 @@ namespace currency
CHECK_AND_ASSERT_MES(r, false, "failed to derive_public_key_from_target_address");
htlc.pkey_refund = out_eph_public_key;
if (de.htlc_hash == null_hash)
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.pkey_redeem, htlc.pkey_refund, self);
std::string hltc_origin = generate_origin_for_htlc(htlc, self);
//calculate hash
if (htlc.flags&CURRENCY_TXOUT_HTLC_FLAGS_HASH_TYPE_MASK)
@ -669,7 +670,7 @@ namespace currency
}
else
{
htlc.htlc_hash = de.htlc_hash;
htlc.htlc_hash = htlc_dest.htlc_hash;
}
}

View file

@ -299,7 +299,7 @@ namespace currency
void append_per_block_increments_for_tx(const transaction& tx, std::unordered_map<uint64_t, uint32_t>& gindices);
std::string get_word_from_timstamp(uint64_t timestamp, bool use_password);
uint64_t get_timstamp_from_word(std::string word, bool& password_used);
std::string generate_origin_for_htlc(const crypto::public_key& redeem, const crypto::public_key& refund, const account_keys& acc_keys);
std::string generate_origin_for_htlc(const txout_htlc& htlc, const account_keys& acc_keys);
template<class t_txin_v>
typename std::conditional<std::is_const<t_txin_v>::value, const std::vector<txin_etc_details_v>, std::vector<txin_etc_details_v> >::type& get_txin_etc_options(t_txin_v& in)
{

View file

@ -28,6 +28,7 @@ namespace currency
size_t ms_sigs_count; //if txin_multisig: must be equal to output's minimum_sigs
size_t ms_keys_count; //if txin_multisig: must be equal to size of output's keys container
bool separately_signed_tx_complete; //for separately signed tx only: denotes the last source entry in complete tx to explicitly mark the final step of tx creation
std::string htlc_origin; //for htlc, specify origin
bool is_multisig() const { return ms_sigs_count > 0; }
@ -42,23 +43,43 @@ namespace currency
FIELD(ms_sigs_count)
FIELD(ms_keys_count)
FIELD(separately_signed_tx_complete)
END_SERIALIZE()
FIELD(htlc_origin)
END_SERIALIZE()
};
struct destination_option_void
{
BEGIN_SERIALIZE_OBJECT()
END_SERIALIZE()
};
//if this struct is present, then creating htlc out, expiration -> number of blocks that htlc proposal is active
struct destination_option_htlc_out
{
uint64_t expiration;
crypto::hash htlc_hash;
BEGIN_SERIALIZE_OBJECT()
FIELD(transfer)
FIELD(origin)
END_SERIALIZE()
};
typedef boost::variant<destination_option_void, destination_option_htlc_out> destination_option_v;
struct tx_destination_entry
{
uint64_t amount; //money
std::list<account_public_address> addr; //destination address, in case of 1 address - txout_to_key, in case of more - txout_multisig
size_t minimum_sigs; // if txout_multisig: minimum signatures that are required to spend this output (minimum_sigs <= addr.size()) IF txout_to_key - not used
uint64_t amount_to_provide; //amount money that provided by initial creator of tx, used with partially created transactions
uint64_t amount; //money
std::list<account_public_address> addr; //destination address, in case of 1 address - txout_to_key, in case of more - txout_multisig
size_t minimum_sigs; //if txout_multisig: minimum signatures that are required to spend this output (minimum_sigs <= addr.size()) IF txout_to_key - not used
uint64_t amount_to_provide; //amount money that provided by initial creator of tx, used with partially created transactions
uint64_t unlock_time;
bool htlc; //if this flag is set, then creating htlc out, unlock_time -> number of blocks that htlc proposal is active
crypto::hash htlc_hash;
tx_destination_entry() : amount(0), minimum_sigs(0), amount_to_provide(0), unlock_time(0), htlc(false), htlc_hash(null_hash){}
tx_destination_entry(uint64_t a, const account_public_address& ad) : amount(a), addr(1, ad), minimum_sigs(0), amount_to_provide(0), unlock_time(0), htlc(false), htlc_hash(null_hash) {}
tx_destination_entry(uint64_t a, const account_public_address& ad, uint64_t ut) : amount(a), addr(1, ad), minimum_sigs(0), amount_to_provide(0), unlock_time(ut), htlc(false), htlc_hash(null_hash) {}
tx_destination_entry(uint64_t a, const std::list<account_public_address>& addr) : amount(a), addr(addr), minimum_sigs(addr.size()), amount_to_provide(0), unlock_time(0), htlc(false), htlc_hash(null_hash) {}
destination_option_v additional_options; //additional options
tx_destination_entry() : amount(0), minimum_sigs(0), amount_to_provide(0), unlock_time(0), additional_options(destination_option_void()){}
tx_destination_entry(uint64_t a, const account_public_address& ad) : amount(a), addr(1, ad), minimum_sigs(0), amount_to_provide(0), unlock_time(0), additional_options(destination_option_void()) {}
tx_destination_entry(uint64_t a, const account_public_address& ad, uint64_t ut) : amount(a), addr(1, ad), minimum_sigs(0), amount_to_provide(0), unlock_time(ut), additional_options(destination_option_void()) {}
tx_destination_entry(uint64_t a, const std::list<account_public_address>& addr) : amount(a), addr(addr), minimum_sigs(addr.size()), amount_to_provide(0), unlock_time(0), additional_options(destination_option_void()) {}
BEGIN_SERIALIZE_OBJECT()
FIELD(amount)
@ -66,8 +87,7 @@ namespace currency
FIELD(minimum_sigs)
FIELD(amount_to_provide)
FIELD(unlock_time)
FIELD(htlc)
FIELD(htlc_hash)
FIELD(additional_options)
END_SERIALIZE()
};

View file

@ -4021,9 +4021,10 @@ void wallet2::create_htlc_proposal(uint64_t amount, const currency::account_publ
dst.resize(1);
dst.back().addr.push_back(addr);
dst.back().amount = amount;
dst.back().htlc = true;
dst.back().htlc_hash = htlc_hash;
dst.back().unlock_time = 740; //about 12 hours
destination_option_htlc_out htlc_option = AUTO_VAL_INIT(htlc_option);
htlc_option.expiration = 740; //about 12 hours
htlc_option.htlc_hash = htlc_hash;
dst.back().additional_options = htlc_option;
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);
@ -4050,15 +4051,45 @@ void wallet2::get_list_of_active_htlc(bool only_redeem_txs, std::list<wallet_pub
}
}
//----------------------------------------------------------------------------------------------------
void wallet2::redeem_htlc(const crypto::hash& htlc_tx_id, const std::string& origin)
void wallet2::redeem_htlc(const crypto::hash& htlc_tx_id, std::string origin)
{
//lets figure out, if we have active htlc for this htlc
auto it = m_active_htlcs_txid.find(htlc_tx_id);
if (it == m_active_htlcs_txid.end())
//have correct origin, let's create transaction
std::vector<tx_destination_entry> dst;
dst.resize(1);
dst.back().addr.push_back(m_account.get_keys().account_address);
dst.back().amount = 0;
construct_tx_param ctp = get_default_construct_tx_param();
ctp.fee = TX_DEFAULT_FEE;
ctp.htlc_tx_id = htlc_tx_id;
ctp.htlc_origin = origin;
/*
struct destination_option_htlc_in
{
WLT_THROW_IF_FALSE_WITH_CODE(false,
"htlc not found with tx_id = " << htlc_tx_id, API_RETURN_CODE_NOT_FOUND);
}
uint64_t transfer;
std::string origin;
BEGIN_SERIALIZE_OBJECT()
FIELD(transfer)
FIELD(origin)
END_SERIALIZE()
};
transfer(const construct_tx_param& ctp,
currency::transaction &tx,
bool send_to_network,
std::string* p_unsigned_filename_or_tx_blob_str);
*/
currency::transaction result_tx = AUTO_VAL_INIT(tx);
transaction result_tx = AUTO_VAL_INIT(result_tx);
this->transfer(ctp, result_tx, true, nullptr);
}
//----------------------------------------------------------------------------------------------------
bool wallet2::prepare_tx_sources_for_packing(uint64_t items_to_pack, size_t fake_outputs_count, std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies, uint64_t& found_money)
@ -4232,6 +4263,55 @@ bool wallet2::prepare_tx_sources(crypto::hash multisig_id, std::vector<currency:
return true;
}
//----------------------------------------------------------------------------------------------------------------
bool wallet2::prepare_tx_sources_htlc(crypto::hash htlc_tx_id, const std::string& origin, std::vector<currency::tx_source_entry>& sources, uint64_t& found_money)
{
//lets figure out, if we have active htlc for this htlc
auto it = m_active_htlcs_txid.find(htlc_tx_id);
if (it == m_active_htlcs_txid.end())
{
WLT_THROW_IF_FALSE_WITH_CODE(false,
"htlc not found with tx_id = " << htlc_tx_id, API_RETURN_CODE_NOT_FOUND);
}
WLT_THROW_IF_FALSE_WITH_CODE(m_transfers.size() > it->second,
"Internal error: index in m_active_htlcs_txid <" << it->second << "> is bigger then size of m_transfers <" << m_transfers.size() << ">", API_RETURN_CODE_INTERNAL_ERROR);
const transfer_details& td = m_transfers[it->second];
WLT_THROW_IF_FALSE_WITH_CODE(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target.type() == typeid(txout_htlc),
"Unexpected type in active htlc", API_RETURN_CODE_INTERNAL_ERROR);
const txout_htlc& htlc_out = boost::get<txout_htlc>(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target);
bool use_sha256 = !(htlc_out.flags&CURRENCY_TXOUT_HTLC_FLAGS_HASH_TYPE_MASK);
//check origin
WLT_THROW_IF_FALSE_WITH_CODE(origin.size() != 0,
"Origin for htlc is empty", API_RETURN_CODE_BAD_ARG);
crypto::hash htlc_calculated_hash = currency::null_hash;
if (use_sha256)
{
htlc_calculated_hash = crypto::sha256_hash(origin.data(), origin.size());
}
else
{
htlc_calculated_hash = crypto::RIPEMD160_hash_256(origin.data(), origin.size());
}
WLT_THROW_IF_FALSE_WITH_CODE(htlc_calculated_hash == htlc_out.htlc_hash,
"Origin hash is missmatched with txout_htlc", API_RETURN_CODE_HTLC_ORIGIN_HASH_MISSMATCHED);
sources.push_back(AUTO_VAL_INIT(currency::tx_source_entry()));
currency::tx_source_entry& src = sources.back();
src.amount = found_money = td.amount();
src.real_output_in_tx_index = td.m_internal_output_index;
src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_ptx_wallet_info->m_tx);
src.htlc_origin = origin;
//src.multisig_id = multisig_id;
//src.ms_sigs_count = ms_out.minimum_sigs;
//src.ms_keys_count = ms_out.keys.size();
return true;
}
//----------------------------------------------------------------------------------------------------------------
uint64_t wallet2::get_needed_money(uint64_t fee, const std::vector<currency::tx_destination_entry>& dsts)
{
uint64_t needed_money = fee;
@ -4247,6 +4327,7 @@ uint64_t wallet2::get_needed_money(uint64_t fee, const std::vector<currency::tx_
}
return needed_money;
}
//----------------------------------------------------------------------------------------------------------------
void wallet2::send_transaction_to_network(const transaction& tx)
{
@ -4793,11 +4874,24 @@ void wallet2::prepare_transaction(const construct_tx_param& ctp, finalize_tx_par
TIME_MEASURE_START_MS(prepare_tx_sources_time);
if (ctp.perform_packing)
{
prepare_tx_sources_for_packing(WALLET_DEFAULT_POS_MINT_PACKING_SIZE, 0, ftp.sources, ftp.selected_transfers, found_money);
else if (ctp.multisig_id == currency::null_hash)
prepare_tx_sources(needed_money, ctp.fake_outputs_count, ctp.dust_policy.dust_threshold, ftp.sources, ftp.selected_transfers, found_money);
else
}
else if (ctp.htlc_tx_id != currency::null_hash)
{
//htlc
bool prepare_tx_sources_htlc(htlc_tx_id, ctp.htlc_origin, sources, found_money);
}
else if (ctp.multisig_id != currency::null_hash)
{
//multisig
prepare_tx_sources(ctp.multisig_id, ftp.sources, found_money);
}
else
{
//regular tx
prepare_tx_sources(needed_money, ctp.fake_outputs_count, ctp.dust_policy.dust_threshold, ftp.sources, ftp.selected_transfers, found_money);
}
TIME_MEASURE_FINISH_MS(prepare_tx_sources_time);
TIME_MEASURE_START_MS(prepare_tx_destinations_time);

View file

@ -273,6 +273,9 @@ namespace tools
uint8_t split_strategy_id;
bool mark_tx_as_complete;
crypto::hash htlc_tx_id;
std::string htlc_origin;
// constructing tx
uint64_t unlock_time;
std::vector<currency::extra_v> extra;
@ -835,7 +838,7 @@ 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 = currency::null_hash);
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, const std::string& origin);
void redeem_htlc(const crypto::hash& htlc_tx_id, std::string origin);
private:
@ -895,6 +898,7 @@ private:
bool prepare_tx_sources(uint64_t needed_money, size_t fake_outputs_count, uint64_t dust_threshold, std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies, uint64_t& found_money);
bool prepare_tx_sources(size_t fake_outputs_count, std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies, uint64_t& found_money);
bool prepare_tx_sources(crypto::hash multisig_id, std::vector<currency::tx_source_entry>& sources, uint64_t& found_money);
bool prepare_tx_sources_htlc(crypto::hash htlc_tx_id, const std::string& origin, std::vector<currency::tx_source_entry>& sources, uint64_t& found_money);
bool prepare_tx_sources_for_packing(uint64_t items_to_pack, size_t fake_outputs_count, std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies, uint64_t& found_money);
void prefetch_global_indicies_if_needed(std::vector<uint64_t>& selected_indicies);
uint64_t get_needed_money(uint64_t fee, const std::vector<currency::tx_destination_entry>& dsts);