diff --git a/rai/core_test/ledger.cpp b/rai/core_test/ledger.cpp index 27290b6e02..9f952e6e9e 100644 --- a/rai/core_test/ledger.cpp +++ b/rai/core_test/ledger.cpp @@ -1247,6 +1247,40 @@ TEST (ledger, fail_receive_fork_previous) ASSERT_EQ (rai::process_result::fork, result5.code); } +TEST (ledger, fail_receive_received_source) +{ + bool init (false); + rai::block_store store (init, rai::unique_path ()); + ASSERT_FALSE (init); + rai::ledger ledger (store); + rai::genesis genesis; + rai::transaction transaction (store.environment, nullptr, true); + genesis.initialize (transaction, store); + rai::keypair key1; + rai::send_block block1 (genesis.hash (), key1.pub, 2, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0); + auto result1 (ledger.process (transaction, block1)); + ASSERT_EQ (rai::process_result::progress, result1.code); + rai::send_block block2 (block1.hash (), key1.pub, 1, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0); + auto result2 (ledger.process (transaction, block2)); + ASSERT_EQ (rai::process_result::progress, result2.code); + rai::send_block block6 (block2.hash (), key1.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0); + auto result6 (ledger.process (transaction, block6)); + ASSERT_EQ (rai::process_result::progress, result6.code); + rai::open_block block3 (block1.hash (), 1, key1.pub, key1.prv, key1.pub, 0); + auto result3 (ledger.process (transaction, block3)); + ASSERT_EQ (rai::process_result::progress, result3.code); + rai::keypair key2; + rai::send_block block4 (block3.hash (), key1.pub, 1, key1.prv, key1.pub, 0); + auto result4 (ledger.process (transaction, block4)); + ASSERT_EQ (rai::process_result::progress, result4.code); + rai::receive_block block5 (block4.hash (), block2.hash (), key1.prv, key1.pub, 0); + auto result5 (ledger.process (transaction, block5)); + ASSERT_EQ (rai::process_result::progress, result5.code); + rai::receive_block block7 (block3.hash (), block2.hash (), key1.prv, key1.pub, 0); + auto result7 (ledger.process (transaction, block7)); + ASSERT_EQ (rai::process_result::fork, result7.code); +} + TEST (ledger, latest_empty) { bool init (false); diff --git a/rai/secure.cpp b/rai/secure.cpp index 2feddde1c6..3e23390097 100644 --- a/rai/secure.cpp +++ b/rai/secure.cpp @@ -2886,24 +2886,27 @@ void ledger_processor::receive_block (rai::receive_block const & block_a) result.code = existing ? rai::process_result::old : rai::process_result::progress; // Have we seen this block already? (Harmless) if (result.code == rai::process_result::progress) { - auto source_missing (!ledger.store.block_exists (transaction, block_a.hashables.source)); + auto block (ledger.store.block_get (transaction, block_a.hashables.source)); + auto source_missing (block == nullptr); result.code = source_missing ? rai::process_result::gap_source : rai::process_result::progress; // Have we seen the source block already? (Harmless) if (result.code == rai::process_result::progress) { - rai::pending_info pending; - result.code = ledger.store.pending_get (transaction, block_a.hashables.source, pending) ? rai::process_result::unreceivable : rai::process_result::progress; // Has this source already been received (Malformed) - if (result.code == rai::process_result::progress) - { - result.code = rai::validate_message (pending.destination, hash, block_a.signature) ? rai::process_result::bad_signature : rai::process_result::progress; // Is the signature valid (Malformed) - if (result.code == rai::process_result::progress) - { - rai::account_info info; - result.code = ledger.store.account_get (transaction, pending.destination, info) ? rai::process_result::gap_previous : rai::process_result::progress; //Have we seen the previous block? No entries for account at all (Harmless) - if (result.code == rai::process_result::progress) - { - result.code = info.head == block_a.hashables.previous ? rai::process_result::progress : rai::process_result::gap_previous; // Block doesn't immediately follow latest block (Harmless) - if (result.code == rai::process_result::progress) - { + assert (dynamic_cast (block.get ()) != nullptr); + auto source (static_cast (block.get ())); + result.code = rai::validate_message (source->hashables.destination, hash, block_a.signature) ? rai::process_result::bad_signature : rai::process_result::progress; // Is the signature valid (Malformed) + if (result.code == rai::process_result::progress) + { + rai::account_info info; + result.code = ledger.store.account_get (transaction, source->hashables.destination, info) ? rai::process_result::gap_previous : rai::process_result::progress; //Have we seen the previous block? No entries for account at all (Harmless) + if (result.code == rai::process_result::progress) + { + result.code = info.head == block_a.hashables.previous ? rai::process_result::progress : rai::process_result::gap_previous; // Block doesn't immediately follow latest block (Harmless) + if (result.code == rai::process_result::progress) + { + rai::pending_info pending; + result.code = ledger.store.pending_get (transaction, block_a.hashables.source, pending) ? rai::process_result::unreceivable : rai::process_result::progress; // Has this source already been received (Malformed) + if (result.code == rai::process_result::progress) + { assert (ledger.store.frontier_get (transaction, block_a.hashables.previous) == pending.destination); auto new_balance (info.balance.number () + pending.amount.number ()); rai::account_info source_info; @@ -2918,11 +2921,11 @@ void ledger_processor::receive_block (rai::receive_block const & block_a) result.account = pending.destination; result.amount = pending.amount; } - else - { - result.code = ledger.store.block_exists (transaction, block_a.hashables.previous) ? rai::process_result::fork : rai::process_result::gap_previous; // If we have the block but it's not the latest we have a signed fork (Malicious) - } } + else + { + result.code = ledger.store.block_exists (transaction, block_a.hashables.previous) ? rai::process_result::fork : rai::process_result::gap_previous; // If we have the block but it's not the latest we have a signed fork (Malicious) + } } } }