1
0
Fork 0
forked from lthn/blockchain

actual_timestamp made obsolete, real timestamp moved to tx_service_attachment in extra, PoS ts guessing interval extended

This commit is contained in:
sowle 2021-10-08 08:08:58 +03:00
parent 9125039397
commit 92e2b1851b
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
12 changed files with 104 additions and 47 deletions

View file

@ -289,7 +289,14 @@ POP_GCC_WARNINGS
buff.append(reinterpret_cast<const char*>(&pod), sizeof(pod));
}
template<typename pod_t>
bool get_pod_from_strbuff(const std::string& buff, pod_t& output)
{
if (buff.size() != sizeof(pod_t))
return false;
output = *reinterpret_cast<const pod_t*>(buff.data());
return true;
}
template<class t_string>
bool parse_commandline(std::map<t_string, t_string>& res, int argc, char** argv)

View file

@ -0,0 +1,7 @@
// 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
#define BC_BLOCK_DATETIME_SERVICE_ID "d"
#define BC_BLOCK_DATETIME_INSTRUCTION_DEFAULT ""

View file

@ -2114,7 +2114,7 @@ bool blockchain_storage::get_tx_rpc_details(const crypto::hash& h, tx_rpc_extend
if (tx_ptr && !timestamp)
{
timestamp = get_actual_timestamp(m_db_blocks[tx_ptr->m_keeper_block_height]->bl);
timestamp = get_block_datetime(m_db_blocks[tx_ptr->m_keeper_block_height]->bl);
}
tei.keeper_block = static_cast<int64_t>(tx_ptr->m_keeper_block_height);
fill_tx_rpc_details(tei, tx_ptr->tx, &(*tx_ptr), h, timestamp, is_short);
@ -2203,11 +2203,11 @@ bool blockchain_storage::get_main_block_rpc_details(uint64_t i, block_rpc_extend
crypto::hash coinbase_id = get_transaction_hash(core_bei_ptr->bl.miner_tx);
//load transactions details
bei.transactions_details.push_back(tx_rpc_extended_info());
get_tx_rpc_details(coinbase_id, bei.transactions_details.back(), get_actual_timestamp(core_bei_ptr->bl), true);
get_tx_rpc_details(coinbase_id, bei.transactions_details.back(), get_block_datetime(core_bei_ptr->bl), true);
for (auto& h : core_bei_ptr->bl.tx_hashes)
{
bei.transactions_details.push_back(tx_rpc_extended_info());
get_tx_rpc_details(h, bei.transactions_details.back(), get_actual_timestamp(core_bei_ptr->bl), true);
get_tx_rpc_details(h, bei.transactions_details.back(), get_block_datetime(core_bei_ptr->bl), true);
bei.total_fee += bei.transactions_details.back().fee;
bei.total_txs_size += bei.transactions_details.back().blob_size;
}
@ -2288,13 +2288,13 @@ bool blockchain_storage::get_alt_block_rpc_details(const block_extended_info& be
crypto::hash coinbase_id = get_transaction_hash(bei_core.bl.miner_tx);
//load transactions details
bei.transactions_details.push_back(tx_rpc_extended_info());
fill_tx_rpc_details(bei.transactions_details.back(), bei_core.bl.miner_tx, nullptr, coinbase_id, get_actual_timestamp(bei_core.bl));
fill_tx_rpc_details(bei.transactions_details.back(), bei_core.bl.miner_tx, nullptr, coinbase_id, get_block_datetime(bei_core.bl));
bei.total_fee = 0;
for (auto& h : bei_core.bl.tx_hashes)
{
bei.transactions_details.push_back(tx_rpc_extended_info());
if (!get_tx_rpc_details(h, bei.transactions_details.back(), get_actual_timestamp(bei_core.bl), true))
if (!get_tx_rpc_details(h, bei.transactions_details.back(), get_block_datetime(bei_core.bl), true))
{
//tx not in blockchain, supposed to be in tx pool
m_tx_pool.get_transaction_details(h, bei.transactions_details.back());
@ -2407,8 +2407,8 @@ uint64_t blockchain_storage::get_seconds_between_last_n_block(size_t n) const
if (m_db_blocks.size() <= n)
return 0;
uint64_t top_block_ts = get_actual_timestamp(m_db_blocks[m_db_blocks.size() - 1]->bl);
uint64_t n_block_ts = get_actual_timestamp(m_db_blocks[m_db_blocks.size() - 1 - n]->bl);
uint64_t top_block_ts = get_block_datetime(m_db_blocks[m_db_blocks.size() - 1]->bl);
uint64_t n_block_ts = get_block_datetime(m_db_blocks[m_db_blocks.size() - 1 - n]->bl);
return top_block_ts > n_block_ts ? top_block_ts - n_block_ts : 0;
}
@ -4905,7 +4905,7 @@ void blockchain_storage::get_pos_mining_estimate(uint64_t amount_coins,
auto bei = m_db_blocks[h];
if (!is_pos_block(bei->bl))
continue;
uint64_t ts = get_actual_timestamp(bei->bl);
uint64_t ts = get_block_datetime(bei->bl);
pos_ts_min = min(pos_ts_min, ts);
pos_ts_max = max(pos_ts_max, ts);
pos_total_minted_money += get_reward_from_miner_tx(bei->bl.miner_tx);
@ -5060,7 +5060,8 @@ bool blockchain_storage::validate_pos_block(const block& b,
}
//check actual time if it there
// the following check is de-facto not applicable since 2021-10, but left intact to avoid consensus issues
// PoS blocks don't use etc_tx_time anymore to store actual timestamp; instead, they use tx_service_attachment in mining tx extra
uint64_t actual_ts = get_actual_timestamp(b);
if ((actual_ts > b.timestamp && actual_ts - b.timestamp > POS_MAX_ACTUAL_TIMESTAMP_TO_MINED) ||
(actual_ts < b.timestamp && b.timestamp - actual_ts > POS_MAX_ACTUAL_TIMESTAMP_TO_MINED)
@ -5379,7 +5380,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
block_fees.reserve(bl.tx_hashes.size());
//process transactions
TIME_MEASURE_START_PD(all_txs_insert_time_5);
if (!add_transaction_from_block(bl.miner_tx, get_transaction_hash(bl.miner_tx), id, get_current_blockchain_size(), get_actual_timestamp(bl)))
if (!add_transaction_from_block(bl.miner_tx, get_transaction_hash(bl.miner_tx), id, get_current_blockchain_size(), get_block_datetime(bl)))
{
LOG_PRINT_L0("Block with id: " << id << " failed to add transaction to blockchain storage");
bvc.m_verification_failed = true;
@ -5454,7 +5455,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
TIME_MEASURE_START_PD(tx_prapare_append);
uint64_t current_bc_size = get_current_blockchain_size();
uint64_t actual_timestamp = get_actual_timestamp(bl);
uint64_t actual_timestamp = get_block_datetime(bl);
TIME_MEASURE_FINISH_PD(tx_prapare_append);
TIME_MEASURE_START_PD(tx_append_time);
if(!add_transaction_from_block(tx, tx_id, id, current_bc_size, actual_timestamp))
@ -5622,7 +5623,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
stringstream powpos_str_entry, timestamp_str_entry;
if (is_pos_bl)
{ // PoS
int64_t actual_ts = get_actual_timestamp(bei.bl); // signed int is intentionally used here
int64_t actual_ts = get_block_datetime(bei.bl); // signed int is intentionally used here
int64_t ts_diff = actual_ts - m_core_runtime_config.get_core_time();
powpos_str_entry << "PoS:\t" << proof_hash << ", stake amount: " << print_money_brief(pos_coinstake_amount) << ", final_difficulty: " << this_coin_diff;
timestamp_str_entry << ", actual ts: " << actual_ts << " (diff: " << std::showpos << ts_diff << "s) block ts: " << std::noshowpos << bei.bl.timestamp << " (shift: " << std::showpos << static_cast<int64_t>(bei.bl.timestamp) - actual_ts << ")";

View file

@ -26,6 +26,7 @@ using namespace epee;
#include "bc_payments_id_service.h"
#include "bc_escrow_service.h"
#include "bc_attachments_helpers.h"
#include "bc_block_datetime_service.h"
#include "genesis.h"
#include "genesis_acc.h"
#include "common/mnemonic-encoding.h"
@ -2108,6 +2109,8 @@ namespace currency
return median_fee * 10;
}
//---------------------------------------------------------------
// NOTE: this function is obsolete and depricated
// PoS block real timestamp is set using a service attachment in mining tx extra since 2021-10
uint64_t get_actual_timestamp(const block& b)
{
uint64_t tes_ts = b.timestamp;
@ -2119,6 +2122,41 @@ namespace currency
}
return tes_ts;
}
//---------------------------------------------------------------
// returns timestamp from BC_BLOCK_DATETIME_SERVICE_ID via tx_service_attachment in extra
// fallbacks to old-style actual timestamp via etc_tx_time, then to block timestamp
uint64_t get_block_datetime(const block& b)
{
// first try BC_BLOCK_DATETIME_SERVICE_ID
tx_service_attachment sa = AUTO_VAL_INIT(sa);
if (get_type_in_variant_container(b.miner_tx.extra, sa))
{
if (sa.service_id == BC_BLOCK_DATETIME_SERVICE_ID && sa.instruction == BC_BLOCK_DATETIME_INSTRUCTION_DEFAULT)
{
uint64_t ts;
if (epee::string_tools::get_pod_from_strbuff(sa.body, ts))
return ts;
}
}
// next try etc_tx_time
etc_tx_time t = AUTO_VAL_INIT(t);
if (get_type_in_variant_container(b.miner_tx.extra, t))
return t.v;
// otherwise return default: block.ts
return b.timestamp;
}
//---------------------------------------------------------------
void set_block_datetime(uint64_t datetime, block& b)
{
tx_service_attachment sa = AUTO_VAL_INIT(sa);
sa.service_id = BC_BLOCK_DATETIME_SERVICE_ID;
sa.instruction = BC_BLOCK_DATETIME_INSTRUCTION_DEFAULT;
sa.flags = 0;
epee::string_tools::append_pod_to_strbuff(sa.body, datetime);
b.miner_tx.extra.push_back(sa);
}
//------------------------------------------------------------------
bool validate_alias_name(const std::string& al)
{
@ -2777,7 +2815,7 @@ namespace currency
pei_rpc.timestamp = bei_chain.bl.timestamp;
pei_rpc.id = epee::string_tools::pod_to_hex(h);
pei_rpc.prev_id = epee::string_tools::pod_to_hex(bei_chain.bl.prev_id);
pei_rpc.actual_timestamp = get_actual_timestamp(bei_chain.bl);
pei_rpc.actual_timestamp = get_block_datetime(bei_chain.bl);
pei_rpc.type = is_pos_block(bei_chain.bl) ? 0 : 1;
pei_rpc.already_generated_coins = boost::lexical_cast<std::string>(bei_chain.already_generated_coins);
pei_rpc.this_block_fee_median = bei_chain.this_block_tx_fee_median;

View file

@ -329,8 +329,10 @@ namespace currency
// prints amount in format "3.14", "0.0"
std::string print_money_brief(uint64_t amount);
uint64_t get_actual_timestamp(const block& b);
uint64_t get_actual_timestamp(const block& b); // obsolete and depricated, use get_block_datetime
uint64_t get_block_datetime(const block& b);
void set_block_datetime(uint64_t datetime, block& b);
bool addendum_to_hexstr(const std::vector<crypto::hash>& add, std::string& hex_buff);
bool hexstr_to_addendum(const std::string& hex_buff, std::vector<crypto::hash>& add);
bool set_payment_id_to_tx(std::vector<attachment_v>& att, const std::string& payment_id);

View file

@ -330,7 +330,7 @@ private:
currency::block_extended_info bei = AUTO_VAL_INIT(bei);
CHECK_AND_ASSERT_MES(bcs.get_block_extended_info_by_height(tx_chain_entry->m_keeper_block_height, bei), false, "cannot find block by height " << tx_chain_entry->m_keeper_block_height);
LOG_PRINT_L0("Key image found in tx: " << tx_id << " height " << tx_chain_entry->m_keeper_block_height << " (ts: " << epee::misc_utils::get_time_str_v2(currency::get_actual_timestamp(bei.bl)) << ")" << ENDL
LOG_PRINT_L0("Key image found in tx: " << tx_id << " height " << tx_chain_entry->m_keeper_block_height << " (ts: " << epee::misc_utils::get_time_str_v2(currency::get_block_datetime(bei.bl)) << ")" << ENDL
<< obj_to_json_str(tx_chain_entry->tx));
}
else

View file

@ -180,7 +180,7 @@ namespace currency
res.pos_block_ts_shift_vs_actual = 0;
auto last_pos_block_ptr = m_core.get_blockchain_storage().get_last_block_of_type(true);
if (last_pos_block_ptr)
res.pos_block_ts_shift_vs_actual = last_pos_block_ptr->bl.timestamp - get_actual_timestamp(last_pos_block_ptr->bl);
res.pos_block_ts_shift_vs_actual = last_pos_block_ptr->bl.timestamp - get_block_datetime(last_pos_block_ptr->bl);
}
if (req.flags&COMMAND_RPC_GET_INFO_FLAG_OUTS_STAT)
m_core.get_blockchain_storage().get_outs_index_stat(res.outs_stat);
@ -918,10 +918,10 @@ namespace currency
}
//@#@
//temporary double check timestamp
if (time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) > 5)
if (time(NULL) - static_cast<int64_t>(get_block_datetime(b)) > 5)
{
LOG_PRINT_RED_L0("Found block (" << get_block_hash(b) << ") timestamp (" << get_actual_timestamp(b)
<< ") is suspiciously less (" << time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) << ") than current time ( " << time(NULL) << ")");
LOG_PRINT_RED_L0("Found block (" << get_block_hash(b) << ") timestamp (" << get_block_datetime(b)
<< ") is suspiciously less (" << time(NULL) - static_cast<int64_t>(get_block_datetime(b)) << ") than current time ( " << time(NULL) << ")");
//mark node to make it easier to find it via scanner
m_core.get_blockchain_storage().get_performnce_data().epic_failure_happend = true;
}
@ -975,10 +975,10 @@ namespace currency
}
//@#@
//temporary double check timestamp
if (time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) > 5)
if (time(NULL) - static_cast<int64_t>(get_block_datetime(b)) > 5)
{
LOG_PRINT_RED_L0("Found block (" << get_block_hash(b) << ") timestamp (" << get_actual_timestamp(b)
<< ") is suspiciously less (" << time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) << ") than current time ( " << time(NULL) << ")");
LOG_PRINT_RED_L0("Found block (" << get_block_hash(b) << ") timestamp (" << get_block_datetime(b)
<< ") is suspiciously less (" << time(NULL) - static_cast<int64_t>(get_block_datetime(b)) << ") than current time ( " << time(NULL) << ")");
//mark node to make it easier to find it via scanner
m_core.get_blockchain_storage().get_performnce_data().epic_failure_happend = true;
}

View file

@ -1281,7 +1281,7 @@ void wallet2::handle_money_received2(const currency::block& b, const currency::t
m_transfer_history.push_back(AUTO_VAL_INIT(wallet_public::wallet_transfer_info()));
wallet_public::wallet_transfer_info& wti = m_transfer_history.back();
wti.is_income = true;
prepare_wti(wti, get_block_height(b), get_actual_timestamp(b), tx, amount, td);
prepare_wti(wti, get_block_height(b), get_block_datetime(b), tx, amount, td);
WLT_LOG_L1("[MONEY RECEIVED]: " << epee::serialization::store_t_to_json(wti));
rise_on_transfer2(wti);
}
@ -1311,7 +1311,7 @@ void wallet2::handle_money_spent2(const currency::block& b,
wti.remote_addresses = recipients;
wti.recipients_aliases = recipients_aliases;
prepare_wti(wti, get_block_height(b), get_actual_timestamp(b), in_tx, amount, td);
prepare_wti(wti, get_block_height(b), get_block_datetime(b), in_tx, amount, td);
WLT_LOG_L1("[MONEY SPENT]: " << epee::serialization::store_t_to_json(wti));
rise_on_transfer2(wti);
}
@ -3454,7 +3454,7 @@ bool wallet2::try_mint_pos(const currency::account_public_address& miner_address
build_minted_block(ctx.sp, ctx.rsp, miner_address);
}
WLT_LOG_L0("PoS mining iteration finished, status: " << ctx.rsp.status << ", used " << ctx.sp.pos_entries.size() << " entries with total amount: " << print_money_brief(pos_entries_amount));
WLT_LOG_L0("PoS mining: " << ctx.rsp.iterations_processed << " iterations finished, status: " << ctx.rsp.status << ", used " << ctx.sp.pos_entries.size() << " entries with total amount: " << print_money_brief(pos_entries_amount));
return true;
}
@ -3530,12 +3530,10 @@ bool wallet2::build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request&
const currency::txout_to_key& txtokey = boost::get<currency::txout_to_key>(target);
keys_ptrs.push_back(&txtokey.key);
//put actual time for tx block
b.timestamp = rsp.block_timestamp;
currency::etc_tx_time tt = AUTO_VAL_INIT(tt);
tt.v = m_core_runtime_config.get_core_time();
b.miner_tx.extra.push_back(tt);
WLT_LOG_MAGENTA("Applying actual timestamp: " << epee::misc_utils::get_time_str(tt.v), LOG_LEVEL_0);
// set a real timestamp
uint64_t current_timestamp = m_core_runtime_config.get_core_time();
set_block_datetime(current_timestamp, b);
WLT_LOG_MAGENTA("Applying actual timestamp: " << current_timestamp, LOG_LEVEL_0);
//sign block
res = prepare_and_sign_pos_block(b,
@ -3563,10 +3561,10 @@ bool wallet2::build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request&
m_wcallback->on_pos_block_found(b);
//@#@
//double check timestamp
if (time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) > 5)
if (time(NULL) - static_cast<int64_t>(get_block_datetime(b)) > 5)
{
WLT_LOG_RED("Found block (" << get_block_hash(b) << ") timestamp (" << get_actual_timestamp(b)
<< ") is suspiciously less (" << time(NULL) - static_cast<int64_t>(get_actual_timestamp(b)) << ") than current time ( " << time(NULL) << ")", LOG_LEVEL_0);
WLT_LOG_RED("Found block (" << get_block_hash(b) << ") timestamp (" << get_block_datetime(b)
<< ") is suspiciously less (" << time(NULL) - static_cast<int64_t>(get_block_datetime(b)) << ") than current time ( " << time(NULL) << ")", LOG_LEVEL_0);
}
//
return true;

View file

@ -1203,16 +1203,20 @@ namespace tools
const currency::core_runtime_config &runtime_config)
{
cxt.rsp.status = API_RETURN_CODE_NOT_FOUND;
uint64_t timstamp_start = runtime_config.get_core_time();
uint64_t timstamp_last_idle_call = runtime_config.get_core_time();
cxt.rsp.iterations_processed = 0;
uint64_t ts_from = cxt.rsp.starter_timestamp; // median ts of last BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW blocks
ts_from = ts_from - (ts_from % POS_SCAN_STEP) + POS_SCAN_STEP;
uint64_t ts_to = runtime_config.get_core_time() + CURRENCY_POS_BLOCK_FUTURE_TIME_LIMIT - 5;
ts_to = ts_to - (ts_to % POS_SCAN_STEP);
CHECK_AND_ASSERT_MES(ts_to > ts_from, false, "scan_pos: ts_to <= ts_from: " << ts_to << ", " << ts_from);
uint64_t ts_middle = (ts_to + ts_from) / 2;
ts_middle -= ts_middle % POS_SCAN_STEP;
uint64_t ts_window = std::min(ts_middle - ts_from, ts_to - ts_middle);
for (size_t i = 0; i != cxt.sp.pos_entries.size(); i++)
{
//set timestamp starting from timestamp%POS_SCAN_STEP = 0
uint64_t adjusted_starter_timestamp = timstamp_start - POS_SCAN_STEP;
adjusted_starter_timestamp = POS_SCAN_STEP * 2 - (adjusted_starter_timestamp%POS_SCAN_STEP) + adjusted_starter_timestamp;
bool go_past = true;
uint64_t step = 0;
@ -1232,7 +1236,7 @@ namespace tools
}
};
while(step <= POS_SCAN_WINDOW)
while(step <= ts_window)
{
//check every WALLET_POS_MINT_CHECK_HEIGHT_INTERVAL seconds if top block changes, in case - break loop
@ -1248,8 +1252,8 @@ namespace tools
}
uint64_t ts = go_past ? adjusted_starter_timestamp - step : adjusted_starter_timestamp + step;
if (ts < cxt.rsp.starter_timestamp)
uint64_t ts = go_past ? ts_middle - step : ts_middle + step;
if (ts < ts_from || ts > ts_to)
{
next_turn();
continue;

View file

@ -112,7 +112,7 @@ bool emission_test::c1(currency::core& c, size_t ev_index, const std::vector<tes
pb.step2_set_txs(std::vector<transaction>());
pb.step3_build_stake_kernel(stake_output_amount, stake_output_gidx, stake_output_key_image, difficulty, prev_id, null_hash, timestamp);
pb.step4_generate_coinbase_tx(0, already_generated_coins, m_miner_acc.get_public_address());
pb.m_block.miner_tx.extra.push_back(currency::etc_tx_time({ timestamp })); // actual timestamp
set_block_datetime(timestamp, pb.m_block);
pb.step5_sign(stake_tx_pub_key, stake_output_idx, stake_output_pubkey, m_miner_acc);
c.handle_incoming_block(t_serializable_object_to_blob(pb.m_block), bvc);

View file

@ -634,7 +634,7 @@ bool hard_fork_1_pos_and_locked_coins::generate(std::vector<test_event_entry>& e
{
MAKE_NEXT_POS_BLOCK(events, b, prev, miner_acc, std::list<currency::account_base>{miner_acc});
prev = b;
events.push_back(event_core_time(get_actual_timestamp(b) + 100));
events.push_back(event_core_time(get_block_datetime(b) + 100));
}

View file

@ -1365,7 +1365,7 @@ bool gen_wallet_transfers_and_chain_switch::generate(std::vector<test_event_entr
CHECK_AND_ASSERT_MES(trs.size() == 2 && trs[0].is_spent() && trs[1].is_spent(), false, "Wrong transfers state");
// fast forward time to make tx_1 and tx_2 outdated (blk_3 is the block where tx_2 came with)
test_core_time::adjust(get_actual_timestamp(blk_3) + CURRENCY_MEMPOOL_TX_LIVETIME + 1);
test_core_time::adjust(get_block_datetime(blk_3) + CURRENCY_MEMPOOL_TX_LIVETIME + 1);
MAKE_NEXT_BLOCK(events, blk_5a, blk_4a, miner_acc);