From 69d69a4b10b4b7e7592479fb5574eb310f59facd Mon Sep 17 00:00:00 2001 From: clemahieu Date: Mon, 6 Feb 2017 23:51:36 -0600 Subject: [PATCH 1/5] Changing pending table to be keyed by account/hash instead of just hash in order to quickly query for pending blocks for an account. --- rai/core_test/block_store.cpp | 22 ++--- rai/core_test/ledger.cpp | 10 +-- rai/core_test/node.cpp | 4 +- rai/node/node.cpp | 2 +- rai/node/testing.cpp | 2 +- rai/node/wallet.cpp | 5 +- rai/qt/qt.cpp | 164 +++++++++++++++++++++------------- rai/secure.cpp | 82 ++++++++++++----- rai/secure.hpp | 22 +++-- 9 files changed, 203 insertions(+), 110 deletions(-) diff --git a/rai/core_test/block_store.cpp b/rai/core_test/block_store.cpp index 5355b220..27168394 100644 --- a/rai/core_test/block_store.cpp +++ b/rai/core_test/block_store.cpp @@ -107,16 +107,16 @@ TEST (block_store, add_pending) rai::block_store store (init, rai::unique_path ()); ASSERT_TRUE (!init); rai::keypair key1; - rai::block_hash hash1 (0); + rai::pending_key key2 (0, 0); rai::pending_info pending1; rai::transaction transaction (store.environment, nullptr, true); - ASSERT_TRUE (store.pending_get (transaction, hash1, pending1)); - store.pending_put (transaction, hash1, pending1); + ASSERT_TRUE (store.pending_get (transaction, key2, pending1)); + store.pending_put (transaction, key2, pending1); rai::pending_info pending2; - ASSERT_FALSE (store.pending_get (transaction, hash1, pending2)); + ASSERT_FALSE (store.pending_get (transaction, key2, pending2)); ASSERT_EQ (pending1, pending2); - store.pending_del (transaction, hash1); - ASSERT_TRUE (store.pending_get (transaction, hash1, pending2)); + store.pending_del (transaction, key2); + ASSERT_TRUE (store.pending_get (transaction, key2, pending2)); } TEST (block_store, pending_iterator) @@ -126,10 +126,12 @@ TEST (block_store, pending_iterator) ASSERT_TRUE (!init); rai::transaction transaction (store.environment, nullptr, true); ASSERT_EQ (store.pending_end (), store.pending_begin (transaction)); - store.pending_put (transaction, 1, {2, 3, 4}); + store.pending_put (transaction, rai::pending_key (1, 2), {2, 3, 4}); auto current (store.pending_begin (transaction)); ASSERT_NE (store.pending_end (), current); - ASSERT_EQ (rai::account (1), current->first); + rai::pending_key key1 (current->first); + ASSERT_EQ (rai::account (1), key1.account); + ASSERT_EQ (rai::block_hash (2), key1.hash); rai::pending_info pending (current->second); ASSERT_EQ (rai::account (2), pending.source); ASSERT_EQ (rai::amount (3), pending.amount); @@ -410,11 +412,11 @@ TEST (block_store, pending_exists) bool init (false); rai::block_store store (init, rai::unique_path ()); ASSERT_TRUE (!init); - rai::block_hash two (2); + rai::pending_key two (2, 0); rai::pending_info pending; rai::transaction transaction (store.environment, nullptr, true); store.pending_put (transaction, two, pending); - rai::block_hash one (1); + rai::pending_key one (1, 0); ASSERT_FALSE (store.pending_exists (transaction, one)); } diff --git a/rai/core_test/ledger.cpp b/rai/core_test/ledger.cpp index a89ace11..66d0d8ed 100644 --- a/rai/core_test/ledger.cpp +++ b/rai/core_test/ledger.cpp @@ -148,7 +148,7 @@ TEST (ledger, process_send) rai::account_info info5; ASSERT_TRUE (ledger.store.account_get (transaction, key2.pub, info5)); rai::pending_info pending1; - ASSERT_FALSE (ledger.store.pending_get (transaction, hash1, pending1)); + ASSERT_FALSE (ledger.store.pending_get (transaction, rai::pending_key (key2.pub, hash1), pending1)); ASSERT_EQ (rai::test_genesis_key.pub, pending1.source); ASSERT_EQ (key2.pub, pending1.destination); ASSERT_EQ (rai::genesis_amount - 50, pending1.amount.number ()); @@ -167,7 +167,7 @@ TEST (ledger, process_send) ASSERT_FALSE (ledger.store.account_get (transaction, rai::test_genesis_key.pub, info7)); ASSERT_EQ (info1.head, info7.head); rai::pending_info pending2; - ASSERT_TRUE (ledger.store.pending_get (transaction, hash1, pending2)); + ASSERT_TRUE (ledger.store.pending_get (transaction, rai::pending_key (key2.pub, hash1), pending2)); ASSERT_EQ (rai::genesis_amount, ledger.account_balance (transaction, rai::test_genesis_key.pub)); } @@ -220,7 +220,7 @@ TEST (ledger, process_receive) ASSERT_EQ (rai::genesis_amount - 50, ledger.weight (transaction, key3.pub)); ASSERT_EQ (hash2, ledger.latest (transaction, key2.pub)); rai::pending_info pending1; - ASSERT_FALSE (ledger.store.pending_get (transaction, hash3, pending1)); + ASSERT_FALSE (ledger.store.pending_get (transaction, rai::pending_key (key2.pub, hash3), pending1)); ASSERT_EQ (rai::test_genesis_key.pub, pending1.source); ASSERT_EQ (25, pending1.amount.number ()); } @@ -259,7 +259,7 @@ TEST (ledger, rollback_receiver) rai::account_info info2; ASSERT_TRUE (ledger.store.account_get (transaction, key2.pub, info2)); rai::pending_info pending1; - ASSERT_TRUE (ledger.store.pending_get (transaction, info2.head, pending1)); + ASSERT_TRUE (ledger.store.pending_get (transaction, rai::pending_key (key2.pub, info2.head), pending1)); } TEST (ledger, rollback_representation) @@ -1117,7 +1117,7 @@ TEST (ledger, fail_open_account_mismatch) ASSERT_EQ (rai::process_result::progress, ledger.process (transaction, block1).code); rai::keypair badkey; rai::open_block block2 (block1.hash (), 1, badkey.pub, badkey.prv, badkey.pub, 0); - ASSERT_EQ (rai::process_result::account_mismatch, ledger.process (transaction, block2).code); + ASSERT_NE (rai::process_result::progress, ledger.process (transaction, block2).code); } TEST (ledger, fail_receive_old) diff --git a/rai/core_test/node.cpp b/rai/core_test/node.cpp index 50bdbbf5..ec4e0523 100644 --- a/rai/core_test/node.cpp +++ b/rai/core_test/node.cpp @@ -711,7 +711,7 @@ TEST (node, fork_keep) auto & node1 (*system.nodes [0]); auto & node2 (*system.nodes [1]); ASSERT_EQ (1, node1.peers.size ()); - system.wallet (0)->insert_adhoc ( rai::test_genesis_key.prv); + system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv); rai::keypair key1; rai::genesis genesis; std::unique_ptr send1 (new rai::send_block (genesis.hash (), key1.pub, rai::genesis_amount - 100, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ()))); @@ -742,7 +742,7 @@ TEST (node, fork_keep) { system.poll (); ++iterations; - ASSERT_LT (iterations, 200); + ASSERT_LT (iterations, 2000); } rai::transaction transaction (system.nodes [0]->store.environment, nullptr, false); auto winner (node1.ledger.winner (transaction, votes1->votes)); diff --git a/rai/node/node.cpp b/rai/node/node.cpp index f45abdfc..2a323192 100755 --- a/rai/node/node.cpp +++ b/rai/node/node.cpp @@ -1640,7 +1640,7 @@ public: rai::pending_info pending; rai::transaction transaction (node.store.environment, nullptr, false); representative = wallet->store.representative (transaction); - auto error (node.store.pending_get (transaction, block_a.hash (), pending)); + auto error (node.store.pending_get (transaction, rai::pending_key (block_a.hashables.destination, block_a.hash ()), pending)); if (!error) { auto block_l (std::shared_ptr (static_cast (block_a.clone ().release ()))); diff --git a/rai/node/testing.cpp b/rai/node/testing.cpp index eca14132..b70de9ee 100644 --- a/rai/node/testing.cpp +++ b/rai/node/testing.cpp @@ -164,7 +164,7 @@ void rai::system::generate_receive (rai::node & node_a) rai::transaction transaction (node_a.store.environment, nullptr, false); rai::uint256_union random_block; random_pool.GenerateBlock (random_block.bytes.data (), sizeof (random_block.bytes)); - auto i (node_a.store.pending_begin (transaction, random_block)); + auto i (node_a.store.pending_begin (transaction, rai::pending_key (random_block, 0))); if (i != node_a.store.pending_end ()) { rai::block_hash send_hash (i->first); diff --git a/rai/node/wallet.cpp b/rai/node/wallet.cpp index f471eb5f..f9a766be 100644 --- a/rai/node/wallet.cpp +++ b/rai/node/wallet.cpp @@ -934,7 +934,7 @@ std::unique_ptr rai::wallet::receive_action (rai::send_block const if (node.config.receive_minimum.number () <= amount_a.number ()) { rai::transaction transaction (node.ledger.store.environment, nullptr, false); - if (node.ledger.store.pending_exists (transaction, hash)) + if (node.ledger.store.pending_exists (transaction, rai::pending_key (send_a.hashables.destination, hash))) { rai::raw_key prv; if (!store.fetch (transaction, send_a.hashables.destination, prv)) @@ -1238,7 +1238,8 @@ public: { if (wallet->store.valid_password (transaction)) { - auto block_l (wallet->node.store.block_get (transaction, i->first)); + rai::pending_key key (i->first); + auto block_l (wallet->node.store.block_get (transaction, key.hash)); assert (dynamic_cast (block_l.get ()) != nullptr); std::shared_ptr block (static_cast (block_l.release ())); auto wallet_l (wallet); diff --git a/rai/qt/qt.cpp b/rai/qt/qt.cpp index 80931cb9..1d5ecddc 100644 --- a/rai/qt/qt.cpp +++ b/rai/qt/qt.cpp @@ -1579,41 +1579,59 @@ void rai_qt::block_creation::create_receive () if (!error) { rai::transaction transaction (wallet.node.store.environment, nullptr, false); - rai::pending_info pending; - if (!wallet.node.store.pending_get (transaction, source_l, pending)) - { - rai::account_info info; - auto error (wallet.node.store.account_get (transaction, pending.destination, info)); - if (!error) - { - rai::raw_key key; - auto error (wallet.wallet_m->store.fetch (transaction, pending.destination, key)); - if (!error) - { - rai::receive_block receive (info.head, source_l, key, pending.destination, wallet.wallet_m->work_fetch (transaction, pending.destination, info.head)); - std::string block_l; - receive.serialize_json (block_l); - block->setPlainText (QString (block_l.c_str ())); - show_label_ok (*status); - status->setText ("Created block"); - } - else - { + auto block_l (wallet.node.store.block_get (transaction, source_l)); + if (block_l != nullptr) + { + auto send_block (dynamic_cast (block_l.get ())); + if (send_block != nullptr) + { + rai::pending_info pending; + if (!wallet.node.store.pending_get (transaction, rai::pending_key (send_block->hashables.destination, source_l), pending)) + { + rai::account_info info; + auto error (wallet.node.store.account_get (transaction, pending.destination, info)); + if (!error) + { + rai::raw_key key; + auto error (wallet.wallet_m->store.fetch (transaction, pending.destination, key)); + if (!error) + { + rai::receive_block receive (info.head, source_l, key, pending.destination, wallet.wallet_m->work_fetch (transaction, pending.destination, info.head)); + std::string block_l; + receive.serialize_json (block_l); + block->setPlainText (QString (block_l.c_str ())); + show_label_ok (*status); + status->setText ("Created block"); + } + else + { + show_label_error (*status); + status->setText ("Account is not in wallet"); + } + } + else + { + show_label_error (*status); + status->setText ("Account not yet open"); + } + } + else + { show_label_error (*status); - status->setText ("Account is not in wallet"); - } - } - else - { + status->setText ("Source block is not pending to receive"); + } + } + else + { show_label_error (*status); - status->setText ("Account not yet open"); - } - } - else - { + status->setText("Source is not a send block"); + } + } + else + { show_label_error (*status); - status->setText ("Source block is not pending to receive"); - } + status->setText("Source block not found"); + } } else { @@ -1684,41 +1702,59 @@ void rai_qt::block_creation::create_open () if (!error) { rai::transaction transaction (wallet.node.store.environment, nullptr, false); - rai::pending_info pending; - if (!wallet.node.store.pending_get (transaction, source_l, pending)) - { - rai::account_info info; - auto error (wallet.node.store.account_get (transaction, pending.destination, info)); - if (error) - { - rai::raw_key key; - auto error (wallet.wallet_m->store.fetch (transaction, pending.destination, key)); - if (!error) - { - rai::open_block open (source_l, representative_l, pending.destination, key, pending.destination, wallet.wallet_m->work_fetch (transaction, pending.destination, pending.destination)); - std::string block_l; - open.serialize_json (block_l); - block->setPlainText (QString (block_l.c_str ())); - show_label_ok (*status); - status->setText ("Created block"); - } - else - { + auto block_l (wallet.node.store.block_get (transaction, source_l)); + if (block_l != nullptr) + { + auto send_block (dynamic_cast (block_l.get ())); + if (send_block != nullptr) + { + rai::pending_info pending; + if (!wallet.node.store.pending_get (transaction, rai::pending_key (send_block->hashables.destination, source_l), pending)) + { + rai::account_info info; + auto error (wallet.node.store.account_get (transaction, pending.destination, info)); + if (error) + { + rai::raw_key key; + auto error (wallet.wallet_m->store.fetch (transaction, pending.destination, key)); + if (!error) + { + rai::open_block open (source_l, representative_l, pending.destination, key, pending.destination, wallet.wallet_m->work_fetch (transaction, pending.destination, pending.destination)); + std::string block_l; + open.serialize_json (block_l); + block->setPlainText (QString (block_l.c_str ())); + show_label_ok (*status); + status->setText ("Created block"); + } + else + { + show_label_error (*status); + status->setText ("Account is not in wallet"); + } + } + else + { + show_label_error (*status); + status->setText ("Account already open"); + } + } + else + { show_label_error (*status); - status->setText ("Account is not in wallet"); - } - } - else - { + status->setText ("Source block is not pending to receive"); + } + } + else + { show_label_error (*status); - status->setText ("Account already open"); - } - } - else - { + status->setText("Source is not a send block"); + } + } + else + { show_label_error (*status); - status->setText ("Source block is not pending to receive"); - } + status->setText("Source block not found"); + } } else { diff --git a/rai/secure.cpp b/rai/secure.cpp index 729a7289..8d41f14f 100644 --- a/rai/secure.cpp +++ b/rai/secure.cpp @@ -1981,7 +1981,7 @@ void rai::block_store::account_put (MDB_txn * transaction_a, rai::account const assert (status == 0); } -void rai::block_store::pending_put (MDB_txn * transaction_a, rai::block_hash const & hash_a, rai::pending_info const & pending_a) +void rai::block_store::pending_put (MDB_txn * transaction_a, rai::pending_key const & key_a, rai::pending_info const & pending_a) { std::vector vector; { @@ -1990,26 +1990,26 @@ void rai::block_store::pending_put (MDB_txn * transaction_a, rai::block_hash con rai::write (stream, pending_a.amount); rai::write (stream, pending_a.destination); } - auto status (mdb_put (transaction_a, pending, hash_a.val (), pending_a.val (), 0)); + auto status (mdb_put (transaction_a, pending, key_a.val (), pending_a.val (), 0)); assert (status == 0); } -void rai::block_store::pending_del (MDB_txn * transaction_a, rai::block_hash const & hash_a) +void rai::block_store::pending_del (MDB_txn * transaction_a, rai::pending_key const & key_a) { - auto status (mdb_del (transaction_a, pending, hash_a.val (), nullptr)); + auto status (mdb_del (transaction_a, pending, key_a.val (), nullptr)); assert (status == 0); } -bool rai::block_store::pending_exists (MDB_txn * transaction_a, rai::block_hash const & hash_a) +bool rai::block_store::pending_exists (MDB_txn * transaction_a, rai::pending_key const & key_a) { - auto iterator (pending_begin (transaction_a, hash_a)); - return iterator != rai::store_iterator (nullptr) && rai::block_hash (iterator->first) == hash_a; + auto iterator (pending_begin (transaction_a, key_a)); + return iterator != rai::store_iterator (nullptr) && rai::pending_key (iterator->first) == key_a; } -bool rai::block_store::pending_get (MDB_txn * transaction_a, rai::block_hash const & hash_a, rai::pending_info & pending_a) +bool rai::block_store::pending_get (MDB_txn * transaction_a, rai::pending_key const & key_a, rai::pending_info & pending_a) { MDB_val value; - auto status (mdb_get (transaction_a, pending, hash_a.val (), &value)); + auto status (mdb_get (transaction_a, pending, key_a.val (), &value)); assert (status == 0 || status == MDB_NOTFOUND); bool result; if (status == MDB_NOTFOUND) @@ -2031,9 +2031,9 @@ bool rai::block_store::pending_get (MDB_txn * transaction_a, rai::block_hash con return result; } -rai::store_iterator rai::block_store::pending_begin (MDB_txn * transaction_a, rai::block_hash const & hash_a) +rai::store_iterator rai::block_store::pending_begin (MDB_txn * transaction_a, rai::pending_key const & key_a) { - rai::store_iterator result (transaction_a, pending, hash_a.val ()); + rai::store_iterator result (transaction_a, pending, key_a.val ()); return result; } @@ -2101,6 +2101,45 @@ rai::mdb_val rai::pending_info::val () const return rai::mdb_val (sizeof (*this), const_cast (this)); } +rai::pending_key::pending_key (rai::account const & account_a, rai::block_hash const & hash_a) : +account (account_a), +hash (hash_a) +{ +} + +rai::pending_key::pending_key (MDB_val const & val_a) +{ + assert(val_a.mv_size == sizeof (*this)); + static_assert (sizeof (account) + sizeof (hash) == sizeof (*this), "Packed class"); + std::copy (reinterpret_cast (val_a.mv_data), reinterpret_cast (val_a.mv_data) + sizeof (*this), reinterpret_cast (this)); +} + +void rai::pending_key::serialize (rai::stream & stream_a) const +{ + rai::write (stream_a, account.bytes); + rai::write (stream_a, hash.bytes); +} + +bool rai::pending_key::deserialize (rai::stream & stream_a) +{ + auto result (rai::read (stream_a, account.bytes)); + if (!result) + { + result = rai::read (stream_a, hash.bytes); + } + return result; +} + +bool rai::pending_key::operator == (rai::pending_key const & other_a) const +{ + return account == other_a.account && hash == other_a.hash; +} + +rai::mdb_val rai::pending_key::val () const +{ + return rai::mdb_val (sizeof (*this), const_cast (this)); +} + rai::uint128_t rai::block_store::representation_get (MDB_txn * transaction_a, rai::account const & account_a) { MDB_val value; @@ -2529,7 +2568,8 @@ public: { auto hash (block_a.hash ()); rai::pending_info pending; - while (ledger.store.pending_get (transaction, hash, pending) && !error) + rai::pending_key key (block_a.hashables.destination, hash); + while (ledger.store.pending_get (transaction, key, pending) && !error) { error = ledger.rollback (transaction, ledger.latest (transaction, block_a.hashables.destination)); } @@ -2538,7 +2578,7 @@ public: rai::account_info info; auto error (ledger.store.account_get (transaction, pending.source, info)); assert (!error); - ledger.store.pending_del (transaction, hash); + ledger.store.pending_del (transaction, key); ledger.store.representation_add (transaction, ledger.representative (transaction, hash), pending.amount.number ()); ledger.change_latest (transaction, pending.source, block_a.hashables.previous, info.rep_block, ledger.balance (transaction, block_a.hashables.previous)); ledger.store.block_del (transaction, hash); @@ -2563,7 +2603,7 @@ public: ledger.store.representation_add (transaction, ledger.representative (transaction, hash), 0 - amount); ledger.change_latest (transaction, destination_account, block_a.hashables.previous, representative, ledger.balance (transaction, block_a.hashables.previous)); ledger.store.block_del (transaction, hash); - ledger.store.pending_put (transaction, block_a.hashables.source, {ledger.account (transaction, block_a.hashables.source), amount, destination_account}); + ledger.store.pending_put (transaction, rai::pending_key (destination_account, block_a.hashables.source), {ledger.account (transaction, block_a.hashables.source), amount, destination_account}); ledger.store.frontier_del (transaction, hash); ledger.store.frontier_put (transaction, block_a.hashables.previous, destination_account); ledger.store.block_successor_clear (transaction, block_a.hashables.previous); @@ -2584,7 +2624,7 @@ public: ledger.store.representation_add (transaction, ledger.representative (transaction, hash), 0 - amount); ledger.change_latest (transaction, destination_account, 0, representative, 0); ledger.store.block_del (transaction, hash); - ledger.store.pending_put (transaction, block_a.hashables.source, {ledger.account (transaction, block_a.hashables.source), amount, destination_account}); + ledger.store.pending_put (transaction, rai::pending_key (destination_account, block_a.hashables.source), {ledger.account (transaction, block_a.hashables.source), amount, destination_account}); ledger.store.frontier_del (transaction, hash); } else @@ -2977,7 +3017,7 @@ void ledger_processor::send_block (rai::send_block const & block_a) ledger.store.representation_add (transaction, info.rep_block, 0 - amount); ledger.store.block_put (transaction, hash, block_a); ledger.change_latest (transaction, account, hash, info.rep_block, block_a.hashables.balance); - ledger.store.pending_put (transaction, hash, {account, amount, block_a.hashables.destination}); + ledger.store.pending_put (transaction, rai::pending_key (block_a.hashables.destination, hash), {account, amount, block_a.hashables.destination}); ledger.store.frontier_del (transaction, block_a.hashables.previous); ledger.store.frontier_put (transaction, hash, account); result.account = account; @@ -3011,8 +3051,9 @@ void ledger_processor::receive_block (rai::receive_block const & block_a) 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_key key (source->hashables.destination, block_a.hashables.source); 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) + 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) { assert (ledger.store.frontier_get (transaction, block_a.hashables.previous) == pending.destination); @@ -3020,7 +3061,7 @@ void ledger_processor::receive_block (rai::receive_block const & block_a) rai::account_info source_info; auto error (ledger.store.account_get (transaction, pending.source, source_info)); assert (!error); - ledger.store.pending_del (transaction, block_a.hashables.source); + ledger.store.pending_del (transaction, key); ledger.store.block_put (transaction, hash, block_a); ledger.change_latest (transaction, pending.destination, hash, info.rep_block, new_balance); ledger.store.representation_add (transaction, info.rep_block, pending.amount.number ()); @@ -3058,8 +3099,9 @@ void ledger_processor::open_block (rai::open_block const & block_a) result.code = ledger.store.account_get (transaction, block_a.hashables.account, info) ? rai::process_result::progress : rai::process_result::fork; // Has this account already been opened? (Malicious) if (result.code == rai::process_result::progress) { + rai::pending_key key (block_a.hashables.account, block_a.hashables.source); 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) + 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) { result.code = pending.destination == block_a.hashables.account ? rai::process_result::progress : rai::process_result::account_mismatch; // Does the account listed in the open block match the one named in the send block? (Malformed) @@ -3068,7 +3110,7 @@ void ledger_processor::open_block (rai::open_block const & block_a) rai::account_info source_info; auto error (ledger.store.account_get (transaction, pending.source, source_info)); assert (!error); - ledger.store.pending_del (transaction, block_a.hashables.source); + ledger.store.pending_del (transaction, key); ledger.store.block_put (transaction, hash, block_a); ledger.change_latest (transaction, pending.destination, hash, hash, pending.amount.number ()); ledger.store.representation_add (transaction, hash, pending.amount.number ()); diff --git a/rai/secure.hpp b/rai/secure.hpp index ace8ffed..f2b80386 100644 --- a/rai/secure.hpp +++ b/rai/secure.hpp @@ -295,6 +295,18 @@ public: rai::amount amount; rai::account destination; }; +class pending_key +{ +public: + pending_key (rai::account const &, rai::block_hash const &); + pending_key (MDB_val const &); + void serialize (rai::stream &) const; + bool deserialize (rai::stream &); + bool operator == (rai::pending_key const &) const; + rai::mdb_val val () const; + rai::account account; + rai::block_hash hash; +}; class block_store { public: @@ -325,11 +337,11 @@ public: rai::store_iterator latest_begin (MDB_txn *); rai::store_iterator latest_end (); - void pending_put (MDB_txn *, rai::block_hash const &, rai::pending_info const &); - void pending_del (MDB_txn *, rai::block_hash const &); - bool pending_get (MDB_txn *, rai::block_hash const &, rai::pending_info &); - bool pending_exists (MDB_txn *, rai::block_hash const &); - rai::store_iterator pending_begin (MDB_txn *, rai::block_hash const &); + void pending_put (MDB_txn *, rai::pending_key const &, rai::pending_info const &); + void pending_del (MDB_txn *, rai::pending_key const &); + bool pending_get (MDB_txn *, rai::pending_key const &, rai::pending_info &); + bool pending_exists (MDB_txn *, rai::pending_key const &); + rai::store_iterator pending_begin (MDB_txn *, rai::pending_key const &); rai::store_iterator pending_begin (MDB_txn *); rai::store_iterator pending_end (); From a9f7db9d6c516f538dd993c064e20f5a6b5fb7ed Mon Sep 17 00:00:00 2001 From: clemahieu Date: Tue, 7 Feb 2017 09:08:54 -0600 Subject: [PATCH 2/5] Removing destination account from pending value since it's in the key. --- rai/core_test/block_store.cpp | 3 +- rai/core_test/ledger.cpp | 1 - rai/node/wallet.cpp | 8 +++-- rai/qt/qt.cpp | 18 ++++++----- rai/secure.cpp | 61 +++++++++++++---------------------- rai/secure.hpp | 3 +- 6 files changed, 40 insertions(+), 54 deletions(-) diff --git a/rai/core_test/block_store.cpp b/rai/core_test/block_store.cpp index 27168394..f3dae71e 100644 --- a/rai/core_test/block_store.cpp +++ b/rai/core_test/block_store.cpp @@ -126,7 +126,7 @@ TEST (block_store, pending_iterator) ASSERT_TRUE (!init); rai::transaction transaction (store.environment, nullptr, true); ASSERT_EQ (store.pending_end (), store.pending_begin (transaction)); - store.pending_put (transaction, rai::pending_key (1, 2), {2, 3, 4}); + store.pending_put (transaction, rai::pending_key (1, 2), {2, 3}); auto current (store.pending_begin (transaction)); ASSERT_NE (store.pending_end (), current); rai::pending_key key1 (current->first); @@ -135,7 +135,6 @@ TEST (block_store, pending_iterator) rai::pending_info pending (current->second); ASSERT_EQ (rai::account (2), pending.source); ASSERT_EQ (rai::amount (3), pending.amount); - ASSERT_EQ (rai::account (4), pending.destination); } TEST (block_store, genesis) diff --git a/rai/core_test/ledger.cpp b/rai/core_test/ledger.cpp index 66d0d8ed..9c6c27dd 100644 --- a/rai/core_test/ledger.cpp +++ b/rai/core_test/ledger.cpp @@ -150,7 +150,6 @@ TEST (ledger, process_send) rai::pending_info pending1; ASSERT_FALSE (ledger.store.pending_get (transaction, rai::pending_key (key2.pub, hash1), pending1)); ASSERT_EQ (rai::test_genesis_key.pub, pending1.source); - ASSERT_EQ (key2.pub, pending1.destination); ASSERT_EQ (rai::genesis_amount - 50, pending1.amount.number ()); ASSERT_EQ (0, ledger.account_balance (transaction, key2.pub)); ASSERT_EQ (50, ledger.account_balance (transaction, rai::test_genesis_key.pub)); diff --git a/rai/node/wallet.cpp b/rai/node/wallet.cpp index f9a766be..f295d618 100644 --- a/rai/node/wallet.cpp +++ b/rai/node/wallet.cpp @@ -1195,8 +1195,9 @@ public: std::unordered_set already_searched; for (auto i (wallet->node.store.pending_begin (transaction)), n (wallet->node.store.pending_end ()); i != n; ++i) { + rai::pending_key key (i->first); rai::pending_info pending (i->second); - auto existing (keys.find (pending.destination)); + auto existing (keys.find (key.account)); if (existing != keys.end ()) { rai::account_info info; @@ -1231,10 +1232,11 @@ public: auto representative (wallet->store.representative (transaction)); for (auto i (wallet->node.store.pending_begin (transaction)), n (wallet->node.store.pending_end ()); i != n; ++i) { + rai::pending_key key (i->first); rai::pending_info pending (i->second); if (pending.source == account_a) { - if (wallet->store.exists (transaction, pending.destination)) + if (wallet->store.exists (transaction, key.account)) { if (wallet->store.valid_password (transaction)) { @@ -1255,7 +1257,7 @@ public: } else { - BOOST_LOG (wallet->node.log) << boost::str (boost::format ("Unable to fetch key for: %1%, stopping pending search") % pending.destination.to_account ()); + BOOST_LOG (wallet->node.log) << boost::str (boost::format ("Unable to fetch key for: %1%, stopping pending search") % key.account.to_account ()); } } } diff --git a/rai/qt/qt.cpp b/rai/qt/qt.cpp index 1d5ecddc..c327263b 100644 --- a/rai/qt/qt.cpp +++ b/rai/qt/qt.cpp @@ -1585,18 +1585,19 @@ void rai_qt::block_creation::create_receive () auto send_block (dynamic_cast (block_l.get ())); if (send_block != nullptr) { + rai::pending_key pending_key (send_block->hashables.destination, source_l); rai::pending_info pending; - if (!wallet.node.store.pending_get (transaction, rai::pending_key (send_block->hashables.destination, source_l), pending)) + if (!wallet.node.store.pending_get (transaction, pending_key, pending)) { rai::account_info info; - auto error (wallet.node.store.account_get (transaction, pending.destination, info)); + auto error (wallet.node.store.account_get (transaction, pending_key.account, info)); if (!error) { rai::raw_key key; - auto error (wallet.wallet_m->store.fetch (transaction, pending.destination, key)); + auto error (wallet.wallet_m->store.fetch (transaction, pending_key.account, key)); if (!error) { - rai::receive_block receive (info.head, source_l, key, pending.destination, wallet.wallet_m->work_fetch (transaction, pending.destination, info.head)); + rai::receive_block receive (info.head, source_l, key, pending_key.account, wallet.wallet_m->work_fetch (transaction, pending_key.account, info.head)); std::string block_l; receive.serialize_json (block_l); block->setPlainText (QString (block_l.c_str ())); @@ -1708,18 +1709,19 @@ void rai_qt::block_creation::create_open () auto send_block (dynamic_cast (block_l.get ())); if (send_block != nullptr) { + rai::pending_key pending_key (send_block->hashables.destination, source_l); rai::pending_info pending; - if (!wallet.node.store.pending_get (transaction, rai::pending_key (send_block->hashables.destination, source_l), pending)) + if (!wallet.node.store.pending_get (transaction, pending_key, pending)) { rai::account_info info; - auto error (wallet.node.store.account_get (transaction, pending.destination, info)); + auto error (wallet.node.store.account_get (transaction, pending_key.account, info)); if (error) { rai::raw_key key; - auto error (wallet.wallet_m->store.fetch (transaction, pending.destination, key)); + auto error (wallet.wallet_m->store.fetch (transaction, pending_key.account, key)); if (!error) { - rai::open_block open (source_l, representative_l, pending.destination, key, pending.destination, wallet.wallet_m->work_fetch (transaction, pending.destination, pending.destination)); + rai::open_block open (source_l, representative_l, pending_key.account, key, pending_key.account, wallet.wallet_m->work_fetch (transaction, pending_key.account, pending_key.account)); std::string block_l; open.serialize_json (block_l); block->setPlainText (QString (block_l.c_str ())); diff --git a/rai/secure.cpp b/rai/secure.cpp index 8d41f14f..fe82fe31 100644 --- a/rai/secure.cpp +++ b/rai/secure.cpp @@ -1988,7 +1988,6 @@ void rai::block_store::pending_put (MDB_txn * transaction_a, rai::pending_key co rai::vectorstream stream (vector); rai::write (stream, pending_a.source); rai::write (stream, pending_a.amount); - rai::write (stream, pending_a.destination); } auto status (mdb_put (transaction_a, pending, key_a.val (), pending_a.val (), 0)); assert (status == 0); @@ -2019,14 +2018,12 @@ bool rai::block_store::pending_get (MDB_txn * transaction_a, rai::pending_key co else { result = false; - assert (value.mv_size == sizeof (pending_a.source.bytes) + sizeof (pending_a.amount.bytes) + sizeof (pending_a.destination.bytes)); + assert (value.mv_size == sizeof (pending_a.source.bytes) + sizeof (pending_a.amount.bytes)); rai::bufferstream stream (reinterpret_cast (value.mv_data), value.mv_size); auto error1 (rai::read (stream, pending_a.source)); assert (!error1); auto error2 (rai::read (stream, pending_a.amount)); assert (!error2); - auto error3 (rai::read (stream, pending_a.destination)); - assert (!error3); } return result; } @@ -2051,22 +2048,20 @@ rai::store_iterator rai::block_store::pending_end () rai::pending_info::pending_info () : source (0), -amount (0), -destination (0) +amount (0) { } rai::pending_info::pending_info (MDB_val const & val_a) { assert(val_a.mv_size == sizeof (*this)); - static_assert (sizeof (source) + sizeof (amount) + sizeof (destination) == sizeof (*this), "Packed class"); + static_assert (sizeof (source) + sizeof (amount) == sizeof (*this), "Packed class"); std::copy (reinterpret_cast (val_a.mv_data), reinterpret_cast (val_a.mv_data) + sizeof (*this), reinterpret_cast (this)); } -rai::pending_info::pending_info (rai::account const & source_a, rai::amount const & amount_a, rai::account const & destination_a) : +rai::pending_info::pending_info (rai::account const & source_a, rai::amount const & amount_a) : source (source_a), -amount (amount_a), -destination (destination_a) +amount (amount_a) { } @@ -2074,7 +2069,6 @@ void rai::pending_info::serialize (rai::stream & stream_a) const { rai::write (stream_a, source.bytes); rai::write (stream_a, amount.bytes); - rai::write (stream_a, destination.bytes); } bool rai::pending_info::deserialize (rai::stream & stream_a) @@ -2083,17 +2077,13 @@ bool rai::pending_info::deserialize (rai::stream & stream_a) if (!result) { result = rai::read (stream_a, amount.bytes); - if (!result) - { - result = rai::read (stream_a, destination.bytes); - } } return result; } bool rai::pending_info::operator == (rai::pending_info const & other_a) const { - return source == other_a.source && amount == other_a.amount && destination == other_a.destination; + return source == other_a.source && amount == other_a.amount; } rai::mdb_val rai::pending_info::val () const @@ -2603,7 +2593,7 @@ public: ledger.store.representation_add (transaction, ledger.representative (transaction, hash), 0 - amount); ledger.change_latest (transaction, destination_account, block_a.hashables.previous, representative, ledger.balance (transaction, block_a.hashables.previous)); ledger.store.block_del (transaction, hash); - ledger.store.pending_put (transaction, rai::pending_key (destination_account, block_a.hashables.source), {ledger.account (transaction, block_a.hashables.source), amount, destination_account}); + ledger.store.pending_put (transaction, rai::pending_key (destination_account, block_a.hashables.source), {ledger.account (transaction, block_a.hashables.source), amount}); ledger.store.frontier_del (transaction, hash); ledger.store.frontier_put (transaction, block_a.hashables.previous, destination_account); ledger.store.block_successor_clear (transaction, block_a.hashables.previous); @@ -2624,7 +2614,7 @@ public: ledger.store.representation_add (transaction, ledger.representative (transaction, hash), 0 - amount); ledger.change_latest (transaction, destination_account, 0, representative, 0); ledger.store.block_del (transaction, hash); - ledger.store.pending_put (transaction, rai::pending_key (destination_account, block_a.hashables.source), {ledger.account (transaction, block_a.hashables.source), amount, destination_account}); + ledger.store.pending_put (transaction, rai::pending_key (destination_account, block_a.hashables.source), {ledger.account (transaction, block_a.hashables.source), amount}); ledger.store.frontier_del (transaction, hash); } else @@ -3017,7 +3007,7 @@ void ledger_processor::send_block (rai::send_block const & block_a) ledger.store.representation_add (transaction, info.rep_block, 0 - amount); ledger.store.block_put (transaction, hash, block_a); ledger.change_latest (transaction, account, hash, info.rep_block, block_a.hashables.balance); - ledger.store.pending_put (transaction, rai::pending_key (block_a.hashables.destination, hash), {account, amount, block_a.hashables.destination}); + ledger.store.pending_put (transaction, rai::pending_key (block_a.hashables.destination, hash), {account, amount}); ledger.store.frontier_del (transaction, block_a.hashables.previous); ledger.store.frontier_put (transaction, hash, account); result.account = account; @@ -3051,23 +3041,22 @@ void ledger_processor::receive_block (rai::receive_block const & block_a) 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_key key (source->hashables.destination, block_a.hashables.source); + rai::pending_key key (account, block_a.hashables.source); rai::pending_info pending; 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) { - 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; 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, pending.destination, hash, info.rep_block, new_balance); + ledger.change_latest (transaction, account, hash, info.rep_block, new_balance); ledger.store.representation_add (transaction, info.rep_block, pending.amount.number ()); ledger.store.frontier_del (transaction, block_a.hashables.previous); - ledger.store.frontier_put (transaction, hash, pending.destination); - result.account = pending.destination; + ledger.store.frontier_put (transaction, hash, account); + result.account = account; result.amount = pending.amount; } } @@ -3104,20 +3093,16 @@ 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) { - result.code = pending.destination == block_a.hashables.account ? rai::process_result::progress : rai::process_result::account_mismatch; // Does the account listed in the open block match the one named in the send block? (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, pending.destination, hash, hash, pending.amount.number ()); - ledger.store.representation_add (transaction, hash, pending.amount.number ()); - ledger.store.frontier_put (transaction, hash, pending.destination); - result.account = pending.destination; - result.amount = pending.amount; - } + 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 ()); + 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 f2b80386..6d3e610d 100644 --- a/rai/secure.hpp +++ b/rai/secure.hpp @@ -286,14 +286,13 @@ class pending_info public: pending_info (); pending_info (MDB_val const &); - pending_info (rai::account const &, rai::amount const &, rai::account const &); + pending_info (rai::account const &, rai::amount const &); void serialize (rai::stream &) const; bool deserialize (rai::stream &); bool operator == (rai::pending_info const &) const; rai::mdb_val val () const; rai::account source; rai::amount amount; - rai::account destination; }; class pending_key { From 361b50bc004e646457e58c68288eb8dad54b117e Mon Sep 17 00:00:00 2001 From: clemahieu Date: Tue, 7 Feb 2017 10:56:42 -0600 Subject: [PATCH 3/5] Adding block_store v3 to v4 upgrade function to update pending table. --- rai/core_test/block_store.cpp | 31 ++++++++++++++++++++- rai/secure.cpp | 26 ++++++++++++++++-- rai/secure.hpp | 1 + rai/versioning.cpp | 52 +++++++++++++++++++++++++++++++++++ rai/versioning.hpp | 16 ++++++++++- 5 files changed, 121 insertions(+), 5 deletions(-) diff --git a/rai/core_test/block_store.cpp b/rai/core_test/block_store.cpp index f3dae71e..806e0297 100644 --- a/rai/core_test/block_store.cpp +++ b/rai/core_test/block_store.cpp @@ -1,5 +1,6 @@ #include #include +#include #include @@ -593,7 +594,6 @@ TEST (block_store, sequence_increment) ASSERT_EQ (31, seq8); } - TEST (block_store, upgrade_v2_v3) { rai::keypair key1; @@ -637,3 +637,32 @@ TEST (block_store, upgrade_v2_v3) ASSERT_FALSE (store.account_get (transaction, rai::test_genesis_key.pub, info)); ASSERT_EQ (change_hash, info.rep_block); } + +TEST (block_store, upgrade_v3_v4) +{ + rai::keypair key1; + rai::keypair key2; + rai::keypair key3; + auto path (rai::unique_path ()); + { + bool init (false); + rai::block_store store (init, path); + ASSERT_FALSE (init); + rai::transaction transaction (store.environment, nullptr, true); + store.version_put (transaction, 3); + rai::pending_info_v3 info (key1.pub, 100, key2.pub); + auto status (mdb_put (transaction, store.pending, key3.pub.val (), info.val (), 0)); + ASSERT_EQ (0, status); + } + bool init (false); + rai::block_store store (init, path); + rai::ledger ledger (store); + rai::transaction transaction (store.environment, nullptr, true); + ASSERT_FALSE (init); + rai::pending_key key (key2.pub, key3.pub); + rai::pending_info info; + auto error (store.pending_get (transaction, key, info)); + ASSERT_FALSE (error); + ASSERT_EQ (key1.pub, info.source); + ASSERT_EQ (rai::amount (100), info.amount); +} diff --git a/rai/secure.cpp b/rai/secure.cpp index fe82fe31..b7773606 100644 --- a/rai/secure.cpp +++ b/rai/secure.cpp @@ -9,6 +9,8 @@ #include +#include + // Genesis keys for network variants namespace { @@ -1562,12 +1564,12 @@ void rai::block_store::do_upgrades (MDB_txn * transaction_a) { case 1: upgrade_v1_to_v2 (transaction_a); - break; case 2: upgrade_v2_to_v3 (transaction_a); - break; case 3: - break; + upgrade_v3_to_v4 (transaction_a); + case 4: + break; default: assert (false); } @@ -1666,6 +1668,24 @@ void rai::block_store::upgrade_v2_to_v3 (MDB_txn * transaction_a) } } +void rai::block_store::upgrade_v3_to_v4 (MDB_txn * transaction_a) +{ + version_put (transaction_a, 4); + std::queue > items; + for (auto i (pending_begin (transaction_a)), n (pending_end ()); i != n; ++i) + { + rai::block_hash hash (i->first); + rai::pending_info_v3 info (i->second); + items.push (std::make_pair (rai::pending_key (info.destination, hash), rai::pending_info (info.source, info.amount))); + } + mdb_drop (transaction_a, pending, 0); + while (!items.empty ()) + { + pending_put (transaction_a, items.front ().first, items.front ().second); + items.pop (); + } +} + void rai::block_store::clear (MDB_dbi db_a) { rai::transaction transaction (environment, nullptr, true); diff --git a/rai/secure.hpp b/rai/secure.hpp index 6d3e610d..5648e343 100644 --- a/rai/secure.hpp +++ b/rai/secure.hpp @@ -380,6 +380,7 @@ public: void do_upgrades (MDB_txn *); void upgrade_v1_to_v2 (MDB_txn *); void upgrade_v2_to_v3 (MDB_txn *); + void upgrade_v3_to_v4 (MDB_txn *); void clear (MDB_dbi); diff --git a/rai/versioning.cpp b/rai/versioning.cpp index b13804d7..f748c12f 100644 --- a/rai/versioning.cpp +++ b/rai/versioning.cpp @@ -53,3 +53,55 @@ rai::mdb_val rai::account_info_v1::val () const { return rai::mdb_val (sizeof (*this), const_cast (this)); } + +rai::pending_info_v3::pending_info_v3 () : +source (0), +amount (0), +destination (0) +{ +} + +rai::pending_info_v3::pending_info_v3 (MDB_val const & val_a) +{ + assert(val_a.mv_size == sizeof (*this)); + static_assert (sizeof (source) + sizeof (amount) + sizeof (destination) == sizeof (*this), "Packed class"); + std::copy (reinterpret_cast (val_a.mv_data), reinterpret_cast (val_a.mv_data) + sizeof (*this), reinterpret_cast (this)); +} + +rai::pending_info_v3::pending_info_v3 (rai::account const & source_a, rai::amount const & amount_a, rai::account const & destination_a) : +source (source_a), +amount (amount_a), +destination (destination_a) +{ +} + +void rai::pending_info_v3::serialize (rai::stream & stream_a) const +{ + rai::write (stream_a, source.bytes); + rai::write (stream_a, amount.bytes); + rai::write (stream_a, destination.bytes); +} + +bool rai::pending_info_v3::deserialize (rai::stream & stream_a) +{ + auto result (rai::read (stream_a, source.bytes)); + if (!result) + { + result = rai::read (stream_a, amount.bytes); + if (!result) + { + result = rai::read (stream_a, destination.bytes); + } + } + return result; +} + +bool rai::pending_info_v3::operator == (rai::pending_info_v3 const & other_a) const +{ + return source == other_a.source && amount == other_a.amount && destination == other_a.destination; +} + +rai::mdb_val rai::pending_info_v3::val () const +{ + return rai::mdb_val (sizeof (*this), const_cast (this)); +} diff --git a/rai/versioning.hpp b/rai/versioning.hpp index 1676afce..63f748d0 100644 --- a/rai/versioning.hpp +++ b/rai/versioning.hpp @@ -19,4 +19,18 @@ public: rai::amount balance; uint64_t modified; }; -} \ No newline at end of file +class pending_info_v3 +{ +public: + pending_info_v3 (); + pending_info_v3 (MDB_val const &); + pending_info_v3 (rai::account const &, rai::amount const &, rai::account const &); + void serialize (rai::stream &) const; + bool deserialize (rai::stream &); + bool operator == (rai::pending_info_v3 const &) const; + rai::mdb_val val () const; + rai::account source; + rai::amount amount; + rai::account destination; +}; +} From 1b308d82343ac65ccc315be26c1da8876e660faf Mon Sep 17 00:00:00 2001 From: clemahieu Date: Tue, 7 Feb 2017 13:18:25 -0600 Subject: [PATCH 4/5] Adding pending to account_balance rpc. --- rai/core_test/block_store.cpp | 3 ++- rai/core_test/ledger.cpp | 6 ++++++ rai/core_test/rpc.cpp | 4 +++- rai/node/node.cpp | 9 +++++++++ rai/node/node.hpp | 1 + rai/node/rpc.cpp | 5 +++-- rai/secure.cpp | 12 ++++++++++++ rai/secure.hpp | 1 + 8 files changed, 37 insertions(+), 4 deletions(-) diff --git a/rai/core_test/block_store.cpp b/rai/core_test/block_store.cpp index 806e0297..8b548b8a 100644 --- a/rai/core_test/block_store.cpp +++ b/rai/core_test/block_store.cpp @@ -630,7 +630,7 @@ TEST (block_store, upgrade_v2_v3) rai::ledger ledger (store); rai::transaction transaction (store.environment, nullptr, true); ASSERT_TRUE (!init); - ASSERT_EQ (3, store.version_get (transaction)); + ASSERT_LT (2, store.version_get (transaction)); ASSERT_EQ (rai::genesis_amount, ledger.weight (transaction, key1.pub)); ASSERT_EQ (0, ledger.weight (transaction, key2.pub)); rai::account_info info; @@ -659,6 +659,7 @@ TEST (block_store, upgrade_v3_v4) rai::ledger ledger (store); rai::transaction transaction (store.environment, nullptr, true); ASSERT_FALSE (init); + ASSERT_LT (3, store.version_get (transaction)); rai::pending_key key (key2.pub, key3.pub); rai::pending_info info; auto error (store.pending_get (transaction, key, info)); diff --git a/rai/core_test/ledger.cpp b/rai/core_test/ledger.cpp index 9c6c27dd..3f811ee7 100644 --- a/rai/core_test/ledger.cpp +++ b/rai/core_test/ledger.cpp @@ -109,6 +109,7 @@ TEST (ledger, process_send) ASSERT_EQ (rai::test_genesis_key.pub, return1.account); ASSERT_EQ (rai::genesis_amount - 50, return1.amount.number ()); ASSERT_EQ (50, ledger.account_balance (transaction, rai::test_genesis_key.pub)); + ASSERT_EQ (rai::genesis_amount - 50, ledger.account_pending (transaction, key2.pub)); rai::account_info info2; ASSERT_FALSE (store.account_get (transaction, rai::test_genesis_key.pub, info2)); auto latest6 (store.block_get (transaction, info2.head)); @@ -127,6 +128,7 @@ TEST (ledger, process_send) ASSERT_EQ (rai::genesis_amount - 50, return2.amount.number ()); ASSERT_EQ (key2.pub, store.frontier_get (transaction, hash2)); ASSERT_EQ (rai::genesis_amount - 50, ledger.account_balance (transaction, key2.pub)); + ASSERT_EQ (0, ledger.account_pending (transaction, key2.pub)); ASSERT_EQ (50, ledger.weight (transaction, rai::test_genesis_key.pub)); ASSERT_EQ (rai::genesis_amount - 50, ledger.weight (transaction, key2.pub)); rai::account_info info3; @@ -152,6 +154,7 @@ TEST (ledger, process_send) ASSERT_EQ (rai::test_genesis_key.pub, pending1.source); ASSERT_EQ (rai::genesis_amount - 50, pending1.amount.number ()); ASSERT_EQ (0, ledger.account_balance (transaction, key2.pub)); + ASSERT_EQ (rai::genesis_amount - 50, ledger.account_pending (transaction, key2.pub)); ASSERT_EQ (50, ledger.account_balance (transaction, rai::test_genesis_key.pub)); ASSERT_EQ (50, ledger.weight (transaction, rai::test_genesis_key.pub)); ASSERT_EQ (0, ledger.weight (transaction, key2.pub)); @@ -168,6 +171,7 @@ TEST (ledger, process_send) rai::pending_info pending2; ASSERT_TRUE (ledger.store.pending_get (transaction, rai::pending_key (key2.pub, hash1), pending2)); ASSERT_EQ (rai::genesis_amount, ledger.account_balance (transaction, rai::test_genesis_key.pub)); + ASSERT_EQ (0, ledger.account_pending (transaction, key2.pub)); } TEST (ledger, process_receive) @@ -208,6 +212,7 @@ TEST (ledger, process_receive) ASSERT_EQ (25, return2.amount.number ()); ASSERT_EQ (hash4, ledger.latest (transaction, key2.pub)); ASSERT_EQ (25, ledger.account_balance (transaction, rai::test_genesis_key.pub)); + ASSERT_EQ (0, ledger.account_pending (transaction, key2.pub)); ASSERT_EQ (rai::genesis_amount - 25, ledger.account_balance (transaction, key2.pub)); ASSERT_EQ (rai::genesis_amount - 25, ledger.weight (transaction, key3.pub)); ledger.rollback (transaction, hash4); @@ -215,6 +220,7 @@ TEST (ledger, process_receive) ASSERT_EQ (key2.pub, store.frontier_get (transaction, hash2)); ASSERT_TRUE (store.frontier_get (transaction, hash4).is_zero ()); ASSERT_EQ (25, ledger.account_balance (transaction, rai::test_genesis_key.pub)); + ASSERT_EQ (25, ledger.account_pending (transaction, key2.pub)); ASSERT_EQ (rai::genesis_amount - 50, ledger.account_balance (transaction, key2.pub)); ASSERT_EQ (rai::genesis_amount - 50, ledger.weight (transaction, key3.pub)); ASSERT_EQ (hash2, ledger.latest (transaction, key2.pub)); diff --git a/rai/core_test/rpc.cpp b/rai/core_test/rpc.cpp index df401f7d..eaafc45a 100644 --- a/rai/core_test/rpc.cpp +++ b/rai/core_test/rpc.cpp @@ -79,6 +79,8 @@ TEST (rpc, account_balance) ASSERT_EQ (200, response.status); std::string balance_text (response.json.get ("balance")); ASSERT_EQ ("340282366920938463463374607431768211455", balance_text); + std::string pending_text (response.json.get ("pending")); + ASSERT_EQ ("0", pending_text); } TEST (rpc, account_create) @@ -1273,7 +1275,7 @@ TEST (rpc, version) ASSERT_EQ (200, response1.status); ASSERT_EQ ("1", response1.json.get ("rpc_version")); ASSERT_EQ (200, response1.status); - ASSERT_EQ ("2", response1.json.get ("store_version")); + ASSERT_EQ ("4", response1.json.get ("store_version")); ASSERT_EQ (boost::str (boost::format ("RaiBlocks %1%.%2%.%3%") % RAIBLOCKS_VERSION_MAJOR % RAIBLOCKS_VERSION_MINOR % RAIBLOCKS_VERSION_PATCH), response1.json.get ("node_vendor")); auto & headers (response1.headers); auto access_control (std::find_if (headers.begin (), headers.end (), [] (decltype (*headers.begin ()) & header_a) { return boost::iequals (header_a.first, "Access-Control-Allow-Origin"); })); diff --git a/rai/node/node.cpp b/rai/node/node.cpp index 2a323192..7207755e 100755 --- a/rai/node/node.cpp +++ b/rai/node/node.cpp @@ -1360,6 +1360,15 @@ rai::uint128_t rai::node::balance (rai::account const & account_a) return ledger.account_balance (transaction, account_a); } +std::pair rai::node::balance_pending (rai::account const & account_a) +{ + std::pair result; + rai::transaction transaction (store.environment, nullptr, false); + result.first = ledger.account_balance (transaction, account_a); + result.second = ledger.account_pending (transaction, account_a); + return result; +} + rai::uint128_t rai::node::weight (rai::account const & account_a) { rai::transaction transaction (store.environment, nullptr, false); diff --git a/rai/node/node.hpp b/rai/node/node.hpp index 2d84fc3b..4cbf140c 100644 --- a/rai/node/node.hpp +++ b/rai/node/node.hpp @@ -354,6 +354,7 @@ public: void keepalive_preconfigured (std::vector const &); rai::block_hash latest (rai::account const &); rai::uint128_t balance (rai::account const &); + std::pair balance_pending (rai::account const &); rai::uint128_t weight (rai::account const &); rai::account representative (rai::account const &); void ongoing_keepalive (); diff --git a/rai/node/rpc.cpp b/rai/node/rpc.cpp index 502568e7..83121629 100644 --- a/rai/node/rpc.cpp +++ b/rai/node/rpc.cpp @@ -141,9 +141,10 @@ void rai::rpc_handler::account_balance () auto error (account.decode_account (account_text)); if (!error) { - auto balance (rpc.node.balance (account)); + auto balance (rpc.node.balance_pending (account)); boost::property_tree::ptree response_l; - response_l.put ("balance", balance.convert_to ()); + response_l.put ("balance", balance.first.convert_to ()); + response_l.put ("pending", balance.second.convert_to ()); rpc.send_response (response, response_l); } else diff --git a/rai/secure.cpp b/rai/secure.cpp index b7773606..fc36cc55 100644 --- a/rai/secure.cpp +++ b/rai/secure.cpp @@ -2725,6 +2725,18 @@ rai::uint128_t rai::ledger::account_balance (MDB_txn * transaction_a, rai::accou return result; } +rai::uint128_t rai::ledger::account_pending (MDB_txn * transaction_a, rai::account const & account_a) +{ + rai::uint128_t result (0); + rai::account end (account_a.number () + 1); + for (auto i (store.pending_begin (transaction_a, rai::pending_key (account_a, 0))), n (store.pending_begin (transaction_a, rai::pending_key (end, 0))); i != n; ++i) + { + rai::pending_info info (i->second); + result += info.amount.number (); + } + return result; +} + rai::process_return rai::ledger::process (MDB_txn * transaction_a, rai::block const & block_a) { ledger_processor processor (*this, transaction_a); diff --git a/rai/secure.hpp b/rai/secure.hpp index 5648e343..1ed7b7a9 100644 --- a/rai/secure.hpp +++ b/rai/secure.hpp @@ -469,6 +469,7 @@ public: rai::uint128_t amount (MDB_txn *, rai::block_hash const &); rai::uint128_t balance (MDB_txn *, rai::block_hash const &); rai::uint128_t account_balance (MDB_txn *, rai::account const &); + rai::uint128_t account_pending (MDB_txn *, rai::account const &); rai::uint128_t weight (MDB_txn *, rai::account const &); std::unique_ptr successor (MDB_txn *, rai::block_hash const &); std::unique_ptr forked_block (MDB_txn *, rai::block const &); From 7cde941f2ec61b05d9711fe65dc6205e76330b05 Mon Sep 17 00:00:00 2001 From: clemahieu Date: Tue, 7 Feb 2017 14:04:18 -0600 Subject: [PATCH 5/5] Add pending RPC to query for blocks that can be received by an account. --- rai/core_test/rpc.cpp | 28 ++++++++++++++++++++++++++-- rai/node/rpc.cpp | 37 +++++++++++++++++++++++++++++++++++++ rai/node/rpc.hpp | 1 + 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/rai/core_test/rpc.cpp b/rai/core_test/rpc.cpp index eaafc45a..543f00d8 100644 --- a/rai/core_test/rpc.cpp +++ b/rai/core_test/rpc.cpp @@ -1200,8 +1200,32 @@ TEST (rpc, peers) system.poll (); } ASSERT_EQ (200, response.status); - auto & frontiers_node (response.json.get_child ("peers")); - ASSERT_EQ (1, frontiers_node.size ()); + auto & peers_node (response.json.get_child ("peers")); + ASSERT_EQ (1, peers_node.size ()); +} + +TEST (rpc, pending) +{ + rai::system system (24000, 1); + rai::keypair key1; + system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv); + auto block1 (system.wallet (0)->send_action (rai::test_genesis_key.pub, key1.pub, 100)); + rai::rpc rpc (system.service, *system.nodes [0], rai::rpc_config (true)); + rpc.start (); + boost::property_tree::ptree request; + request.put ("action", "pending"); + request.put ("account", key1.pub.to_account ()); + request.put ("count", "100"); + test_response response (request, rpc, system.service); + while (response.status == 0) + { + system.poll (); + } + ASSERT_EQ (200, response.status); + auto & blocks_node (response.json.get_child ("blocks")); + ASSERT_EQ (1, blocks_node.size ()); + rai::block_hash hash1 (blocks_node.begin ()->second.get ("")); + ASSERT_EQ (block1->hash (), hash1); } TEST (rpc_config, serialization) diff --git a/rai/node/rpc.cpp b/rai/node/rpc.cpp index 83121629..7470bcf7 100644 --- a/rai/node/rpc.cpp +++ b/rai/node/rpc.cpp @@ -847,6 +847,39 @@ void rai::rpc_handler::peers () rpc.send_response (response, response_l); } +void rai::rpc_handler::pending () +{ + std::string account_text (request.get ("account")); + rai::account account; + if (!account.decode_account(account_text)) + { + std::string count_text (request.get ("count")); + uint64_t count; + if (!rpc.decode_unsigned (count_text, count)) + { + boost::property_tree::ptree response_l; + boost::property_tree::ptree peers_l; + { + rai::transaction transaction (rpc.node.store.environment, nullptr, false); + rai::account end (account.number () + 1); + for (auto i (rpc.node.store.pending_begin (transaction, rai::pending_key (account, 0))), n (rpc.node.store.pending_begin (transaction, rai::pending_key (end, 0))); i != n && peers_l.size ()< count; ++i) + { + rai::pending_key key (i->first); + boost::property_tree::ptree entry; + entry.put ("", key.hash.to_string ()); + peers_l.push_back (std::make_pair ("", entry)); + } + } + response_l.add_child ("blocks", peers_l); + rpc.send_response (response, response_l); + } + } + else + { + rpc.error_response (response, "Bad account number"); + } +} + void rai::rpc_handler::payment_begin () { std::string id_text (request.get ("wallet")); @@ -1753,6 +1786,10 @@ void rai::rpc_handler::process_request () { peers (); } + else if (action == "pending") + { + pending (); + } else if (action == "process") { process (); diff --git a/rai/node/rpc.hpp b/rai/node/rpc.hpp index 77030499..0b430462 100644 --- a/rai/node/rpc.hpp +++ b/rai/node/rpc.hpp @@ -109,6 +109,7 @@ public: void payment_end (); void payment_wait (); void peers (); + void pending (); void process (); void rai_to_raw (); void rai_from_raw ();