forked from lthn/blockchain
htlc: implemented tracking of active htlc, creating transactio with htlc
This commit is contained in:
parent
fca90b0146
commit
66387d2bd5
6 changed files with 123 additions and 12 deletions
|
|
@ -590,7 +590,19 @@ namespace currency
|
|||
// return true;
|
||||
// }
|
||||
//---------------------------------------------------------------
|
||||
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, uint8_t tx_outs_attr)
|
||||
std::string generate_origin_for_htlc(cons crypto::public_key& redeem, cons crypto::public_key& refund, 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, acc_keys.spend_secret_key);
|
||||
crypto::hash origin_hs = cn_fast_hash(blob.data(), blob.size());
|
||||
std::string origin_blob;
|
||||
string_tools::apped_pod_to_strbuff(origin_blob, origin_hs);
|
||||
return origin_hs;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
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, uint8_t tx_outs_attr, const account_keys& self)
|
||||
{
|
||||
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());
|
||||
|
||||
|
|
@ -622,10 +634,38 @@ namespace currency
|
|||
|
||||
tx_out out;
|
||||
out.amount = de.amount;
|
||||
if (target_keys.size() == 1)
|
||||
if (de.htlc)
|
||||
{
|
||||
//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.flags = 0; //0 - SHA256, 1 - RIPEMD160, by default leave SHA256
|
||||
//receiver key
|
||||
htlc.pkey_redeem = *target_keys.begin();
|
||||
//generate refund key
|
||||
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
|
||||
bool r = derive_public_key_from_target_address(self.account_address, tx_sec_key, output_index, out_eph_public_key, derivation);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to derive_public_key_from_target_address");
|
||||
htlc.pkey_refund = out_eph_public_key;
|
||||
//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);
|
||||
//calculate hash
|
||||
|
||||
if (htlc.flags&CURRENCY_TXOUT_HTLC_FLAGS_HASH_TYPE_MASK)
|
||||
{
|
||||
htlc.htlc_hash = crypto::sha256_hash(hltc_origin.data(), hltc_origin.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
crypto::hash160 h160 = crypto::RIPEMD160_hash(hltc_origin.data(), hltc_origin.size());
|
||||
std::memcpy(&htlc.htlc_hash, &h160, sizeof(h160));
|
||||
}
|
||||
}
|
||||
else if (target_keys.size() == 1)
|
||||
{
|
||||
//out to key
|
||||
txout_to_key tk;
|
||||
txout_to_key tk = AUTO_VAL_INIT(tk);
|
||||
tk.key = target_keys.back();
|
||||
|
||||
if (de.addr.front().is_auditable()) // check only the first address because there's only one in this branch
|
||||
|
|
@ -1178,7 +1218,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, tx_outs_attr);
|
||||
bool r = construct_tx_out(dst_entr, txkey.sec, output_index, tx, deriv_cache, tx_outs_attr, sender_account_keys.account_address);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construc tx out");
|
||||
output_index++;
|
||||
summary_outs_money += dst_entr.amount;
|
||||
|
|
|
|||
|
|
@ -163,7 +163,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, 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, uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED, const account_public_address& self = account_public_address());
|
||||
bool validate_alias_name(const std::string& al);
|
||||
bool validate_password(const std::string& password);
|
||||
void get_attachment_extra_info_details(const std::vector<attachment_v>& attachment, extra_attachment_info& eai);
|
||||
|
|
@ -298,7 +298,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(cons crypto::public_key& redeem, cons crypto::public_key& refund, 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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -52,11 +52,12 @@ namespace currency
|
|||
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
|
||||
|
||||
tx_destination_entry() : amount(0), minimum_sigs(0), amount_to_provide(0), unlock_time(0){}
|
||||
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){}
|
||||
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) {}
|
||||
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){}
|
||||
tx_destination_entry() : amount(0), minimum_sigs(0), amount_to_provide(0), unlock_time(0), htlc(false){}
|
||||
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){}
|
||||
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){}
|
||||
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){}
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(amount)
|
||||
|
|
@ -64,6 +65,7 @@ namespace currency
|
|||
FIELD(minimum_sigs)
|
||||
FIELD(amount_to_provide)
|
||||
FIELD(unlock_time)
|
||||
FIELD(htlc)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -584,6 +584,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
|
|||
//active htlc
|
||||
auto amount_gindex_pair = std::make_pair(amount, td.m_global_output_index);
|
||||
m_active_htlcs[amount_gindex_pair] = transfer_index;
|
||||
m_active_htlcs_txid[get_transaction_hash(tx)] = transfer_index;
|
||||
}
|
||||
size_t transfer_index = m_transfers.size()-1;
|
||||
if (td.m_key_image != currency::null_ki)
|
||||
|
|
@ -1328,11 +1329,21 @@ void wallet2::process_htlc_triggers_on_block_added(uint64_t height)
|
|||
auto it_active_htlc = m_active_htlcs.find(std::make_pair(tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].amount, tr.m_global_output_index));
|
||||
if (it_active_htlc == m_active_htlcs.end())
|
||||
{
|
||||
LOG_ERROR("Erasing htlc, but it seems to be already erased");
|
||||
LOG_ERROR("Erasing active htlc(m_active_htlcs), but it seems to be already erased");
|
||||
}
|
||||
else
|
||||
{
|
||||
const transfer_details& td = m_transfers[it->second];
|
||||
m_active_htlcs.erase(it);
|
||||
auto it_tx = m_active_htlcs_txid.find(td.tx_hash());
|
||||
if (it_tx == m_active_htlcs_txid.end())
|
||||
{
|
||||
LOG_ERROR("Erasing active htlc(;), but it seems to be already erased");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_active_htlcs_txid.erase(it_tx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2206,6 +2217,7 @@ void wallet2::detach_blockchain(uint64_t including_height)
|
|||
const txout_htlc& htlc = boost::get<txout_htlc>(tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].target);
|
||||
auto amount_gindex_pair = std::make_pair(tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].amount, tr.m_global_output_index);
|
||||
m_active_htlcs[amount_gindex_pair] = i;
|
||||
m_active_htlcs_txid[tr.tx_hash()] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3993,6 +4005,43 @@ void wallet2::send_escrow_proposal(const bc_services::contract_private_details&
|
|||
add_sent_tx_detailed_info(tx, ftp.prepared_destinations, ftp.selected_transfers);
|
||||
|
||||
print_tx_sent_message(tx, "(from multisig)", fee);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::create_htlc_proposal(uint64_t amount, account_public_address& addr, uint64_t lock_blocks_count, currency::transaction &tx)
|
||||
{
|
||||
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;
|
||||
dst.back().htlc = true;
|
||||
dst.back().unlock_time = 740; //about 12 hours
|
||||
|
||||
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::get_list_of_active_htlc(bool only_redeem_txs, std::list<htlc_entry_info>& htlcs)
|
||||
{
|
||||
for (auto htlc_entry : m_active_htlcs_txid)
|
||||
{
|
||||
htlc_entry_info entry = AUTO_VAL_INIT(entry);
|
||||
entry.tx_id = htlc_entry.first;
|
||||
const transfer_details& td = m_transfers[htlc_entry.second];
|
||||
entry.amount = td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].amount;
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target.type() == typeid(txout_htlc),
|
||||
"[get_list_of_active_htlc]Internal error: unexpected type of out");
|
||||
const txout_htlc& htlc = boost::get<txout_htlc>(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target);
|
||||
entry.sha256_hash = htlc.htlc_hash;
|
||||
htlcs.push_back(entry);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::redeem_htlc(const crypto::hash& htlc_tx_id, const std::string& origin)
|
||||
{
|
||||
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@ namespace tools
|
|||
return;
|
||||
|
||||
a & m_htlcs;
|
||||
a & m_active_htlcs;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -815,6 +816,10 @@ namespace tools
|
|||
uint64_t get_sync_progress();
|
||||
uint64_t get_wallet_file_size()const;
|
||||
void set_use_deffered_global_outputs(bool use);
|
||||
void create_htlc_proposal(uint64_t amount, account_public_address& addr, uint64_t lock_blocks_count,
|
||||
account_public_address& addr, currency::transaction &tx);
|
||||
void get_list_of_active_htlc(bool only_redeem_txs, std::list<htlc_entry_info>& htlcs);
|
||||
void redeem_htlc(const crypto::hash& htlc_tx_id, const std::string& origin);
|
||||
|
||||
private:
|
||||
|
||||
|
|
@ -983,7 +988,8 @@ private:
|
|||
uint64_t transfer_index;
|
||||
};
|
||||
std::multimap<uint64_t, htlc_expiration_trigger> m_htlcs; //uint64_t -> height of expiration
|
||||
amount_gindex_to_transfer_id_container m_active_htlcs; // map [amount; gindex] -> tid
|
||||
amount_gindex_to_transfer_id_container m_active_htlcs; // map [amount; gindex] -> transfer index
|
||||
std::unordered_map<crypto::hash, uint64_t> m_active_htlcs_txid; // map [txid] -> transfer index, limitation: 1 transactiom -> 1 htlc
|
||||
|
||||
std::shared_ptr<i_core_proxy> m_core_proxy;
|
||||
std::shared_ptr<i_wallet2_callback> m_wcallback;
|
||||
|
|
|
|||
|
|
@ -974,6 +974,20 @@ namespace wallet_public
|
|||
};
|
||||
};
|
||||
|
||||
struct htlc_entry_info
|
||||
{
|
||||
crypto::hash sha256_hash;
|
||||
crypto::hash tx_id;
|
||||
uint64_t amount;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(amount)
|
||||
KV_SERIALIZE(sha256_hash)
|
||||
KV_SERIALIZE(tx_id)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
inline std::string get_escrow_contract_state_name(uint32_t state)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue