forked from lthn/blockchain
added explicit transactions to blocktemplate
This commit is contained in:
parent
cdfd321387
commit
d7c67b196c
8 changed files with 104 additions and 22 deletions
|
|
@ -333,6 +333,11 @@ namespace currency
|
|||
return m_blockchain_storage.create_block_template(b, adr, stakeholder_address, diffic, height, ex_nonce, pos, pe);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::get_block_template(const create_block_template_params& params, create_block_template_response& resp)
|
||||
{
|
||||
return m_blockchain_storage.create_block_template(params, resp);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const
|
||||
{
|
||||
return m_blockchain_storage.find_blockchain_supplement(qblock_ids, resp);
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ namespace currency
|
|||
|
||||
//-------------------- i_miner_handler -----------------------
|
||||
virtual bool handle_block_found(const block& b, block_verification_context* p_verification_result = nullptr);
|
||||
virtual bool get_block_template(block& b, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos = false, const pos_entry& pe = pos_entry());
|
||||
virtual bool get_block_template(const create_block_template_params& params, create_block_template_response& resp);
|
||||
bool get_block_template(block& b, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos = false, const pos_entry& pe = pos_entry());
|
||||
|
||||
miner& get_miner(){ return m_miner; }
|
||||
static void init_options(boost::program_options::options_description& desc);
|
||||
|
|
|
|||
|
|
@ -109,4 +109,6 @@ namespace currency
|
|||
blobdata tx_to_blob(const transaction& b);
|
||||
bool tx_to_blob(const transaction& b, blobdata& b_blob);
|
||||
bool read_keyimages_from_tx(const transaction& tx, std::list<crypto::key_image>& kil);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ namespace currency
|
|||
struct i_miner_handler
|
||||
{
|
||||
virtual bool handle_block_found(const block& b, block_verification_context* p_verification_result = nullptr) = 0;
|
||||
virtual bool get_block_template(const create_block_template_params& params, create_block_template_response& resp) = 0;
|
||||
virtual bool get_block_template(block& b, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos = false, const pos_entry& pe = pos_entry()) = 0;
|
||||
protected:
|
||||
~i_miner_handler(){};
|
||||
|
|
|
|||
|
|
@ -793,28 +793,45 @@ namespace currency
|
|||
return false;
|
||||
}
|
||||
|
||||
block b = AUTO_VAL_INIT(b);
|
||||
wide_difficulty_type dt = 0;
|
||||
currency::pos_entry pe = AUTO_VAL_INIT(pe);
|
||||
pe.amount = req.pos_amount;
|
||||
pe.index = req.pos_index;
|
||||
pe.stake_unlock_time = req.stake_unlock_time;
|
||||
//pe.keyimage key image will be set in the wallet
|
||||
//pe.wallet_index is not included in serialization map, TODO: refactoring here
|
||||
|
||||
if (!m_core.get_block_template(b, miner_address, stakeholder_address, dt, res.height, req.extra_text, req.pos_block, pe))
|
||||
create_block_template_params params = AUTO_VAL_INIT(params);
|
||||
params.miner_address = miner_address;
|
||||
params.stakeholder_address = stakeholder_address;
|
||||
params.ex_nonce = req.extra_text;
|
||||
params.pos = req.pos_block;
|
||||
params.pe.amount = req.pos_amount;
|
||||
params.pe.index = req.pos_index;
|
||||
params.pe.stake_unlock_time = req.stake_unlock_time;
|
||||
//params.pe.keyimage key image will be set in the wallet
|
||||
//params.pe.wallet_index is not included in serialization map, TODO: refactoring here
|
||||
params.pcustom_fill_block_template_func = nullptr;
|
||||
if (req.explicit_transaction.size())
|
||||
{
|
||||
transaction tx = AUTO_VAL_INIT(tx);
|
||||
if (!parse_and_validate_tx_from_blob(req.explicit_transaction, tx))
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
|
||||
error_resp.message = "Wrong parameters: explicit_transaction is invalid";
|
||||
LOG_ERROR("Failed to parse explicit_transaction blob");
|
||||
return false;
|
||||
}
|
||||
params.explicit_txs.push_back(tx);
|
||||
}
|
||||
|
||||
create_block_template_response resp = AUTO_VAL_INIT(resp);
|
||||
if (!m_core.get_block_template(params, resp))
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
||||
error_resp.message = "Internal error: failed to create block template";
|
||||
LOG_ERROR("Failed to create block template");
|
||||
return false;
|
||||
}
|
||||
res.difficulty = dt.convert_to<std::string>();
|
||||
blobdata block_blob = t_serializable_object_to_blob(b);
|
||||
|
||||
res.difficulty = resp.diffic.convert_to<std::string>();
|
||||
blobdata block_blob = t_serializable_object_to_blob(resp.b);
|
||||
res.blocktemplate_blob = string_tools::buff_to_hex_nodelimer(block_blob);
|
||||
res.prev_hash = string_tools::pod_to_hex(b.prev_id);
|
||||
|
||||
res.prev_hash = string_tools::pod_to_hex(resp.b.prev_id);
|
||||
res.height = resp.height;
|
||||
//calculate epoch seed
|
||||
res.seed = currency::ethash_epoch_to_seed(currency::ethash_height_to_epoch(res.height));
|
||||
|
||||
|
|
|
|||
|
|
@ -770,7 +770,7 @@ namespace currency
|
|||
{
|
||||
struct request
|
||||
{
|
||||
//uint64_t reserve_size; //max 255 bytes
|
||||
blobdata explicit_transaction;
|
||||
std::string extra_text;
|
||||
std::string wallet_address;
|
||||
std::string stakeholder_address;
|
||||
|
|
@ -780,6 +780,7 @@ namespace currency
|
|||
uint64_t stake_unlock_time;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_BLOB_AS_HEX_STRING(explicit_transaction)
|
||||
KV_SERIALIZE(extra_text)
|
||||
KV_SERIALIZE(wallet_address)
|
||||
KV_SERIALIZE(stakeholder_address);
|
||||
|
|
|
|||
|
|
@ -2291,15 +2291,32 @@ void wallet2::get_transfers(wallet2::transfer_container& incoming_transfers) con
|
|||
incoming_transfers = m_transfers;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::generate_packing_transaction_if_needed(transaction& tx)
|
||||
bool wallet2::generate_packing_transaction_if_needed(transaction& tx, uint64_t fake_outputs_number)
|
||||
{
|
||||
prepare_free_transfers_cache(0);
|
||||
auto it = m_found_free_amounts.find(CURRENCY_BLOCK_REWARD);
|
||||
if (it == m_found_free_amounts.end() || it->second.size() < WALLET_POS_MINT_PACKING_SIZE)
|
||||
return false;
|
||||
|
||||
//let's check if we have at least WALLET_POS_MINT_PACKING_SIZE transactions which is ready to go
|
||||
size_t count = 0;
|
||||
for (auto it_ind = it->second.begin(); it_ind != it->second.end() && count < WALLET_POS_MINT_PACKING_SIZE; it_ind++)
|
||||
{
|
||||
if (is_transfer_ready_to_go(m_transfers[*it_ind], fake_outputs_number))
|
||||
++count;
|
||||
}
|
||||
if (count < WALLET_POS_MINT_PACKING_SIZE)
|
||||
return false;
|
||||
construct_tx_param ctp = get_default_construct_tx_param();
|
||||
currency::tx_destination_entry de = AUTO_VAL_INIT(de);
|
||||
de.addr.push_back(m_account.get_public_address());
|
||||
de.amount = WALLET_POS_MINT_PACKING_SIZE;
|
||||
ctp.dsts.push_back(de);
|
||||
ctp.perform_packing = true;
|
||||
|
||||
transfer(ctp, tx, false, nullptr);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool include_unspent /*= true*/) const
|
||||
|
|
@ -2769,6 +2786,12 @@ bool wallet2::build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request&
|
|||
tmpl_req.pos_index = req.pos_entries[rsp.index].index;
|
||||
tmpl_req.extra_text = m_miner_text_info;
|
||||
tmpl_req.stake_unlock_time = req.pos_entries[rsp.index].stake_unlock_time;
|
||||
//generate packing tx
|
||||
transaction pack_tx = AUTO_VAL_INIT(pack_tx);
|
||||
if (generate_packing_transaction_if_needed(pack_tx, 0))
|
||||
{
|
||||
tx_to_blob(pack_tx, tmpl_req.explicit_transaction);
|
||||
}
|
||||
m_core_proxy->call_COMMAND_RPC_GETBLOCKTEMPLATE(tmpl_req, tmpl_rsp);
|
||||
WLT_CHECK_AND_ASSERT_MES(tmpl_rsp.status == CORE_RPC_STATUS_OK, false, "Failed to create block template after kernel hash found!");
|
||||
|
||||
|
|
@ -3453,12 +3476,10 @@ bool wallet2::prepare_tx_sources_for_packing(uint64_t items_to_pack, size_t fake
|
|||
}
|
||||
it->second.erase(it->second.begin());
|
||||
if (!it->second.size())
|
||||
found_free_amounts.erase(it);
|
||||
m_found_free_amounts.erase(it);
|
||||
}
|
||||
|
||||
|
||||
return prepare_tx_sources(fake_outputs_count, sources, selected_indicies, found_money);
|
||||
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::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)
|
||||
|
|
@ -4110,6 +4131,8 @@ void wallet2::prepare_transaction(const construct_tx_param& ctp, finalize_tx_par
|
|||
TIME_MEASURE_START_MS(prepare_tx_sources_time);
|
||||
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 if (ctp.perform_packing)
|
||||
prepare_tx_sources_for_packing(WALLET_POS_MINT_PACKING_SIZE, 0, ftp.sources, ftp.selected_transfers, found_money);
|
||||
else
|
||||
prepare_tx_sources(ctp.multisig_id, ftp.sources, found_money);
|
||||
TIME_MEASURE_FINISH_MS(prepare_tx_sources_time);
|
||||
|
|
@ -4239,7 +4262,32 @@ void wallet2::transfer(const std::vector<currency::tx_destination_entry>& dsts,
|
|||
ctp.tx_outs_attr = tx_outs_attr;
|
||||
ctp.unlock_time = unlock_time;
|
||||
TIME_MEASURE_FINISH(precalculation_time);
|
||||
transfer(ctp, tx, send_to_network, p_signed_tx_blob_str);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
construct_tx_param wallet2::get_default_construct_tx_param_inital()
|
||||
{
|
||||
construct_tx_param ctp = AUTO_VAL_INIT(ctp);
|
||||
|
||||
ctp.fee = m_core_runtime_config.tx_default_fee;
|
||||
ctp.dust_policy = tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD);
|
||||
ctp.split_strategy_id = tools::detail::ssi_digit;
|
||||
ctp.tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED;
|
||||
ctp.shuffle = 0;
|
||||
return ctp;
|
||||
}
|
||||
const construct_tx_param& wallet2::get_default_construct_tx_param()
|
||||
{
|
||||
static construct_tx_param ctp = get_default_construct_tx_param_inital();
|
||||
return ctp;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::transfer(const construct_tx_param& ctp,
|
||||
currency::transaction &tx,
|
||||
bool send_to_network,
|
||||
std::string* p_signed_tx_blob_str)
|
||||
{
|
||||
TIME_MEASURE_START(prepare_transaction_time);
|
||||
finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
|
||||
prepare_transaction(ctp, ftp);
|
||||
|
|
|
|||
|
|
@ -541,6 +541,11 @@ namespace tools
|
|||
const std::vector<currency::attachment_v>& attachments,
|
||||
currency::transaction& tx);
|
||||
|
||||
void transfer(const construct_tx_param& ctp,
|
||||
currency::transaction &tx,
|
||||
bool send_to_network,
|
||||
std::string* p_signed_tx_blob_str);
|
||||
|
||||
template<typename destination_split_strategy_t>
|
||||
void transfer_from_contract(
|
||||
const std::list<currency::account_keys>& owner_keys,
|
||||
|
|
@ -805,7 +810,9 @@ private:
|
|||
|
||||
void change_contract_state(wallet_public::escrow_contract_details_basic& contract, uint32_t new_state, const crypto::hash& contract_id, const wallet_public::wallet_transfer_info& wti) const;
|
||||
void change_contract_state(wallet_public::escrow_contract_details_basic& contract, uint32_t new_state, const crypto::hash& contract_id, const std::string& reason = "internal intention") const;
|
||||
|
||||
|
||||
construct_tx_param get_default_construct_tx_param_inital();
|
||||
const construct_tx_param& get_default_construct_tx_param();
|
||||
|
||||
uint64_t get_tx_expiration_median() const;
|
||||
|
||||
|
|
@ -847,7 +854,7 @@ private:
|
|||
void exception_handler() const;
|
||||
uint64_t get_minimum_allowed_fee_for_contract(const crypto::hash& ms_id);
|
||||
void check_for_free_space_and_throw_if_it_lacks(const std::wstring& path, uint64_t exact_size_needed_if_known = UINT64_MAX);
|
||||
bool generate_packing_transaction_if_needed(transaction& tx);
|
||||
bool generate_packing_transaction_if_needed(transaction& tx, uint64_t fake_outputs_number);
|
||||
|
||||
|
||||
currency::account_base m_account;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue