Skip to content

Commit

Permalink
Use supernode aggregated stakes instead of stake transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
LenyKholodov committed Mar 10, 2019
1 parent 8d78cbb commit ad0241f
Show file tree
Hide file tree
Showing 12 changed files with 335 additions and 141 deletions.
21 changes: 12 additions & 9 deletions src/cryptonote_core/blockchain_based_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ void BlockchainBasedList::apply_block(uint64_t block_height, const crypto::hash&
if (block_height != m_block_height + 1)
throw std::runtime_error("block_height should be next after the block already processed");

const StakeTransactionStorage::stake_transaction_array& stake_txs = stake_txs_storage.get_txs();
const StakeTransactionStorage::supernode_stake_array& stakes = stake_txs_storage.get_supernode_stakes();

//build blockchain based list for each tier

Expand All @@ -107,22 +107,25 @@ void BlockchainBasedList::apply_block(uint64_t block_height, const crypto::hash&
return !is_valid_stake(block_height, desc.block_height, desc.unlock_time);
}), prev_supernodes.end());

current_supernodes.reserve(stake_txs.size());
current_supernodes.reserve(stakes.size());

for (const stake_transaction& stake_tx : stake_txs)
for (const supernode_stake& stake : stakes)
{
if (!is_valid_stake(block_height, stake_tx.block_height, stake_tx.unlock_time))
if (!stake.amount)
continue;

if (stake_tx.tier != i)
if (!is_valid_stake(block_height, stake.block_height, stake.unlock_time))
continue;

if (stake.tier != i)
continue;

supernode sn;

sn.supernode_public_id = stake_tx.supernode_public_id;
sn.supernode_public_address = stake_tx.supernode_public_address;
sn.block_height = stake_tx.block_height;
sn.unlock_time = stake_tx.unlock_time;
sn.supernode_public_id = stake.supernode_public_id;
sn.supernode_public_address = stake.supernode_public_address;
sn.block_height = stake.block_height;
sn.unlock_time = stake.unlock_time;

current_supernodes.emplace_back(std::move(sn));
}
Expand Down
9 changes: 5 additions & 4 deletions src/cryptonote_core/cryptonote_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1096,14 +1096,14 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
void core::set_update_stake_transactions_handler(const stake_transactions_update_handler& handler)
void core::set_update_stakes_handler(const supernode_stakes_update_handler& handler)
{
m_graft_stake_transaction_processor.set_on_update_stake_transactions_handler(handler);
m_graft_stake_transaction_processor.set_on_update_stakes_handler(handler);
}
//-----------------------------------------------------------------------------------------------
void core::invoke_update_stake_transactions_handler()
void core::invoke_update_stakes_handler()
{
m_graft_stake_transaction_processor.invoke_update_stake_transactions_handler(true);
m_graft_stake_transaction_processor.invoke_update_stakes_handler(true);
}
//-----------------------------------------------------------------------------------------------
void core::set_update_blockchain_based_list_handler(const blockchain_based_list_update_handler& handler)
Expand Down Expand Up @@ -1294,6 +1294,7 @@ namespace cryptonote
m_check_updates_interval.do_call(boost::bind(&core::check_updates, this));
m_miner.on_idle();
m_mempool.on_idle();
m_graft_stake_transaction_processor.synchronize();
return true;
}
//-----------------------------------------------------------------------------------------------
Expand Down
10 changes: 5 additions & 5 deletions src/cryptonote_core/cryptonote_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -737,16 +737,16 @@ namespace cryptonote
bool fluffy_blocks_enabled() const { return m_fluffy_blocks_enabled; }

/**
* @brief set update handler for new stake transactions
* @brief set update handler for supernode stakes
*/
typedef StakeTransactionProcessor::stake_transactions_update_handler stake_transactions_update_handler;
typedef StakeTransactionProcessor::supernode_stakes_update_handler supernode_stakes_update_handler;

void set_update_stake_transactions_handler(const stake_transactions_update_handler&);
void set_update_stakes_handler(const supernode_stakes_update_handler&);

/**
* @brief invoke stake transactions update handler
* @brief invoke stakes update handler
*/
void invoke_update_stake_transactions_handler();
void invoke_update_stakes_handler();

/**
* @brief set update handler for new blockchain based list
Expand Down
106 changes: 33 additions & 73 deletions src/cryptonote_core/stake_transaction_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,8 @@ using namespace cryptonote;
namespace
{

const char* STAKE_TRANSACTION_STORAGE_FILE_NAME = "stake_transactions.bin";
const char* BLOCKCHAIN_BASED_LIST_FILE_NAME = "blockchain_based_list.v1.bin";

unsigned int get_tier(uint64_t stake)
{
return 0 +
(stake >= config::graft::TIER1_STAKE_AMOUNT) +
(stake >= config::graft::TIER2_STAKE_AMOUNT) +
(stake >= config::graft::TIER3_STAKE_AMOUNT) +
(stake >= config::graft::TIER4_STAKE_AMOUNT);
}
const char* STAKE_TRANSACTION_STORAGE_FILE_NAME = "stake_transactions.v1.bin";
const char* BLOCKCHAIN_BASED_LIST_FILE_NAME = "blockchain_based_list.v2.bin";

}

Expand All @@ -30,19 +21,27 @@ bool stake_transaction::is_valid(uint64_t block_index) const
if (block_index < stake_first_valid_block)
return false;

if (block_index > stake_last_valid_block)
if (block_index >= stake_last_valid_block)
return false;

return true;
}

StakeTransactionProcessor::StakeTransactionProcessor(Blockchain& blockchain)
: m_blockchain(blockchain)
, m_stake_transactions_need_update(true)
, m_stakes_need_update(true)
, m_blockchain_based_list_need_update(true)
{
}

const supernode_stake* StakeTransactionProcessor::find_supernode_stake(const std::string& supernode_public_id) const
{
if (!m_storage)
return nullptr;

return m_storage->find_supernode_stake(supernode_public_id);
}

namespace
{

Expand Down Expand Up @@ -129,6 +128,8 @@ void StakeTransactionProcessor::process_block_stake_transaction(uint64_t block_i

BlockchainDB& db = m_blockchain.get_db();

//analyze block transactions and add new stake transactions if exist

stake_transaction stake_tx;

for (const crypto::hash& tx_hash : block.tx_hashes)
Expand Down Expand Up @@ -187,38 +188,23 @@ void StakeTransactionProcessor::process_block_stake_transaction(uint64_t block_i
stake_tx.block_height = block_index;
stake_tx.hash = tx_hash;
stake_tx.unlock_time = unlock_time;
stake_tx.tier = get_tier(stake_tx.amount);

if (!stake_tx.tier)
{
MCLOG(el::Level::Warning, "global", "Ignore stake transaction at block #" << block_index << ", tx_hash=" << tx_hash << ", supernode_public_id '" << stake_tx.supernode_public_id << "'"
<< " because amount " << amount / double(COIN) << " is less than minimum required " << config::graft::TIER1_STAKE_AMOUNT / double(COIN));
continue;
}

m_storage->add_tx(stake_tx);

m_stake_transactions_need_update = true;

MCLOG(el::Level::Info, "global", "New stake transaction found at block #" << block_index << ", tx_hash=" << tx_hash << ", supernode_public_id '" << stake_tx.supernode_public_id
<< "', amount=" << amount / double(COIN));
}

uint64_t prev_block = m_storage->get_last_processed_block_index();
//remove obsolete stake transactions from a storage

const stake_transaction_array& stake_txs = m_storage->get_txs();
m_storage->remove_obsolete_txs(block_index);

for (const stake_transaction& tx : stake_txs)
{
bool is_valid_for_this_block = tx.is_valid(block_index),
is_valid_for_prev_block = prev_block && tx.is_valid(prev_block);
//update supernode stakes

if (is_valid_for_prev_block != is_valid_for_this_block)
{
m_stake_transactions_need_update = true;
break;
}
}
if (m_storage->update_supernode_stakes(block_index))
m_stakes_need_update = true;

//update cache entries and save storage

m_storage->add_last_processed_block(block_index, block_hash);

Expand Down Expand Up @@ -277,7 +263,7 @@ void StakeTransactionProcessor::synchronize()
m_storage->remove_last_processed_block();

if (stake_tx_count != m_storage->get_tx_count())
m_stake_transactions_need_update = true;
m_storage->clear_supernode_stakes();

if (m_blockchain_based_list->block_height() == last_processed_block_index)
m_blockchain_based_list->remove_latest_block();
Expand Down Expand Up @@ -320,8 +306,8 @@ void StakeTransactionProcessor::synchronize()
if (m_storage->need_store())
m_storage->store();

if (m_stake_transactions_need_update && m_on_stake_transactions_update)
invoke_update_stake_transactions_handler_impl();
if (m_stakes_need_update && m_on_stakes_update)
invoke_update_stakes_handler_impl();

if (m_blockchain_based_list_need_update && m_on_blockchain_based_list_update)
invoke_update_blockchain_based_list_handler_impl(height - first_block_index);
Expand All @@ -330,63 +316,37 @@ void StakeTransactionProcessor::synchronize()
MCLOG(el::Level::Info, "global", "Stake transactions sync OK");
}

void StakeTransactionProcessor::set_on_update_stake_transactions_handler(const stake_transactions_update_handler& handler)
void StakeTransactionProcessor::set_on_update_stakes_handler(const supernode_stakes_update_handler& handler)
{
CRITICAL_REGION_LOCAL1(m_storage_lock);
m_on_stake_transactions_update = handler;
m_on_stakes_update = handler;
}

void StakeTransactionProcessor::invoke_update_stake_transactions_handler_impl()
void StakeTransactionProcessor::invoke_update_stakes_handler_impl()
{
try
{
stake_transaction_array valid_stake_txs;
const stake_transaction_array& stake_txs = m_storage->get_txs();

valid_stake_txs.reserve(stake_txs.size());

uint64_t top_block_index = m_blockchain.get_db().height() - 1;

for (const stake_transaction& tx : stake_txs)
{
stake_transaction tx_copy = tx;

if (!tx_copy.is_valid(top_block_index))
{
uint64_t first_history_block = top_block_index - config::graft::SUPERNODE_HISTORY_SIZE;

if (tx_copy.block_height + tx_copy.unlock_time < first_history_block)
continue;

//add stake transaction with zero amount to indicate correspondent node presense for search in supernode

tx_copy.amount = 0;
}

valid_stake_txs.emplace_back(std::move(tx_copy));
}

m_on_stake_transactions_update(valid_stake_txs);
m_on_stakes_update(m_storage->get_supernode_stakes());

m_stake_transactions_need_update = false;
m_stakes_need_update = false;
}
catch (std::exception& e)
{
MCLOG(el::Level::Error, "global", "exception in StakeTransactionProcessor stake transactions update handler: " << e.what());
}
}

void StakeTransactionProcessor::invoke_update_stake_transactions_handler(bool force)
void StakeTransactionProcessor::invoke_update_stakes_handler(bool force)
{
CRITICAL_REGION_LOCAL1(m_storage_lock);

if (!m_on_stake_transactions_update)
if (!m_on_stakes_update)
return;

if (!m_stake_transactions_need_update && !force)
if (!m_stakes_need_update && !force)
return;

invoke_update_stake_transactions_handler_impl();
invoke_update_stakes_handler_impl();
}

void StakeTransactionProcessor::set_on_update_blockchain_based_list_handler(const blockchain_based_list_update_handler& handler)
Expand Down
21 changes: 12 additions & 9 deletions src/cryptonote_core/stake_transaction_processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,26 @@ namespace cryptonote
class StakeTransactionProcessor
{
public:
typedef StakeTransactionStorage::stake_transaction_array stake_transaction_array;
typedef StakeTransactionStorage::supernode_stake_array supernode_stake_array;

StakeTransactionProcessor(Blockchain& blockchain);

/// Initialize storages
void init_storages(const std::string& config_dir);

/// Search supernode stake by supernode public id (returns nullptr if no stake is found)
const supernode_stake* find_supernode_stake(const std::string& supernode_public_id) const;

/// Synchronize with blockchain
void synchronize();

typedef std::function<void(const stake_transaction_array&)> stake_transactions_update_handler;
typedef std::function<void(const supernode_stake_array&)> supernode_stakes_update_handler;

/// Update handler for new stake transactions
void set_on_update_stake_transactions_handler(const stake_transactions_update_handler&);
/// Update handler for new stakes
void set_on_update_stakes_handler(const supernode_stakes_update_handler&);

/// Force invoke update handler for stake transactions
void invoke_update_stake_transactions_handler(bool force = true);
/// Force invoke update handler for stakes
void invoke_update_stakes_handler(bool force = true);

typedef BlockchainBasedList::supernode_tier_array supernode_tier_array;
typedef std::function<void(uint64_t block_number, const supernode_tier_array&)> blockchain_based_list_update_handler;
Expand All @@ -42,7 +45,7 @@ class StakeTransactionProcessor

private:
void process_block(uint64_t block_index, const block& block, const crypto::hash& block_hash, bool update_storage = true);
void invoke_update_stake_transactions_handler_impl();
void invoke_update_stakes_handler_impl();
void invoke_update_blockchain_based_list_handler_impl(size_t depth);
void process_block_stake_transaction(uint64_t block_index, const block& block, const crypto::hash& block_hash, bool update_storage = true);
void process_block_blockchain_based_list(uint64_t block_index, const block& block, const crypto::hash& block_hash, bool update_storage = true);
Expand All @@ -52,9 +55,9 @@ class StakeTransactionProcessor
std::unique_ptr<StakeTransactionStorage> m_storage;
std::unique_ptr<BlockchainBasedList> m_blockchain_based_list;
epee::critical_section m_storage_lock;
stake_transactions_update_handler m_on_stake_transactions_update;
supernode_stakes_update_handler m_on_stakes_update;
blockchain_based_list_update_handler m_on_blockchain_based_list_update;
bool m_stake_transactions_need_update;
bool m_stakes_need_update;
bool m_blockchain_based_list_need_update;
};

Expand Down
Loading

0 comments on commit ad0241f

Please sign in to comment.