Validate work difficulty during ledger processing (#2667)
Block work is now validated during ledger processing according to their epoch version and some block details. The following article details the reasoning for this change: [Development Update: V21 PoW Difficulty Increases](https://medium.com/nanocurrency/development-update-v21-pow-difficulty-increases-362b5d052c8e). When an account is upgraded with epoch 2, blocks must meet the new thresholds or they are discarded during ledger processing. Before ledger processing, an initial work validation is performed on node entry.
This commit is contained in:
parent
55dcc11b64
commit
8df03622e9
6 changed files with 248 additions and 114 deletions
|
|
@ -2969,3 +2969,90 @@ TEST (ledger, zero_rep)
|
||||||
ASSERT_EQ (nano::genesis_amount, node1.ledger.cache.rep_weights.representation_get (nano::test_genesis_key.pub));
|
ASSERT_EQ (nano::genesis_amount, node1.ledger.cache.rep_weights.representation_get (nano::test_genesis_key.pub));
|
||||||
ASSERT_EQ (0, node1.ledger.cache.rep_weights.representation_get (0));
|
ASSERT_EQ (0, node1.ledger.cache.rep_weights.representation_get (0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST (ledger, work_validation)
|
||||||
|
{
|
||||||
|
nano::logger_mt logger;
|
||||||
|
auto store = nano::make_store (logger, nano::unique_path ());
|
||||||
|
ASSERT_TRUE (!store->init_error ());
|
||||||
|
nano::stat stats;
|
||||||
|
nano::ledger ledger (*store, stats);
|
||||||
|
nano::genesis genesis;
|
||||||
|
store->initialize (store->tx_begin_write (), genesis, ledger.cache);
|
||||||
|
nano::work_pool pool (std::numeric_limits<unsigned>::max ());
|
||||||
|
nano::block_builder builder;
|
||||||
|
auto gen = nano::test_genesis_key;
|
||||||
|
nano::keypair key;
|
||||||
|
|
||||||
|
// With random work the block doesn't pass, then modifies the block with sufficient work and ensures a correct result
|
||||||
|
auto process_block = [&store, &ledger, &pool](nano::block & block_a, nano::block_details const details_a) {
|
||||||
|
EXPECT_EQ (nano::process_result::insufficient_work, ledger.process (store->tx_begin_write (), block_a).code);
|
||||||
|
block_a.block_work_set (*pool.generate (block_a.root (), nano::work_threshold (block_a.work_version (), details_a)));
|
||||||
|
EXPECT_EQ (nano::process_result::progress, ledger.process (store->tx_begin_write (), block_a).code);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::error_code ec;
|
||||||
|
|
||||||
|
auto send = *builder.send ()
|
||||||
|
.previous (nano::genesis_hash)
|
||||||
|
.destination (gen.pub)
|
||||||
|
.balance (nano::genesis_amount - 1)
|
||||||
|
.sign (gen.prv, gen.pub)
|
||||||
|
.work (0)
|
||||||
|
.build (ec);
|
||||||
|
ASSERT_FALSE (ec);
|
||||||
|
|
||||||
|
auto receive = *builder.receive ()
|
||||||
|
.previous (send.hash ())
|
||||||
|
.source (send.hash ())
|
||||||
|
.sign (gen.prv, gen.pub)
|
||||||
|
.work (0)
|
||||||
|
.build (ec);
|
||||||
|
ASSERT_FALSE (ec);
|
||||||
|
|
||||||
|
auto change = *builder.change ()
|
||||||
|
.previous (receive.hash ())
|
||||||
|
.representative (key.pub)
|
||||||
|
.sign (gen.prv, gen.pub)
|
||||||
|
.work (0)
|
||||||
|
.build (ec);
|
||||||
|
ASSERT_FALSE (ec);
|
||||||
|
|
||||||
|
auto state = *builder.state ()
|
||||||
|
.account (gen.pub)
|
||||||
|
.previous (change.hash ())
|
||||||
|
.representative (gen.pub)
|
||||||
|
.balance (nano::genesis_amount - 1)
|
||||||
|
.link (key.pub)
|
||||||
|
.sign (gen.prv, gen.pub)
|
||||||
|
.work (0)
|
||||||
|
.build (ec);
|
||||||
|
ASSERT_FALSE (ec);
|
||||||
|
|
||||||
|
auto open = *builder.open ()
|
||||||
|
.account (key.pub)
|
||||||
|
.source (state.hash ())
|
||||||
|
.representative (key.pub)
|
||||||
|
.sign (key.prv, key.pub)
|
||||||
|
.work (0)
|
||||||
|
.build (ec);
|
||||||
|
ASSERT_FALSE (ec);
|
||||||
|
|
||||||
|
auto epoch = *builder.state ()
|
||||||
|
.account (key.pub)
|
||||||
|
.previous (open.hash ())
|
||||||
|
.balance (1)
|
||||||
|
.representative (key.pub)
|
||||||
|
.link (ledger.epoch_link (nano::epoch::epoch_1))
|
||||||
|
.sign (gen.prv, gen.pub)
|
||||||
|
.work (0)
|
||||||
|
.build (ec);
|
||||||
|
ASSERT_FALSE (ec);
|
||||||
|
|
||||||
|
process_block (send, {});
|
||||||
|
process_block (receive, {});
|
||||||
|
process_block (change, {});
|
||||||
|
process_block (state, nano::block_details (nano::epoch::epoch_0, true, false, false));
|
||||||
|
process_block (open, {});
|
||||||
|
process_block (epoch, nano::block_details (nano::epoch::epoch_1, false, false, true));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1707,6 +1707,16 @@ bool nano::block_details::deserialize (nano::stream & stream_a)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nano::block_sideband::block_sideband (nano::account const & account_a, nano::block_hash const & successor_a, nano::amount const & balance_a, uint64_t height_a, uint64_t timestamp_a, nano::block_details const & details_a) :
|
||||||
|
successor (successor_a),
|
||||||
|
account (account_a),
|
||||||
|
balance (balance_a),
|
||||||
|
height (height_a),
|
||||||
|
timestamp (timestamp_a),
|
||||||
|
details (details_a)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
nano::block_sideband::block_sideband (nano::account const & account_a, nano::block_hash const & successor_a, nano::amount const & balance_a, uint64_t height_a, uint64_t timestamp_a, nano::epoch epoch_a, bool is_send, bool is_receive, bool is_epoch) :
|
nano::block_sideband::block_sideband (nano::account const & account_a, nano::block_hash const & successor_a, nano::amount const & balance_a, uint64_t height_a, uint64_t timestamp_a, nano::epoch epoch_a, bool is_send, bool is_receive, bool is_epoch) :
|
||||||
successor (successor_a),
|
successor (successor_a),
|
||||||
account (account_a),
|
account (account_a),
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ class block_sideband final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
block_sideband () = default;
|
block_sideband () = default;
|
||||||
|
block_sideband (nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t, uint64_t, nano::block_details const &);
|
||||||
block_sideband (nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t, uint64_t, nano::epoch, bool is_send, bool is_receive, bool is_epoch);
|
block_sideband (nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t, uint64_t, nano::epoch, bool is_send, bool is_receive, bool is_epoch);
|
||||||
void serialize (nano::stream &, nano::block_type) const;
|
void serialize (nano::stream &, nano::block_type) const;
|
||||||
bool deserialize (nano::stream &, nano::block_type);
|
bool deserialize (nano::stream &, nano::block_type);
|
||||||
|
|
|
||||||
|
|
@ -86,8 +86,6 @@ void nano::block_processor::add (std::shared_ptr<nano::block> block_a, uint64_t
|
||||||
void nano::block_processor::add (nano::unchecked_info const & info_a)
|
void nano::block_processor::add (nano::unchecked_info const & info_a)
|
||||||
{
|
{
|
||||||
debug_assert (!nano::work_validate (*info_a.block));
|
debug_assert (!nano::work_validate (*info_a.block));
|
||||||
if (info_a.block->difficulty () >= nano::work_threshold (info_a.block->work_version ()))
|
|
||||||
{
|
|
||||||
if (info_a.verified == nano::signature_verification::unknown && (info_a.block->type () == nano::block_type::state || info_a.block->type () == nano::block_type::open || !info_a.account.is_zero ()))
|
if (info_a.verified == nano::signature_verification::unknown && (info_a.block->type () == nano::block_type::state || info_a.block->type () == nano::block_type::open || !info_a.account.is_zero ()))
|
||||||
{
|
{
|
||||||
state_block_signature_verification.add (info_a);
|
state_block_signature_verification.add (info_a);
|
||||||
|
|
@ -101,7 +99,6 @@ void nano::block_processor::add (nano::unchecked_info const & info_a)
|
||||||
condition.notify_all ();
|
condition.notify_all ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void nano::block_processor::force (std::shared_ptr<nano::block> block_a)
|
void nano::block_processor::force (std::shared_ptr<nano::block> block_a)
|
||||||
{
|
{
|
||||||
|
|
@ -448,6 +445,14 @@ nano::process_return nano::block_processor::process_one (nano::write_transaction
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case nano::process_result::insufficient_work:
|
||||||
|
{
|
||||||
|
if (node.config.logging.ledger_logging ())
|
||||||
|
{
|
||||||
|
node.logger.try_log (boost::str (boost::format ("Insufficient work for %1% : %2 (difficulty %3)") % hash.to_string () % info_a.block->block_work () % info_a.block->difficulty ()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -318,7 +318,8 @@ enum class process_result
|
||||||
opened_burn_account, // The impossible happened, someone found the private key associated with the public key '0'.
|
opened_burn_account, // The impossible happened, someone found the private key associated with the public key '0'.
|
||||||
balance_mismatch, // Balance and amount delta don't match
|
balance_mismatch, // Balance and amount delta don't match
|
||||||
representative_mismatch, // Representative is changed when it is not allowed
|
representative_mismatch, // Representative is changed when it is not allowed
|
||||||
block_position // This block cannot follow the previous block
|
block_position, // This block cannot follow the previous block
|
||||||
|
insufficient_work // Insufficient work for this block, even though it passed the minimal validation
|
||||||
};
|
};
|
||||||
class process_return final
|
class process_return final
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -332,9 +332,13 @@ void ledger_processor::state_block_impl (nano::state_block & block_a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result.code == nano::process_result::progress)
|
if (result.code == nano::process_result::progress)
|
||||||
|
{
|
||||||
|
nano::block_details block_details (epoch, is_send, is_receive, false);
|
||||||
|
result.code = block_a.difficulty () >= nano::work_threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
|
||||||
|
if (result.code == nano::process_result::progress)
|
||||||
{
|
{
|
||||||
ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::state_block);
|
ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::state_block);
|
||||||
block_a.sideband_set (nano::block_sideband (block_a.hashables.account /* unused */, 0, 0 /* unused */, info.block_count + 1, nano::seconds_since_epoch (), epoch, is_send, is_receive, false));
|
block_a.sideband_set (nano::block_sideband (block_a.hashables.account /* unused */, 0, 0 /* unused */, info.block_count + 1, nano::seconds_since_epoch (), block_details));
|
||||||
ledger.store.block_put (transaction, hash, block_a);
|
ledger.store.block_put (transaction, hash, block_a);
|
||||||
|
|
||||||
if (!info.head.is_zero ())
|
if (!info.head.is_zero ())
|
||||||
|
|
@ -369,6 +373,7 @@ void ledger_processor::state_block_impl (nano::state_block & block_a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ledger_processor::epoch_block_impl (nano::state_block & block_a)
|
void ledger_processor::epoch_block_impl (nano::state_block & block_a)
|
||||||
{
|
{
|
||||||
|
|
@ -418,11 +423,15 @@ void ledger_processor::epoch_block_impl (nano::state_block & block_a)
|
||||||
{
|
{
|
||||||
result.code = block_a.hashables.balance == info.balance ? nano::process_result::progress : nano::process_result::balance_mismatch;
|
result.code = block_a.hashables.balance == info.balance ? nano::process_result::progress : nano::process_result::balance_mismatch;
|
||||||
if (result.code == nano::process_result::progress)
|
if (result.code == nano::process_result::progress)
|
||||||
|
{
|
||||||
|
nano::block_details block_details (epoch, false, false, true);
|
||||||
|
result.code = block_a.difficulty () >= nano::work_threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
|
||||||
|
if (result.code == nano::process_result::progress)
|
||||||
{
|
{
|
||||||
ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::epoch_block);
|
ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::epoch_block);
|
||||||
result.account = block_a.hashables.account;
|
result.account = block_a.hashables.account;
|
||||||
result.amount = 0;
|
result.amount = 0;
|
||||||
block_a.sideband_set (nano::block_sideband (block_a.hashables.account /* unused */, 0, 0 /* unused */, info.block_count + 1, nano::seconds_since_epoch (), epoch, false, false, true));
|
block_a.sideband_set (nano::block_sideband (block_a.hashables.account /* unused */, 0, 0 /* unused */, info.block_count + 1, nano::seconds_since_epoch (), block_details));
|
||||||
ledger.store.block_put (transaction, hash, block_a);
|
ledger.store.block_put (transaction, hash, block_a);
|
||||||
nano::account_info new_info (hash, block_a.representative (), info.open_block.is_zero () ? hash : info.open_block, info.balance, nano::seconds_since_epoch (), info.block_count + 1, epoch);
|
nano::account_info new_info (hash, block_a.representative (), info.open_block.is_zero () ? hash : info.open_block, info.balance, nano::seconds_since_epoch (), info.block_count + 1, epoch);
|
||||||
ledger.change_latest (transaction, block_a.hashables.account, info, new_info);
|
ledger.change_latest (transaction, block_a.hashables.account, info, new_info);
|
||||||
|
|
@ -437,6 +446,7 @@ void ledger_processor::epoch_block_impl (nano::state_block & block_a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ledger_processor::change_block (nano::change_block & block_a)
|
void ledger_processor::change_block (nano::change_block & block_a)
|
||||||
{
|
{
|
||||||
|
|
@ -467,10 +477,14 @@ void ledger_processor::change_block (nano::change_block & block_a)
|
||||||
result.code = validate_message (account, hash, block_a.signature) ? nano::process_result::bad_signature : nano::process_result::progress; // Is this block signed correctly (Malformed)
|
result.code = validate_message (account, hash, block_a.signature) ? nano::process_result::bad_signature : nano::process_result::progress; // Is this block signed correctly (Malformed)
|
||||||
}
|
}
|
||||||
if (result.code == nano::process_result::progress)
|
if (result.code == nano::process_result::progress)
|
||||||
|
{
|
||||||
|
nano::block_details block_details (nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */);
|
||||||
|
result.code = block_a.difficulty () >= nano::work_threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
|
||||||
|
if (result.code == nano::process_result::progress)
|
||||||
{
|
{
|
||||||
debug_assert (!validate_message (account, hash, block_a.signature));
|
debug_assert (!validate_message (account, hash, block_a.signature));
|
||||||
result.verified = nano::signature_verification::valid;
|
result.verified = nano::signature_verification::valid;
|
||||||
block_a.sideband_set (nano::block_sideband (account, 0, info.balance, info.block_count + 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */));
|
block_a.sideband_set (nano::block_sideband (account, 0, info.balance, info.block_count + 1, nano::seconds_since_epoch (), block_details));
|
||||||
ledger.store.block_put (transaction, hash, block_a);
|
ledger.store.block_put (transaction, hash, block_a);
|
||||||
auto balance (ledger.balance (transaction, block_a.hashables.previous));
|
auto balance (ledger.balance (transaction, block_a.hashables.previous));
|
||||||
ledger.cache.rep_weights.representation_add (block_a.representative (), balance);
|
ledger.cache.rep_weights.representation_add (block_a.representative (), balance);
|
||||||
|
|
@ -488,6 +502,7 @@ void ledger_processor::change_block (nano::change_block & block_a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ledger_processor::send_block (nano::send_block & block_a)
|
void ledger_processor::send_block (nano::send_block & block_a)
|
||||||
{
|
{
|
||||||
|
|
@ -513,6 +528,10 @@ void ledger_processor::send_block (nano::send_block & block_a)
|
||||||
result.code = validate_message (account, hash, block_a.signature) ? nano::process_result::bad_signature : nano::process_result::progress; // Is this block signed correctly (Malformed)
|
result.code = validate_message (account, hash, block_a.signature) ? nano::process_result::bad_signature : nano::process_result::progress; // Is this block signed correctly (Malformed)
|
||||||
}
|
}
|
||||||
if (result.code == nano::process_result::progress)
|
if (result.code == nano::process_result::progress)
|
||||||
|
{
|
||||||
|
nano::block_details block_details (nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */);
|
||||||
|
result.code = block_a.difficulty () >= nano::work_threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
|
||||||
|
if (result.code == nano::process_result::progress)
|
||||||
{
|
{
|
||||||
debug_assert (!validate_message (account, hash, block_a.signature));
|
debug_assert (!validate_message (account, hash, block_a.signature));
|
||||||
result.verified = nano::signature_verification::valid;
|
result.verified = nano::signature_verification::valid;
|
||||||
|
|
@ -526,7 +545,7 @@ void ledger_processor::send_block (nano::send_block & block_a)
|
||||||
{
|
{
|
||||||
auto amount (info.balance.number () - block_a.hashables.balance.number ());
|
auto amount (info.balance.number () - block_a.hashables.balance.number ());
|
||||||
ledger.cache.rep_weights.representation_add (info.representative, 0 - amount);
|
ledger.cache.rep_weights.representation_add (info.representative, 0 - amount);
|
||||||
block_a.sideband_set (nano::block_sideband (account, 0, block_a.hashables.balance /* unused */, info.block_count + 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */));
|
block_a.sideband_set (nano::block_sideband (account, 0, block_a.hashables.balance /* unused */, info.block_count + 1, nano::seconds_since_epoch (), block_details));
|
||||||
ledger.store.block_put (transaction, hash, block_a);
|
ledger.store.block_put (transaction, hash, block_a);
|
||||||
nano::account_info new_info (hash, info.representative, info.open_block, block_a.hashables.balance, nano::seconds_since_epoch (), info.block_count + 1, nano::epoch::epoch_0);
|
nano::account_info new_info (hash, info.representative, info.open_block, block_a.hashables.balance, nano::seconds_since_epoch (), info.block_count + 1, nano::epoch::epoch_0);
|
||||||
ledger.change_latest (transaction, account, info, new_info);
|
ledger.change_latest (transaction, account, info, new_info);
|
||||||
|
|
@ -544,6 +563,7 @@ void ledger_processor::send_block (nano::send_block & block_a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ledger_processor::receive_block (nano::receive_block & block_a)
|
void ledger_processor::receive_block (nano::receive_block & block_a)
|
||||||
{
|
{
|
||||||
|
|
@ -587,6 +607,10 @@ void ledger_processor::receive_block (nano::receive_block & block_a)
|
||||||
{
|
{
|
||||||
result.code = pending.epoch == nano::epoch::epoch_0 ? nano::process_result::progress : nano::process_result::unreceivable; // Are we receiving a state-only send? (Malformed)
|
result.code = pending.epoch == nano::epoch::epoch_0 ? nano::process_result::progress : nano::process_result::unreceivable; // Are we receiving a state-only send? (Malformed)
|
||||||
if (result.code == nano::process_result::progress)
|
if (result.code == nano::process_result::progress)
|
||||||
|
{
|
||||||
|
nano::block_details block_details (nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */);
|
||||||
|
result.code = block_a.difficulty () >= nano::work_threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
|
||||||
|
if (result.code == nano::process_result::progress)
|
||||||
{
|
{
|
||||||
auto new_balance (info.balance.number () + pending.amount.number ());
|
auto new_balance (info.balance.number () + pending.amount.number ());
|
||||||
nano::account_info source_info;
|
nano::account_info source_info;
|
||||||
|
|
@ -594,7 +618,7 @@ void ledger_processor::receive_block (nano::receive_block & block_a)
|
||||||
(void)error;
|
(void)error;
|
||||||
debug_assert (!error);
|
debug_assert (!error);
|
||||||
ledger.store.pending_del (transaction, key);
|
ledger.store.pending_del (transaction, key);
|
||||||
block_a.sideband_set (nano::block_sideband (account, 0, new_balance, info.block_count + 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */));
|
block_a.sideband_set (nano::block_sideband (account, 0, new_balance, info.block_count + 1, nano::seconds_since_epoch (), block_details));
|
||||||
ledger.store.block_put (transaction, hash, block_a);
|
ledger.store.block_put (transaction, hash, block_a);
|
||||||
nano::account_info new_info (hash, info.representative, info.open_block, new_balance, nano::seconds_since_epoch (), info.block_count + 1, nano::epoch::epoch_0);
|
nano::account_info new_info (hash, info.representative, info.open_block, new_balance, nano::seconds_since_epoch (), info.block_count + 1, nano::epoch::epoch_0);
|
||||||
ledger.change_latest (transaction, account, info, new_info);
|
ledger.change_latest (transaction, account, info, new_info);
|
||||||
|
|
@ -610,6 +634,7 @@ void ledger_processor::receive_block (nano::receive_block & block_a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result.code = ledger.store.block_exists (transaction, block_a.hashables.previous) ? nano::process_result::fork : nano::process_result::gap_previous; // If we have the block but it's not the latest we have a signed fork (Malicious)
|
result.code = ledger.store.block_exists (transaction, block_a.hashables.previous) ? nano::process_result::fork : nano::process_result::gap_previous; // If we have the block but it's not the latest we have a signed fork (Malicious)
|
||||||
|
|
@ -652,13 +677,17 @@ void ledger_processor::open_block (nano::open_block & block_a)
|
||||||
{
|
{
|
||||||
result.code = pending.epoch == nano::epoch::epoch_0 ? nano::process_result::progress : nano::process_result::unreceivable; // Are we receiving a state-only send? (Malformed)
|
result.code = pending.epoch == nano::epoch::epoch_0 ? nano::process_result::progress : nano::process_result::unreceivable; // Are we receiving a state-only send? (Malformed)
|
||||||
if (result.code == nano::process_result::progress)
|
if (result.code == nano::process_result::progress)
|
||||||
|
{
|
||||||
|
nano::block_details block_details (nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */);
|
||||||
|
result.code = block_a.difficulty () >= nano::work_threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
|
||||||
|
if (result.code == nano::process_result::progress)
|
||||||
{
|
{
|
||||||
nano::account_info source_info;
|
nano::account_info source_info;
|
||||||
auto error (ledger.store.account_get (transaction, pending.source, source_info));
|
auto error (ledger.store.account_get (transaction, pending.source, source_info));
|
||||||
(void)error;
|
(void)error;
|
||||||
debug_assert (!error);
|
debug_assert (!error);
|
||||||
ledger.store.pending_del (transaction, key);
|
ledger.store.pending_del (transaction, key);
|
||||||
block_a.sideband_set (nano::block_sideband (block_a.hashables.account, 0, pending.amount, 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */));
|
block_a.sideband_set (nano::block_sideband (block_a.hashables.account, 0, pending.amount, 1, nano::seconds_since_epoch (), block_details));
|
||||||
ledger.store.block_put (transaction, hash, block_a);
|
ledger.store.block_put (transaction, hash, block_a);
|
||||||
nano::account_info new_info (hash, block_a.representative (), hash, pending.amount.number (), nano::seconds_since_epoch (), 1, nano::epoch::epoch_0);
|
nano::account_info new_info (hash, block_a.representative (), hash, pending.amount.number (), nano::seconds_since_epoch (), 1, nano::epoch::epoch_0);
|
||||||
ledger.change_latest (transaction, block_a.hashables.account, info, new_info);
|
ledger.change_latest (transaction, block_a.hashables.account, info, new_info);
|
||||||
|
|
@ -675,6 +704,7 @@ void ledger_processor::open_block (nano::open_block & block_a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ledger_processor::ledger_processor (nano::ledger & ledger_a, nano::write_transaction const & transaction_a, nano::signature_verification verification_a) :
|
ledger_processor::ledger_processor (nano::ledger & ledger_a, nano::write_transaction const & transaction_a, nano::signature_verification verification_a) :
|
||||||
ledger (ledger_a),
|
ledger (ledger_a),
|
||||||
|
|
@ -753,7 +783,7 @@ nano::uint128_t nano::ledger::account_pending (nano::transaction const & transac
|
||||||
|
|
||||||
nano::process_return nano::ledger::process (nano::write_transaction const & transaction_a, nano::block & block_a, nano::signature_verification verification)
|
nano::process_return nano::ledger::process (nano::write_transaction const & transaction_a, nano::block & block_a, nano::signature_verification verification)
|
||||||
{
|
{
|
||||||
debug_assert (!nano::work_validate (block_a));
|
debug_assert (network_params.network.is_test_network () || !nano::work_validate (block_a));
|
||||||
ledger_processor processor (*this, transaction_a, verification);
|
ledger_processor processor (*this, transaction_a, verification);
|
||||||
block_a.visit (processor);
|
block_a.visit (processor);
|
||||||
if (processor.result.code == nano::process_result::progress)
|
if (processor.result.code == nano::process_result::progress)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue