diff --git a/rai/core_test/rpc.cpp b/rai/core_test/rpc.cpp index 9d5bcd90..be24820b 100644 --- a/rai/core_test/rpc.cpp +++ b/rai/core_test/rpc.cpp @@ -1575,19 +1575,19 @@ TEST (rpc, frontier_count) TEST (rpc, available_supply) { - rai::system system (24000, 1); + rai::system system (24000, 1); rai::node_init init1; - auto & node1 (*system.nodes [0]); - rai::rpc rpc (system.service, node1, rai::rpc_config (true)); + auto & node1 (*system.nodes [0]); + rai::rpc rpc (system.service, node1, rai::rpc_config (true)); rpc.start (); - boost::property_tree::ptree request1; + boost::property_tree::ptree request1; request1.put ("action", "available_supply"); test_response response1 (request1, rpc, system.service); while (response1.status == 0) { system.poll (); } - ASSERT_EQ (200, response1.status); + ASSERT_EQ (200, response1.status); ASSERT_EQ ("0", response1.json.get ("available")); system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv); rai::keypair key; @@ -1597,8 +1597,16 @@ TEST (rpc, available_supply) { system.poll (); } - ASSERT_EQ (200, response2.status); + ASSERT_EQ (200, response2.status); ASSERT_EQ ("1", response2.json.get ("available")); + auto block2 (system.wallet (0)->send_action (rai::test_genesis_key.pub, 0, 100)); // Sending to burning 0 account + test_response response3 (request1, rpc, system.service); + while (response3.status == 0) + { + system.poll (); + } + ASSERT_EQ (200, response3.status); + ASSERT_EQ ("1", response3.json.get ("available")); } TEST (rpc, mrai_to_raw) diff --git a/rai/node/node.cpp b/rai/node/node.cpp index a8fb760f..e1002f36 100755 --- a/rai/node/node.cpp +++ b/rai/node/node.cpp @@ -1280,6 +1280,13 @@ rai::process_return rai::block_processor::process_receive_one (MDB_txn * transac BOOST_LOG (node.log) << boost::str (boost::format ("Account mismatch for: %1%") % block_a->hash ().to_string ()); } } + case rai::process_result::fork_burning: + { + if (node.config.logging.ledger_logging ()) + { + BOOST_LOG (node.log) << boost::str (boost::format ("Fork of burning 0 account for: %1%") % block_a->hash ().to_string ()); + } + } } return result; } diff --git a/rai/node/rpc.cpp b/rai/node/rpc.cpp index 4def7a33..706cfaf5 100755 --- a/rai/node/rpc.cpp +++ b/rai/node/rpc.cpp @@ -830,7 +830,8 @@ void rai::rpc_handler::available_supply () auto genesis_balance (node.balance (rai::genesis_account)); // Cold storage genesis auto landing_balance (node.balance (rai::account ("059F68AAB29DE0D3A27443625C7EA9CDDB6517A8B76FE37727EF6A4D76832AD5"))); // Active unavailable account auto faucet_balance (node.balance (rai::account ("8E319CE6F3025E5B2DF66DA7AB1467FE48F1679C13DD43BFDB29FA2E9FC40D3B"))); // Faucet account - auto available (rai::genesis_amount - genesis_balance - landing_balance - faucet_balance); + auto burned_balance ((node.balance_pending (rai::account (0))).second); // Burning 0 account + auto available (rai::genesis_amount - genesis_balance - landing_balance - faucet_balance - burned_balance); boost::property_tree::ptree response_l; response_l.put ("available", available.convert_to ()); response (response_l); diff --git a/rai/secure.cpp b/rai/secure.cpp index 5bcdff2e..15287f98 100755 --- a/rai/secure.cpp +++ b/rai/secure.cpp @@ -3151,7 +3151,8 @@ rai::process_return rai::ledger::process (MDB_txn * transaction_a, rai::block co rai::uint128_t rai::ledger::supply (MDB_txn * transaction_a) { auto unallocated (account_balance (transaction_a, rai::genesis_account)); - auto absolute_supply (rai::genesis_amount - unallocated); + auto burned (account_pending (transaction_a, 0)); + auto absolute_supply (rai::genesis_amount - unallocated - burned); auto adjusted_supply (absolute_supply - inactive_supply); return adjusted_supply <= absolute_supply ? adjusted_supply : 0; } @@ -3544,16 +3545,20 @@ void ledger_processor::open_block (rai::open_block const & block_a) result.code = ledger.store.pending_get (transaction, key, pending) ? rai::process_result::unreceivable : rai::process_result::progress; // Has this source already been received (Malformed) if (result.code == rai::process_result::progress) { - rai::account_info source_info; - auto error (ledger.store.account_get (transaction, pending.source, source_info)); - assert (!error); - ledger.store.pending_del (transaction, key); - ledger.store.block_put (transaction, hash, block_a); - ledger.change_latest (transaction, block_a.hashables.account, hash, hash, pending.amount.number (), info.block_count + 1); - ledger.store.representation_add (transaction, hash, pending.amount.number ()); - ledger.store.frontier_put (transaction, hash, block_a.hashables.account); - result.account = block_a.hashables.account; - result.amount = pending.amount; + result.code = block_a.hashables.account.is_zero () ? rai::process_result::fork_burning : rai::process_result::progress; // Is it burning 0 account? (Malicious) + if (result.code == rai::process_result::progress) + { + rai::account_info source_info; + auto error (ledger.store.account_get (transaction, pending.source, source_info)); + assert (!error); + ledger.store.pending_del (transaction, key); + ledger.store.block_put (transaction, hash, block_a); + ledger.change_latest (transaction, block_a.hashables.account, hash, hash, pending.amount.number (), info.block_count + 1); + ledger.store.representation_add (transaction, hash, pending.amount.number ()); + ledger.store.frontier_put (transaction, hash, block_a.hashables.account); + result.account = block_a.hashables.account; + result.amount = pending.amount; + } } } } diff --git a/rai/secure.hpp b/rai/secure.hpp index cafad76d..5ff37641 100644 --- a/rai/secure.hpp +++ b/rai/secure.hpp @@ -517,7 +517,8 @@ enum class process_result gap_previous, // Block marked as previous is unknown gap_source, // Block marked as source is unknown not_receive_from_send, // Receive does not have a send source - account_mismatch // Account number in open block doesn't match send destination + account_mismatch, // Account number in open block doesn't match send destination + fork_burning // Malicious fork based on spending of burned amount }; class process_return {