Skip to content

Commit 69a5c87

Browse files
committed
fcmp++: wallet: use HF table to determine whether to use FCMP++ unlock rules when offline
Fixes issue found by @nahuhh where `account new` and `balance` commands in the CLI throw exceptions when offline.
1 parent 90ce152 commit 69a5c87

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

src/wallet/wallet2.cpp

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7355,9 +7355,22 @@ bool wallet2::is_transfer_unlocked(uint64_t unlock_time, uint64_t block_height)
73557355
//----------------------------------------------------------------------------------------------------
73567356
bool wallet2::is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t block_height)
73577357
{
7358-
if (use_fork_rules(HF_VERSION_FCMP_PLUS_PLUS, 0))
7358+
bool use_fcmp_pp_unlock_rules = false;
7359+
try
7360+
{
7361+
// use FCMP++ rules if check daemon earliest height for HF_VERSION_FCMP_PLUS_PLUS is here
7362+
use_fcmp_pp_unlock_rules = use_fork_rules(HF_VERSION_FCMP_PLUS_PLUS, 0);
7363+
}
7364+
catch (...) // in case of daemon failure...
7365+
{
7366+
// use FCMP++ rules if latest refreshed height is at least hard fork table's height for HF_VERSION_FCMP_PLUS_PLUS
7367+
use_fcmp_pp_unlock_rules = use_fork_rules_offline(HF_VERSION_FCMP_PLUS_PLUS, 0);
7368+
}
7369+
if (use_fcmp_pp_unlock_rules)
73597370
return get_blockchain_current_height() >= (cryptonote::get_last_locked_block_index(unlock_time, block_height)+1);
73607371

7372+
// else, use pre-FCMP++ unlock rules...
7373+
73617374
if(unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER)
73627375
{
73637376
//interpret as block index
@@ -11654,6 +11667,37 @@ bool wallet2::use_fork_rules(uint8_t version, int64_t early_blocks)
1165411667
return close_enough;
1165511668
}
1165611669
//----------------------------------------------------------------------------------------------------
11670+
bool wallet2::use_fork_rules_offline(uint8_t version, int64_t early_blocks) const
11671+
{
11672+
// get hard fork table based on network type
11673+
const size_t wallet_num_hard_forks = m_nettype == TESTNET ? num_testnet_hard_forks
11674+
: m_nettype == STAGENET ? num_stagenet_hard_forks : num_mainnet_hard_forks;
11675+
const hardfork_t *wallet_hard_forks = m_nettype == TESTNET ? testnet_hard_forks
11676+
: m_nettype == STAGENET ? stagenet_hard_forks : mainnet_hard_forks;
11677+
11678+
// find hard fork with lowest version >= `version`
11679+
const hardfork_t *best_fork_info = nullptr;
11680+
for (std::size_t i = 0; i < wallet_num_hard_forks; ++i)
11681+
{
11682+
const hardfork_t &fork_info = wallet_hard_forks[i];
11683+
if (fork_info.version < version)
11684+
continue;
11685+
if (nullptr == best_fork_info || fork_info.version < best_fork_info->version)
11686+
best_fork_info = &fork_info;
11687+
}
11688+
11689+
if (nullptr == best_fork_info) // did not find fork in table
11690+
return false;
11691+
11692+
const int64_t height = static_cast<int64_t>(get_blockchain_current_height());
11693+
const bool close_enough = height >= static_cast<int64_t>(best_fork_info->height) - early_blocks;
11694+
if (close_enough)
11695+
LOG_PRINT_L2("Using v" << static_cast<unsigned>(version) << " rules (offline)");
11696+
else
11697+
LOG_PRINT_L2("Not using v" << static_cast<unsigned>(version) << " rules (offline)");
11698+
return close_enough;
11699+
}
11700+
//----------------------------------------------------------------------------------------------------
1165711701
uint64_t wallet2::get_upper_transaction_weight_limit()
1165811702
{
1165911703
if (m_upper_transaction_weight_limit > 0)

src/wallet/wallet2.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,20 @@ namespace tools
11421142

11431143
uint8_t get_current_hard_fork();
11441144
void get_hard_fork_info(uint8_t version, uint64_t &earliest_height);
1145+
/**
1146+
* brief: determine if daemon's blockchain is past a certain fork version
1147+
* param: version - fork version
1148+
* param: early_blocks - threshold of blocks for which the the fork can be away from activation
1149+
* return: true iff daemon's blockchain is past the fork version, within said threshold
1150+
*/
11451151
bool use_fork_rules(uint8_t version, int64_t early_blocks = 0);
1152+
/**
1153+
* brief: determine if wallet's cached blockchain is past a certain fork version, according to its own fork table
1154+
* param: version - fork version
1155+
* param: early_blocks - threshold of blocks for which the the fork can be away from activation
1156+
* return: true iff wallet's cached blockchain is past the fork version, within said threshold
1157+
*/
1158+
bool use_fork_rules_offline(uint8_t version, int64_t early_blocks = 0) const;
11461159
fee_algorithm get_fee_algorithm();
11471160

11481161
std::string get_wallet_file() const;

0 commit comments

Comments
 (0)