Merge branch 'pending_accounts'
This commit is contained in:
commit
34eb45df1f
15 changed files with 451 additions and 161 deletions
|
@ -1,5 +1,6 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <rai/node/node.hpp>
|
||||
#include <rai/versioning.hpp>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
|
@ -107,16 +108,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,14 +127,15 @@ 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});
|
||||
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);
|
||||
ASSERT_EQ (rai::account (4), pending.destination);
|
||||
}
|
||||
|
||||
TEST (block_store, genesis)
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -592,7 +594,6 @@ TEST (block_store, sequence_increment)
|
|||
ASSERT_EQ (31, seq8);
|
||||
}
|
||||
|
||||
|
||||
TEST (block_store, upgrade_v2_v3)
|
||||
{
|
||||
rai::keypair key1;
|
||||
|
@ -629,10 +630,40 @@ 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;
|
||||
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);
|
||||
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));
|
||||
ASSERT_FALSE (error);
|
||||
ASSERT_EQ (key1.pub, info.source);
|
||||
ASSERT_EQ (rai::amount (100), info.amount);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -148,11 +150,11 @@ 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 ());
|
||||
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));
|
||||
|
@ -167,8 +169,9 @@ 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));
|
||||
ASSERT_EQ (0, ledger.account_pending (transaction, key2.pub));
|
||||
}
|
||||
|
||||
TEST (ledger, process_receive)
|
||||
|
@ -209,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);
|
||||
|
@ -216,11 +220,12 @@ 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));
|
||||
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 +264,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 +1122,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)
|
||||
|
|
|
@ -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 <rai::send_block> 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));
|
||||
|
|
|
@ -79,6 +79,8 @@ TEST (rpc, account_balance)
|
|||
ASSERT_EQ (200, response.status);
|
||||
std::string balance_text (response.json.get <std::string> ("balance"));
|
||||
ASSERT_EQ ("340282366920938463463374607431768211455", balance_text);
|
||||
std::string pending_text (response.json.get <std::string> ("pending"));
|
||||
ASSERT_EQ ("0", pending_text);
|
||||
}
|
||||
|
||||
TEST (rpc, account_create)
|
||||
|
@ -1198,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 <std::string> (""));
|
||||
ASSERT_EQ (block1->hash (), hash1);
|
||||
}
|
||||
|
||||
TEST (rpc_config, serialization)
|
||||
|
@ -1273,7 +1299,7 @@ TEST (rpc, version)
|
|||
ASSERT_EQ (200, response1.status);
|
||||
ASSERT_EQ ("1", response1.json.get <std::string> ("rpc_version"));
|
||||
ASSERT_EQ (200, response1.status);
|
||||
ASSERT_EQ ("2", response1.json.get <std::string> ("store_version"));
|
||||
ASSERT_EQ ("4", response1.json.get <std::string> ("store_version"));
|
||||
ASSERT_EQ (boost::str (boost::format ("RaiBlocks %1%.%2%.%3%") % RAIBLOCKS_VERSION_MAJOR % RAIBLOCKS_VERSION_MINOR % RAIBLOCKS_VERSION_PATCH), response1.json.get <std::string> ("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"); }));
|
||||
|
|
|
@ -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::uint128_t, rai::uint128_t> rai::node::balance_pending (rai::account const & account_a)
|
||||
{
|
||||
std::pair <rai::uint128_t, rai::uint128_t> 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);
|
||||
|
@ -1640,7 +1649,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 <rai::send_block> (static_cast <rai::send_block *> (block_a.clone ().release ())));
|
||||
|
|
|
@ -354,6 +354,7 @@ public:
|
|||
void keepalive_preconfigured (std::vector <std::string> const &);
|
||||
rai::block_hash latest (rai::account const &);
|
||||
rai::uint128_t balance (rai::account const &);
|
||||
std::pair <rai::uint128_t, rai::uint128_t> balance_pending (rai::account const &);
|
||||
rai::uint128_t weight (rai::account const &);
|
||||
rai::account representative (rai::account const &);
|
||||
void ongoing_keepalive ();
|
||||
|
|
|
@ -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 <std::string> ());
|
||||
response_l.put ("balance", balance.first.convert_to <std::string> ());
|
||||
response_l.put ("pending", balance.second.convert_to <std::string> ());
|
||||
rpc.send_response (response, response_l);
|
||||
}
|
||||
else
|
||||
|
@ -846,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 <std::string> ("account"));
|
||||
rai::account account;
|
||||
if (!account.decode_account(account_text))
|
||||
{
|
||||
std::string count_text (request.get <std::string> ("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 <std::string> ("wallet"));
|
||||
|
@ -1752,6 +1786,10 @@ void rai::rpc_handler::process_request ()
|
|||
{
|
||||
peers ();
|
||||
}
|
||||
else if (action == "pending")
|
||||
{
|
||||
pending ();
|
||||
}
|
||||
else if (action == "process")
|
||||
{
|
||||
process ();
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -934,7 +934,7 @@ std::unique_ptr <rai::block> 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))
|
||||
|
@ -1195,8 +1195,9 @@ public:
|
|||
std::unordered_set <rai::account> 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,14 +1232,16 @@ 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))
|
||||
{
|
||||
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 <rai::send_block *> (block_l.get ()) != nullptr);
|
||||
std::shared_ptr <rai::send_block> block (static_cast <rai::send_block *> (block_l.release ()));
|
||||
auto wallet_l (wallet);
|
||||
|
@ -1254,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 ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
166
rai/qt/qt.cpp
166
rai/qt/qt.cpp
|
@ -1579,41 +1579,60 @@ 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 <rai::send_block *> (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, pending_key, pending))
|
||||
{
|
||||
rai::account_info 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_key.account, key));
|
||||
if (!error)
|
||||
{
|
||||
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 ()));
|
||||
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 +1703,60 @@ 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 <rai::send_block *> (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, pending_key, pending))
|
||||
{
|
||||
rai::account_info 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_key.account, key));
|
||||
if (!error)
|
||||
{
|
||||
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 ()));
|
||||
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
|
||||
{
|
||||
|
|
171
rai/secure.cpp
171
rai/secure.cpp
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include <ed25519-donna/ed25519.h>
|
||||
|
||||
#include <queue>
|
||||
|
||||
// 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 <std::pair <rai::pending_key, rai::pending_info>> 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);
|
||||
|
@ -1981,35 +2001,34 @@ 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 <uint8_t> vector;
|
||||
{
|
||||
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, 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)
|
||||
|
@ -2019,21 +2038,19 @@ bool rai::block_store::pending_get (MDB_txn * transaction_a, rai::block_hash con
|
|||
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 <uint8_t const *> (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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2051,22 +2068,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 <uint8_t const *> (val_a.mv_data), reinterpret_cast <uint8_t const *> (val_a.mv_data) + sizeof (*this), reinterpret_cast <uint8_t *> (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 +2089,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 +2097,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
|
||||
|
@ -2101,6 +2111,45 @@ rai::mdb_val rai::pending_info::val () const
|
|||
return rai::mdb_val (sizeof (*this), const_cast <rai::pending_info *> (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 <uint8_t const *> (val_a.mv_data), reinterpret_cast <uint8_t const *> (val_a.mv_data) + sizeof (*this), reinterpret_cast <uint8_t *> (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 <rai::pending_key *> (this));
|
||||
}
|
||||
|
||||
rai::uint128_t rai::block_store::representation_get (MDB_txn * transaction_a, rai::account const & account_a)
|
||||
{
|
||||
MDB_val value;
|
||||
|
@ -2529,7 +2578,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 +2588,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 +2613,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});
|
||||
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 +2634,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});
|
||||
ledger.store.frontier_del (transaction, hash);
|
||||
}
|
||||
else
|
||||
|
@ -2675,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);
|
||||
|
@ -2977,7 +3039,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});
|
||||
ledger.store.frontier_del (transaction, block_a.hashables.previous);
|
||||
ledger.store.frontier_put (transaction, hash, account);
|
||||
result.account = account;
|
||||
|
@ -3011,22 +3073,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 (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)
|
||||
{
|
||||
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, 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.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;
|
||||
}
|
||||
}
|
||||
|
@ -3058,24 +3120,21 @@ 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)
|
||||
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, block_a.hashables.source);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -286,14 +286,25 @@ 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
|
||||
{
|
||||
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
|
||||
{
|
||||
|
@ -325,11 +336,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 ();
|
||||
|
||||
|
@ -369,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);
|
||||
|
||||
|
@ -457,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 <rai::block> successor (MDB_txn *, rai::block_hash const &);
|
||||
std::unique_ptr <rai::block> forked_block (MDB_txn *, rai::block const &);
|
||||
|
|
|
@ -53,3 +53,55 @@ rai::mdb_val rai::account_info_v1::val () const
|
|||
{
|
||||
return rai::mdb_val (sizeof (*this), const_cast <rai::account_info_v1 *> (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 <uint8_t const *> (val_a.mv_data), reinterpret_cast <uint8_t const *> (val_a.mv_data) + sizeof (*this), reinterpret_cast <uint8_t *> (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 <rai::pending_info_v3 *> (this));
|
||||
}
|
||||
|
|
|
@ -19,4 +19,18 @@ public:
|
|||
rai::amount balance;
|
||||
uint64_t modified;
|
||||
};
|
||||
}
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue