1
0
Fork 0
forked from lthn/blockchain

wallet2::prepare_and_sign_pos_block() and COMMAND_RPC_GETBLOCKTEMPLATE refactored

This commit is contained in:
sowle 2022-10-12 18:02:22 +02:00
parent 642cc94691
commit f0bbcb5f40
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
5 changed files with 65 additions and 71 deletions

View file

@ -833,11 +833,7 @@ namespace currency
params.stakeholder_address = stakeholder_address;
params.ex_nonce = req.extra_text;
params.pos = req.pos_block;
params.pe.amount = req.pos_amount;
params.pe.g_index = req.pos_g_index;
params.pe.tx_id = req.tx_id;
params.pe.tx_out_index = req.tx_out_index;
params.pe.stake_unlock_time = req.stake_unlock_time;
params.pe = req.pe;
//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;

View file

@ -803,11 +803,13 @@ namespace currency
std::string wallet_address;
std::string stakeholder_address;
bool pos_block; //is pos block
uint64_t pos_amount; //do we still need it?
uint64_t pos_g_index; //
crypto::hash tx_id;
uint64_t tx_out_index;
uint64_t stake_unlock_time;
//uint64_t pos_amount; //do we still need it?
//uint64_t pos_g_index; //
//crypto::hash tx_id;
//uint64_t tx_out_index;
//uint64_t stake_unlock_time;
pos_entry pe; // for making PoS blocks
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_BLOB_AS_HEX_STRING(explicit_transaction)
@ -815,11 +817,12 @@ namespace currency
KV_SERIALIZE(wallet_address)
KV_SERIALIZE(stakeholder_address);
KV_SERIALIZE(pos_block)
KV_SERIALIZE(pos_amount)
KV_SERIALIZE(pos_g_index)
KV_SERIALIZE_POD_AS_HEX_STRING(tx_id)
KV_SERIALIZE(tx_out_index)
KV_SERIALIZE(stake_unlock_time)
//KV_SERIALIZE(pos_amount)
//KV_SERIALIZE(pos_g_index)
//KV_SERIALIZE_POD_AS_HEX_STRING(tx_id)
//KV_SERIALIZE(tx_out_index)
//KV_SERIALIZE(stake_unlock_time)
KV_SERIALIZE(pe)
END_KV_SERIALIZE_MAP()
};

View file

@ -3594,45 +3594,50 @@ bool wallet2::is_in_hardfork_zone(uint64_t hardfork_index) const
return m_core_runtime_config.is_hardfork_active_for_height(hardfork_index, get_blockchain_current_size());
}
//----------------------------------------------------------------------------------------------------
bool wallet2::prepare_and_sign_pos_block(currency::block& b,
const pos_entry& pos_info,
const crypto::public_key& source_tx_pub_key,
uint64_t in_tx_output_index,
const std::vector<const crypto::public_key*>& keys_ptrs)
bool wallet2::prepare_and_sign_pos_block(currency::block& b, const pos_entry& pe) const
{
WLT_CHECK_AND_ASSERT_MES(pe.wallet_index < m_transfers.size(), false, "invalid pe.wallet_index: " << pe.wallet_index);
const transaction& source_tx = m_transfers[pe.wallet_index].m_ptx_wallet_info->m_tx;
if (!is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM))
{
// old PoS with non-hidden amounts
WLT_CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(currency::txin_gen), false, "Wrong input 0 type in transaction: " << b.miner_tx.vin[0].type().name());
WLT_CHECK_AND_ASSERT_MES(b.miner_tx.vin[1].type() == typeid(currency::txin_to_key), false, "Wrong input 1 type in transaction: " << b.miner_tx.vin[1].type().name());
auto& txin = boost::get<currency::txin_to_key>(b.miner_tx.vin[1]);
txin.k_image = pos_info.keyimage;
txin.k_image = pe.keyimage;
WLT_CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1 &&
b.miner_tx.signatures[0].type() == typeid(NLSAG_sig) &&
boost::get<NLSAG_sig>(b.miner_tx.signatures[0]).s.size() == txin.key_offsets.size(),
false, "Wrong signatures amount in coinbase transacton");
//derive secret key
crypto::key_derivation pos_coin_derivation = AUTO_VAL_INIT(pos_coin_derivation);
bool r = crypto::generate_key_derivation(source_tx_pub_key,
bool r = crypto::generate_key_derivation(get_tx_pub_key_from_extra(source_tx),
m_account.get_keys().view_secret_key,
pos_coin_derivation);
WLT_CHECK_AND_ASSERT_MES(r, false, "internal error: pos coin base generator: failed to generate_key_derivation("
<< source_tx_pub_key
<< pe.tx_id
<< ", view secret key: " << m_account.get_keys().view_secret_key << ")");
crypto::secret_key derived_secret_ephemeral_key = AUTO_VAL_INIT(derived_secret_ephemeral_key);
crypto::derive_secret_key(pos_coin_derivation,
in_tx_output_index,
pe.tx_out_index,
m_account.get_keys().spend_secret_key,
derived_secret_ephemeral_key);
// sign block actually in coinbase transaction
crypto::hash block_hash = currency::get_block_hash(b);
// get stake output pub key (stealth address) for ring signature generation
std::vector<const crypto::public_key*> keys_ptrs;
TRY_ENTRY()
const currency::tx_out_v& stake_out_v = source_tx.vout[pe.tx_out_index];
keys_ptrs.push_back(&boost::get<currency::txout_to_key>(boost::get<tx_out_bare>(stake_out_v).target).key);
CATCH_ENTRY_CUSTOM("wallet2::prepare_and_sign_pos_block", { LOG_PRINT_RED_L0("unable to get output's pub key because of the exception"); }, false);
crypto::generate_ring_signature(block_hash,
txin.k_image,
keys_ptrs,
@ -3808,15 +3813,12 @@ bool wallet2::reset_history()
return true;
}
//-------------------------------
bool wallet2::build_minted_block(const mining_context& cxt,
uint64_t new_block_expected_height /* = UINT64_MAX */)
bool wallet2::build_minted_block(const mining_context& cxt)
{
return build_minted_block(cxt, m_account.get_public_address(), new_block_expected_height);
return build_minted_block(cxt, m_account.get_public_address());
}
bool wallet2::build_minted_block(const mining_context& cxt,
const currency::account_public_address& miner_address,
uint64_t new_block_expected_height /* UINT64_MAX */)
bool wallet2::build_minted_block(const mining_context& cxt, const currency::account_public_address& miner_address)
{
//found a block, construct it, sign and push to daemon
WLT_LOG_GREEN("Found kernel, constructing block", LOG_LEVEL_0);
@ -3824,21 +3826,30 @@ bool wallet2::build_minted_block(const mining_context& cxt,
WLT_CHECK_AND_ASSERT_MES(cxt.index < m_transfers.size(), false, "cxt.index = " << cxt.index << " is out of bounds");
const transfer_details& td = m_transfers[cxt.index];
pos_entry pe = AUTO_VAL_INIT(pe);
currency::COMMAND_RPC_GETBLOCKTEMPLATE::request tmpl_req = AUTO_VAL_INIT(tmpl_req);
currency::COMMAND_RPC_GETBLOCKTEMPLATE::response tmpl_rsp = AUTO_VAL_INIT(tmpl_rsp);
tmpl_req.wallet_address = get_account_address_as_str(miner_address);
tmpl_req.stakeholder_address = get_account_address_as_str(m_account.get_public_address());
tmpl_req.pos_block = true;
pe.g_index = tmpl_req.pos_g_index = td.m_global_output_index;
pe.amount = tmpl_req.pos_amount = td.amount();// pe.amount;
pe.keyimage = td.m_key_image;
pe.block_timestamp = td.m_ptx_wallet_info->m_block_timestamp;
pe.stake_unlock_time = tmpl_req.stake_unlock_time = cxt.stake_unlock_time;
pe.tx_id = tmpl_req.tx_id = td.tx_hash();
pe.tx_out_index = tmpl_req.tx_out_index = td.m_internal_output_index;
pe.wallet_index = cxt.index;
tmpl_req.pe = AUTO_VAL_INIT(tmpl_req.pe);
tmpl_req.pe.amount = td.amount();
tmpl_req.pe.block_timestamp = td.m_ptx_wallet_info->m_block_timestamp;
tmpl_req.pe.g_index = td.m_global_output_index;
tmpl_req.pe.keyimage = td.m_key_image;
tmpl_req.pe.stake_unlock_time = cxt.stake_unlock_time;
tmpl_req.pe.tx_id = td.tx_hash();
tmpl_req.pe.tx_out_index = td.m_internal_output_index;
tmpl_req.pe.wallet_index = cxt.index;
//pe.g_index = tmpl_req.pos_g_index = td.m_global_output_index;
//pe.amount = tmpl_req.pos_amount = td.amount();// pe.amount;
//pe.keyimage = td.m_key_image;
//pe.block_timestamp = td.m_ptx_wallet_info->m_block_timestamp;
//pe.stake_unlock_time = tmpl_req.stake_unlock_time = cxt.stake_unlock_time;
//pe.tx_id = tmpl_req.tx_id = td.tx_hash();
//pe.tx_out_index = tmpl_req.tx_out_index = td.m_internal_output_index;
//pe.wallet_index = cxt.index;
//tmpl_req.pos_index = pe.index; // gindex <--- this should be removed as soon as pos_entry::index is replaced with tx_id and tx_out_index
// TODO: also fill out tx_id and tx_out_index for mining tx creation
@ -3856,9 +3867,9 @@ bool wallet2::build_minted_block(const mining_context& cxt,
currency::block b = AUTO_VAL_INIT(b);
currency::blobdata block_blob;
bool res = epee::string_tools::parse_hexstr_to_binbuff(tmpl_rsp.blocktemplate_blob, block_blob);
WLT_CHECK_AND_ASSERT_MES(res, false, "Failed to create block template after kernel hash found!");
WLT_CHECK_AND_ASSERT_MES(res, false, "parse_hexstr_to_binbuff() failed after kernel hash found!");
res = parse_and_validate_block_from_blob(block_blob, b);
WLT_CHECK_AND_ASSERT_MES(res, false, "Failed to create block template after kernel hash found!");
WLT_CHECK_AND_ASSERT_MES(res, false, "parse_and_validate_block_from_blob() failed after kernel hash found!");
if (cxt.last_block_hash != b.prev_id)
{
@ -3883,19 +3894,7 @@ bool wallet2::build_minted_block(const mining_context& cxt,
else
{
// old fashioned non-hidden amount PoS scheme
const auto& target = boost::get<tx_out_bare>(stake_out_v).target;
WLT_CHECK_AND_ASSERT_MES(target.type() == typeid(currency::txout_to_key), false, "wrong type_id in source transaction in coinbase tx");
const currency::txout_to_key& stake_out_to_key = boost::get<currency::txout_to_key>(target);
std::vector<const crypto::public_key*> keys_ptrs;
keys_ptrs.push_back(&stake_out_to_key.key);
//sign block
res = prepare_and_sign_pos_block(b,
pe,
get_tx_pub_key_from_extra(m_transfers[pe.wallet_index].m_ptx_wallet_info->m_tx),
td.m_internal_output_index,
keys_ptrs);
res = prepare_and_sign_pos_block(b, tmpl_req.pe);
WLT_CHECK_AND_ASSERT_MES(res, false, "Failed to prepare_and_sign_pos_block");
}
@ -4784,8 +4783,10 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vector<currency
if (td.m_global_output_index == daemon_oe.global_amount_index)
continue;
tx_output_entry oe = AUTO_VAL_INIT(oe);
oe.out_reference = daemon_oe.global_amount_index;
oe.stealth_address = daemon_oe.out_key;
oe.amount_commitment = daemon_oe.amount_commitment;
oe.concealing_point = daemon_oe.concealing_point;
oe.out_reference = daemon_oe.global_amount_index;
oe.stealth_address = daemon_oe.stealth_address;
src.outputs.push_back(oe);
if (src.outputs.size() >= fake_outputs_count)
break;
@ -6050,7 +6051,7 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public
continue;
tx_output_entry oe = AUTO_VAL_INIT(oe);
oe.out_reference = daemon_oe.global_amount_index;
oe.stealth_address = daemon_oe.out_key;
oe.stealth_address = daemon_oe.stealth_address;
src.outputs.push_back(oe);
if (src.outputs.size() >= fake_outs_count)
break;

View file

@ -821,11 +821,7 @@ namespace tools
//next functions in public area only becausce of test_generator
//TODO: Need refactoring - remove it back to private zone
void set_genesis(const crypto::hash& genesis_hash);
bool prepare_and_sign_pos_block(currency::block& b,
const currency::pos_entry& pos_info,
const crypto::public_key& source_tx_pub_key,
uint64_t in_tx_output_index,
const std::vector<const crypto::public_key*>& keys_ptrs);
bool prepare_and_sign_pos_block(currency::block& b, const currency::pos_entry& pe) const;
void process_new_blockchain_entry(const currency::block& b,
const currency::block_direct_data_entry& bche,
const crypto::hash& bl_id,
@ -836,8 +832,8 @@ namespace tools
bool get_pos_entries(std::vector<currency::pos_entry>& entries); // TODO: make it const
size_t get_pos_entries_count();
bool build_minted_block(const mining_context& cxt, uint64_t new_block_expected_height = UINT64_MAX);
bool build_minted_block(const mining_context& cxt, const currency::account_public_address& miner_address, uint64_t new_block_expected_height = UINT64_MAX);
bool build_minted_block(const mining_context& cxt);
bool build_minted_block(const mining_context& cxt, const currency::account_public_address& miner_address);
bool reset_history();
bool is_transfer_unlocked(const transfer_details& td) const;
bool is_transfer_unlocked(const transfer_details& td, bool for_pos_mining, uint64_t& stake_lock_time) const;

View file

@ -353,7 +353,7 @@ bool test_generator::sign_block(currency::block& b,
const std::vector<const block_info*>& blocks,
const outputs_index& oi)
{
uint64_t h = 0;
/*uint64_t h = 0;
uint64_t out_i = 0;
const transaction * pts = nullptr;
crypto::public_key source_tx_pub_key = null_pkey;
@ -368,11 +368,9 @@ bool test_generator::sign_block(currency::block& b,
out_i,
source_tx_pub_key,
out_key);
CHECK_AND_ASSERT_THROW_MES(r, "Failed to get_output_details_by_global_index()");
CHECK_AND_ASSERT_THROW_MES(r, "Failed to get_output_details_by_global_index()");*/
std::vector<const crypto::public_key*> keys_ptrs;
keys_ptrs.push_back(&out_key);
r = w.prepare_and_sign_pos_block(b, pe, source_tx_pub_key, out_i, keys_ptrs);
bool r = w.prepare_and_sign_pos_block(b, pe);
CHECK_AND_ASSERT_THROW_MES(r,"Failed to prepare_and_sign_pos_block()");
return true;