diff --git a/rai/core_test/conflicts.cpp b/rai/core_test/conflicts.cpp index 9731ff41..3eb4c516 100644 --- a/rai/core_test/conflicts.cpp +++ b/rai/core_test/conflicts.cpp @@ -11,10 +11,13 @@ TEST (conflicts, start_stop) ASSERT_EQ (rai::process_result::progress, node1.process (send1).code); ASSERT_EQ (0, node1.active.roots.size ()); auto node_l (system.nodes [0]); - node1.active.start (send1, [node_l] (rai::block & block_a) { - node_l->process_confirmed (block_a); - }); + rai::transaction transaction (node1.store.environment, nullptr, true); + node1.active.start (transaction, send1, [node_l] (rai::block & block_a) + { + node_l->process_confirmed (block_a); + }); + } ASSERT_EQ (1, node1.active.roots.size ()); auto root1 (send1.root ()); auto existing1 (node1.active.roots.find (root1)); @@ -33,16 +36,22 @@ TEST (conflicts, add_existing) rai::send_block send1 (genesis.hash (), key1.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0); ASSERT_EQ (rai::process_result::progress, node1.process (send1).code); auto node_l (system.nodes [0]); - node1.active.start (send1, [node_l] (rai::block & block_a) { - node_l->process_confirmed (block_a); - }); + rai::transaction transaction (node1.store.environment, nullptr, true); + node1.active.start (transaction, send1, [node_l] (rai::block & block_a) + { + node_l->process_confirmed (block_a); + }); + } rai::keypair key2; rai::send_block send2 (genesis.hash (), key2.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0); - node1.active.start (send2, [node_l] (rai::block & block_a) { - node_l->process_confirmed (block_a); - }); + rai::transaction transaction (node1.store.environment, nullptr, true); + node1.active.start (transaction, send2, [node_l] (rai::block & block_a) + { + node_l->process_confirmed (block_a); + }); + } ASSERT_EQ (1, node1.active.roots.size ()); rai::vote vote1 (key2.pub, key2.prv, 0, send2.clone ()); node1.active.vote (vote1); @@ -62,16 +71,22 @@ TEST (conflicts, add_two) rai::send_block send1 (genesis.hash (), key1.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0); ASSERT_EQ (rai::process_result::progress, node1.process (send1).code); auto node_l (system.nodes [0]); - node1.active.start (send1, [node_l] (rai::block & block_a) { - node_l->process_confirmed (block_a); - }); + rai::transaction transaction (node1.store.environment, nullptr, true); + node1.active.start (transaction, send1, [node_l] (rai::block & block_a) + { + node_l->process_confirmed (block_a); + }); + } rai::keypair key2; rai::send_block send2 (send1.hash (), key2.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0); ASSERT_EQ (rai::process_result::progress, node1.process (send2).code); - node1.active.start (send2, [node_l] (rai::block & block_a) { - node_l->process_confirmed (block_a); - }); + rai::transaction transaction (node1.store.environment, nullptr, true); + node1.active.start (transaction, send2, [node_l] (rai::block & block_a) + { + node_l->process_confirmed (block_a); + }); + } ASSERT_EQ (2, node1.active.roots.size ()); -} \ No newline at end of file +} diff --git a/rai/core_test/ledger.cpp b/rai/core_test/ledger.cpp index 5dd94b70..d968faa3 100644 --- a/rai/core_test/ledger.cpp +++ b/rai/core_test/ledger.cpp @@ -719,10 +719,13 @@ TEST (votes, add_unsigned) ASSERT_EQ (rai::process_result::progress, node1.ledger.process (transaction, send1).code); } auto node_l (system.nodes [0]); - node1.active.start (send1, [node_l] (rai::block & block_a) { - node_l->process_confirmed (block_a); - }); + rai::transaction transaction (node1.store.environment, nullptr, true); + node1.active.start (transaction, send1, [node_l] (rai::block & block_a) + { + node_l->process_confirmed (block_a); + }); + } auto votes1 (node1.active.roots.find (send1.root ())->election); ASSERT_NE (nullptr, votes1); ASSERT_EQ (1, votes1->votes.rep_votes.size ()); @@ -744,10 +747,13 @@ TEST (votes, add_one) ASSERT_EQ (rai::process_result::progress, node1.ledger.process (transaction, send1).code); } auto node_l (system.nodes [0]); - node1.active.start (send1, [node_l] (rai::block & block_a) { - node_l->process_confirmed (block_a); - }); + rai::transaction transaction (node1.store.environment, nullptr, true); + node1.active.start (transaction, send1, [node_l] (rai::block & block_a) + { + node_l->process_confirmed (block_a); + }); + } auto votes1 (node1.active.roots.find (send1.root ())->election); ASSERT_EQ (1, votes1->votes.rep_votes.size ()); rai::vote vote1 (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 1, send1.clone ()); @@ -774,10 +780,13 @@ TEST (votes, add_two) ASSERT_EQ (rai::process_result::progress, node1.ledger.process (transaction, send1).code); } auto node_l (system.nodes [0]); - node1.active.start (send1, [node_l] (rai::block & block_a) { - node_l->process_confirmed (block_a); - }); + rai::transaction transaction (node1.store.environment, nullptr, true); + node1.active.start (transaction, send1, [node_l] (rai::block & block_a) + { + node_l->process_confirmed (block_a); + }); + } auto votes1 (node1.active.roots.find (send1.root ())->election); rai::vote vote1 (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 1, send1.clone ()); votes1->vote (vote1); @@ -808,10 +817,13 @@ TEST (votes, add_existing) ASSERT_EQ (rai::process_result::progress, node1.ledger.process (transaction, send1).code); } auto node_l (system.nodes [0]); - node1.active.start (send1, [node_l] (rai::block & block_a) { - node_l->process_confirmed (block_a); - }); + rai::transaction transaction (node1.store.environment, nullptr, true); + node1.active.start (transaction, send1, [node_l] (rai::block & block_a) + { + node_l->process_confirmed (block_a); + }); + } auto votes1 (node1.active.roots.find (send1.root ())->election); rai::vote vote1 (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 1, send1.clone ()); votes1->vote (vote1); @@ -840,10 +852,13 @@ TEST (votes, add_old) ASSERT_EQ (rai::process_result::progress, node1.ledger.process (transaction, send1).code); } auto node_l (system.nodes [0]); - node1.active.start (send1, [node_l] (rai::block & block_a) { - node_l->process_confirmed (block_a); - }); + rai::transaction transaction (node1.store.environment, nullptr, true); + node1.active.start (transaction, send1, [node_l] (rai::block & block_a) + { + node_l->process_confirmed (block_a); + }); + } auto votes1 (node1.active.roots.find (send1.root ())->election); rai::vote vote1 (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 2, send1.clone ()); votes1->vote (vote1); diff --git a/rai/core_test/network.cpp b/rai/core_test/network.cpp index 62a7ea06..56b06473 100644 --- a/rai/core_test/network.cpp +++ b/rai/core_test/network.cpp @@ -262,10 +262,13 @@ TEST (receivable_processor, confirm_insufficient_pos) rai::send_block block1 (genesis.hash (), 0, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0); ASSERT_EQ (rai::process_result::progress, node1.process (block1).code); auto node_l (system.nodes [0]); - node1.active.start (block1, [node_l] (rai::block & block_a) { - node_l->process_confirmed (block_a); - }); + rai::transaction transaction (node1.store.environment, nullptr, true); + node1.active.start (transaction, block1, [node_l] (rai::block & block_a) + { + node_l->process_confirmed (block_a); + }); + } rai::keypair key1; rai::confirm_ack con1 (key1.pub, key1.prv, 0, block1.clone ()); node1.process_message (con1, node1.network.endpoint ()); @@ -279,10 +282,13 @@ TEST (receivable_processor, confirm_sufficient_pos) rai::send_block block1 (genesis.hash (), 0, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0); ASSERT_EQ (rai::process_result::progress, node1.process (block1).code); auto node_l (system.nodes [0]); - node1.active.start (block1, [node_l] (rai::block & block_a) { - node_l->process_confirmed (block_a); - }); + rai::transaction transaction (node1.store.environment, nullptr, true); + node1.active.start (transaction, block1, [node_l] (rai::block & block_a) + { + node_l->process_confirmed (block_a); + }); + } rai::confirm_ack con1 (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 0, block1.clone ()); node1.process_message (con1, node1.network.endpoint ()); } diff --git a/rai/core_test/node.cpp b/rai/core_test/node.cpp index e9c17d8c..58ca6283 100644 --- a/rai/core_test/node.cpp +++ b/rai/core_test/node.cpp @@ -688,14 +688,6 @@ TEST (node, fork_publish) ASSERT_NE (node1.active.roots.end (), conflict1); auto votes1 (conflict1->election); ASSERT_NE (nullptr, votes1); - ASSERT_EQ (1, votes1->votes.rep_votes.size ()); - auto iterations1 (0); - while (votes1->votes.rep_votes.size () == 1) - { - system.poll (); - ++iterations1; - ASSERT_LT (iterations1, 200); - } ASSERT_EQ (2, votes1->votes.rep_votes.size ()); auto existing1 (votes1->votes.rep_votes.find (rai::test_genesis_key.pub)); ASSERT_NE (votes1->votes.rep_votes.end (), existing1); @@ -1111,6 +1103,9 @@ TEST (node, broadcast_elected) rai::keypair rep_big; rai::keypair rep_small; rai::keypair rep_other; + //std::cerr << "Big: " << rep_big.pub.to_account () << std::endl; + //std::cerr << "Small: " << rep_small.pub.to_account () << std::endl; + //std::cerr << "Other: " << rep_other.pub.to_account () << std::endl; rai::block_hash fork_hash; { rai::transaction transaction0 (node0->store.environment, nullptr, true); @@ -1157,6 +1152,8 @@ TEST (node, broadcast_elected) node0->generate_work (fork1); system.wallet (2)->insert_adhoc (rep_small.prv); node2->process_receive_republish (fork1.clone (), 0); + //std::cerr << "fork0: " << fork_hash.to_string () << std::endl; + //std::cerr << "fork1: " << fork1.hash ().to_string () << std::endl; while (!node2->ledger.block_exists (fork_hash)) { system.poll (); @@ -1164,3 +1161,35 @@ TEST (node, broadcast_elected) ASSERT_TRUE (node1->ledger.block_exists(fork_hash)); } } + +TEST (node, rep_self_vote) +{ + rai::system system (24000, 1); + auto node0 (system.nodes [0]); + rai::keypair rep_big; + { + rai::transaction transaction0 (node0->store.environment, nullptr, true); + rai::send_block fund_big (node0->ledger.latest (transaction0, rai::test_genesis_key.pub), rep_big.pub, rai::uint128_t ("0xb0000000000000000000000000000000"), rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0); + rai::open_block open_big (fund_big.hash (), rep_big.pub, rep_big.pub, rep_big.prv, rep_big.pub, 0); + node0->generate_work (fund_big); + node0->generate_work (open_big); + ASSERT_EQ (rai::process_result::progress, node0->ledger.process (transaction0, fund_big).code); + ASSERT_EQ (rai::process_result::progress, node0->ledger.process (transaction0, open_big).code); + } + system.wallet (0)->insert_adhoc (rep_big.prv); + system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv); + rai::send_block block0 (node0->latest (rai::test_genesis_key.pub), rep_big.pub, rai::uint128_t ("0x60000000000000000000000000000000"), rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0); + node0->generate_work (block0); + ASSERT_EQ (rai::process_result::progress, node0->process (block0).code); + auto & active (node0->active); + { + rai::transaction transaction (node0->store.environment, nullptr, true); + active.start (transaction, block0, [] (rai::block &) {}); + } + auto existing (active.roots.find (block0.root ())); + ASSERT_NE (active.roots.end (), existing); + auto & rep_votes (existing->election->votes.rep_votes); + ASSERT_EQ (3, rep_votes.size ()); + ASSERT_NE (rep_votes.end (), rep_votes.find (rai::test_genesis_key.pub)); + ASSERT_NE (rep_votes.end (), rep_votes.find (rep_big.pub)); +} diff --git a/rai/node/node.cpp b/rai/node/node.cpp index f5f7191b..5f55f873 100644 --- a/rai/node/node.cpp +++ b/rai/node/node.cpp @@ -562,7 +562,8 @@ public: BOOST_LOG (node.log) << boost::str (boost::format ("Starting fast confirmation of block: %1%") % block_a.hash ().to_string ()); } auto node_l (node.shared ()); - node.active.start (block_a, [node_l] (rai::block & block_a) + rai::transaction transaction (node.store.environment, nullptr, true); + node.active.start (transaction, block_a, [node_l] (rai::block & block_a) { node_l->process_confirmed (block_a); }); @@ -1277,7 +1278,7 @@ rai::process_return rai::node::process_receive_one (rai::transaction & transacti std::unique_ptr root; root = ledger.successor (transaction_a, block_a.root ()); auto node_l (shared_from_this ()); - active.start (*root, [node_l] (rai::block & block_a) + active.start (transaction_a, *root, [node_l] (rai::block & block_a) { node_l->process_confirmed (block_a); }); @@ -2073,51 +2074,32 @@ std::shared_ptr rai::node::shared () return shared_from_this (); } -rai::election::election (rai::node & node_a, rai::block const & block_a, std::function const & confirmation_action_a) : +rai::election::election (MDB_txn * transaction_a, rai::node & node_a, rai::block const & block_a, std::function const & confirmation_action_a) : confirmation_action (confirmation_action_a), votes (block_a), node (node_a), last_vote (std::chrono::system_clock::now ()), last_winner (block_a.clone ()) { + assert (node_a.store.block_exists (transaction_a, block_a.hash ())); confirmed.clear (); + compute_rep_votes (transaction_a); } -void rai::election::recompute_winner () +void rai::election::compute_rep_votes (MDB_txn * transaction_a) { - auto last_winner_l (last_winner); - for (auto i (node.wallets.items.begin ()), n (node.wallets.items.end ()); i != n; ++i) + node.wallets.foreach_representative (transaction_a, [this, transaction_a] (rai::public_key const & pub_a, rai::raw_key const & prv_a) { - auto is_representative (false); - rai::vote vote_l; - { - rai::transaction transaction (node.store.environment, nullptr, true); - is_representative = i->second->store.is_representative (transaction); - if (is_representative) - { - auto representative (i->second->store.representative (transaction)); - rai::raw_key prv; - is_representative = !i->second->store.fetch (transaction, representative, prv); - if (is_representative) - { - vote_l = rai::vote (representative, prv, node.store.sequence_atomic_inc (transaction, representative), last_winner_l->clone ()); - } - else - { - BOOST_LOG (node.log) << boost::str (boost::format ("Unable to vote on block due to locked wallet %1%") % i->first.to_string ()); - } - } - } - if (is_representative) - { - vote (vote_l); - } - } + votes.vote (transaction_a, node.store, rai::vote (pub_a, prv_a, node.store.sequence_atomic_inc (transaction_a, pub_a), last_winner->clone ())); + }); } void rai::election::broadcast_winner () { - recompute_winner (); + { + rai::transaction transaction (node.store.environment, nullptr, true); + compute_rep_votes (transaction); + } auto list (node.peers.list ()); node.network.confirm_broadcast (list, last_winner->clone (), 0); } @@ -2254,14 +2236,14 @@ void rai::active_transactions::announce_votes () node.alarm.add ((rai::rai_network == rai::rai_networks::rai_test_network) ? now + std::chrono::milliseconds (10) : now + std::chrono::seconds (16), [node_l] () {node_l->active.announce_votes ();}); } -void rai::active_transactions::start (rai::block const & block_a, std::function const & confirmation_action_a) +void rai::active_transactions::start (MDB_txn * transaction_a, rai::block const & block_a, std::function const & confirmation_action_a) { std::lock_guard lock (mutex); auto root (block_a.root ()); auto existing (roots.find (root)); if (existing == roots.end ()) { - auto election (std::make_shared (node, block_a, confirmation_action_a)); + auto election (std::make_shared (transaction_a, node, block_a, confirmation_action_a)); roots.insert (rai::conflict_info {root, election, 0}); } } diff --git a/rai/node/node.hpp b/rai/node/node.hpp index 7de0c35b..98b4838e 100644 --- a/rai/node/node.hpp +++ b/rai/node/node.hpp @@ -39,14 +39,14 @@ class election : public std::enable_shared_from_this std::function confirmation_action; void confirm_once (); public: - election (rai::node &, rai::block const &, std::function const &); + election (MDB_txn *, rai::node &, rai::block const &, std::function const &); void vote (rai::vote const &); // Set last_winner based on our current state of the ledger bool recalculate_winner (MDB_txn *); // Tell the network our view of the winner void broadcast_winner (); // Change our winner to agree with the network - void recompute_winner (); + void compute_rep_votes (MDB_txn *); // Confirmation method 1, uncontested quarum void confirm_if_quarum (MDB_txn *); // Confirmation method 2, settling time @@ -74,7 +74,7 @@ public: active_transactions (rai::node &); // Start an election for a block // Call action with confirmed block, may be different than what we started with - void start (rai::block const &, std::function const &); + void start (MDB_txn *, rai::block const &, std::function const &); void vote (rai::vote const &); bool active (rai::block const &); void announce_votes (); diff --git a/rai/node/wallet.cpp b/rai/node/wallet.cpp index b0e1b4f0..d7409f51 100644 --- a/rai/node/wallet.cpp +++ b/rai/node/wallet.cpp @@ -1199,7 +1199,8 @@ public: std::shared_ptr block_l (wallet->node.store.block_get (transaction, info.head).release ()); wallet->node.background ([this_l, account, block_l] { - this_l->wallet->node.active.start (*block_l, [this_l, account] (rai::block &) + rai::transaction transaction (this_l->wallet->node.store.environment, nullptr, true); + this_l->wallet->node.active.start (transaction, *block_l, [this_l, account] (rai::block &) { // If there were any forks for this account they've been rolled back and we can receive anything remaining from this account this_l->receive_all (account); @@ -1436,7 +1437,7 @@ void rai::wallets::queue_wallet_action (rai::account const & account_a, rai::uin } } -void rai::wallets::foreach_representative (rai::transaction const & transaction_a, std::function const & action_a) +void rai::wallets::foreach_representative (MDB_txn * transaction_a, std::function const & action_a) { for (auto i (items.begin ()), n (items.end ()); i != n; ++i) { diff --git a/rai/node/wallet.hpp b/rai/node/wallet.hpp index 96fe6bd6..e4ea94c8 100644 --- a/rai/node/wallet.hpp +++ b/rai/node/wallet.hpp @@ -187,7 +187,7 @@ public: void destroy (rai::uint256_union const &); void do_wallet_actions (rai::account const &); void queue_wallet_action (rai::account const &, rai::uint128_t const &, std::function const &); - void foreach_representative (rai::transaction const &, std::function const &); + void foreach_representative (MDB_txn *, std::function const &); std::function observer; std::unordered_map > items; std::unordered_map , std::greater >> pending_actions;