Merge branch 'pulls/200'

This commit is contained in:
clemahieu 2017-11-02 16:24:01 -05:00
commit a0d0f68a4e
4 changed files with 263 additions and 9 deletions

View file

@ -921,8 +921,52 @@ TEST (block_store, upgrade_v8_v9)
rai::block_store store (init, path);
ASSERT_FALSE (init);
rai::transaction transaction (store.environment, nullptr, false);
ASSERT_EQ (9, store.version_get (transaction));
ASSERT_LT (8, store.version_get (transaction));
auto vote (store.vote_get (transaction, key.pub));
ASSERT_NE (nullptr, vote);
ASSERT_EQ (10, vote->sequence);
}
TEST (block_store, upgrade_v9_v10)
{
auto path (rai::unique_path ());
rai::block_hash hash (0);
{
bool init (false);
rai::block_store store (init, path);
ASSERT_FALSE (init);
rai::transaction transaction (store.environment, nullptr, true);
rai::genesis genesis;;
genesis.initialize (transaction, store);
rai::ledger ledger (store);
store.version_put (transaction, 9);
rai::account_info info;
store.account_get (transaction, rai::test_genesis_key.pub, info);
rai::keypair key0;
rai::uint128_t balance (rai::genesis_amount);
hash = info.head;
for (auto i (1); i < 32; ++i) // Making 31 send blocks (+ 1 open = 32 total)
{
balance = balance - rai::Gxrb_ratio;
rai::send_block block0 (hash, key0.pub, balance, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
ASSERT_EQ (rai::process_result::progress, ledger.process (transaction, block0).code);
hash = block0.hash ();
}
rai::block_info block_info_auto; // Checking automatic block_info creation for block 32
store.block_info_get (transaction, hash, block_info_auto);
ASSERT_EQ (block_info_auto.account, rai::test_genesis_key.pub);
ASSERT_EQ (block_info_auto.balance.number (), balance);
ASSERT_EQ (0, mdb_drop (transaction, store.blocks_info, 0)); // Cleaning blocks_info subdatabase
bool block_info_exists (store.block_info_exists (transaction, hash));
ASSERT_EQ (block_info_exists, 0); // Checking if automatic block_info is deleted
}
bool init (false);
rai::block_store store (init, path);
ASSERT_FALSE (init);
rai::transaction transaction (store.environment, nullptr, false);
ASSERT_LT (9, store.version_get (transaction));
rai::block_info block_info;
store.block_info_get (transaction, hash, block_info);
ASSERT_EQ (block_info.account, rai::test_genesis_key.pub);
ASSERT_EQ (block_info.balance.number (), rai::genesis_amount - rai::Gxrb_ratio * 31);
}

View file

@ -1359,7 +1359,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 ("9", response1.json.get <std::string> ("store_version"));
ASSERT_EQ ("10", response1.json.get <std::string> ("store_version"));
ASSERT_EQ (boost::str (boost::format ("RaiBlocks %1%.%2%") % RAIBLOCKS_VERSION_MAJOR % RAIBLOCKS_VERSION_MINOR), response1.json.get <std::string> ("node_vendor"));
auto headers (response1.resp.find ("Access-Control-Allow-Origin"));
ASSERT_NE (response1.resp.end (), headers);

View file

@ -1515,6 +1515,7 @@ receive_blocks (0),
open_blocks (0),
change_blocks (0),
pending (0),
blocks_info (0),
representation (0),
unchecked (0),
unsynced (0),
@ -1530,6 +1531,7 @@ checksum (0)
error_a |= mdb_dbi_open (transaction, "open", MDB_CREATE, &open_blocks) != 0;
error_a |= mdb_dbi_open (transaction, "change", MDB_CREATE, &change_blocks) != 0;
error_a |= mdb_dbi_open (transaction, "pending", MDB_CREATE, &pending) != 0;
error_a |= mdb_dbi_open (transaction, "blocks_info", MDB_CREATE, &blocks_info) != 0;
error_a |= mdb_dbi_open (transaction, "representation", MDB_CREATE, &representation) != 0;
error_a |= mdb_dbi_open (transaction, "unchecked", MDB_CREATE | MDB_DUPSORT, &unchecked) != 0;
error_a |= mdb_dbi_open (transaction, "unsynced", MDB_CREATE, &unsynced) != 0;
@ -1592,6 +1594,8 @@ void rai::block_store::do_upgrades (MDB_txn * transaction_a)
case 8:
upgrade_v8_to_v9 (transaction_a);
case 9:
upgrade_v9_to_v10 (transaction_a);
case 10:
break;
default:
assert (false);
@ -1801,6 +1805,31 @@ void rai::block_store::upgrade_v8_to_v9 (MDB_txn * transaction_a)
mdb_drop (transaction_a, sequence, 1);
}
void rai::block_store::upgrade_v9_to_v10 (MDB_txn * transaction_a)
{
version_put (transaction_a, 10);
for (auto i (latest_begin (transaction_a)), n (latest_end ()); i != n; ++i)
{
rai::account account (i->first);
rai::account_info info (i->second);
size_t block_count (1);
auto hash (info.open_block);
while (!hash.is_zero ())
{
if ((block_count % block_info_max) == 0)
{
rai::block_info block_info;
block_info.account = account;
rai::amount balance (block_balance (transaction_a, hash));
block_info.balance = balance;
block_info_put (transaction_a, hash, block_info);
}
hash = block_successor (transaction_a, hash);
++block_count;
}
}
}
void rai::block_store::clear (MDB_dbi db_a)
{
rai::transaction transaction (environment, nullptr, true);
@ -2304,6 +2333,110 @@ rai::mdb_val rai::pending_key::val () const
return rai::mdb_val (sizeof (*this), const_cast <rai::pending_key *> (this));
}
void rai::block_store::block_info_put (MDB_txn * transaction_a, rai::block_hash const & hash_a, rai::block_info const & block_info_a)
{
auto status (mdb_put (transaction_a, blocks_info, hash_a.val (), block_info_a.val (), 0));
assert (status == 0);
}
void rai::block_store::block_info_del (MDB_txn * transaction_a, rai::block_hash const & hash_a)
{
auto status (mdb_del (transaction_a, blocks_info, hash_a.val (), nullptr));
assert (status == 0);
}
bool rai::block_store::block_info_exists (MDB_txn * transaction_a, rai::block_hash const & hash_a)
{
auto iterator (block_info_begin (transaction_a, hash_a));
return iterator != rai::store_iterator (nullptr) && rai::block_hash (iterator->first) == hash_a;
}
bool rai::block_store::block_info_get (MDB_txn * transaction_a, rai::block_hash const & hash_a, rai::block_info & block_info_a)
{
MDB_val value;
auto status (mdb_get (transaction_a, blocks_info, hash_a.val (), &value));
assert (status == 0 || status == MDB_NOTFOUND);
bool result;
if (status == MDB_NOTFOUND)
{
result = true;
}
else
{
result = false;
assert (value.mv_size == sizeof (block_info_a.account.bytes) + sizeof (block_info_a.balance.bytes));
rai::bufferstream stream (reinterpret_cast <uint8_t const *> (value.mv_data), value.mv_size);
auto error1 (rai::read (stream, block_info_a.account));
assert (!error1);
auto error2 (rai::read (stream, block_info_a.balance));
assert (!error2);
}
return result;
}
rai::store_iterator rai::block_store::block_info_begin (MDB_txn * transaction_a, rai::block_hash const & hash_a)
{
rai::store_iterator result (transaction_a, blocks_info, hash_a.val ());
return result;
}
rai::store_iterator rai::block_store::block_info_begin (MDB_txn * transaction_a)
{
rai::store_iterator result (transaction_a, blocks_info);
return result;
}
rai::store_iterator rai::block_store::block_info_end ()
{
rai::store_iterator result (nullptr);
return result;
}
rai::block_info::block_info () :
account (0),
balance (0)
{
}
rai::block_info::block_info (MDB_val const & val_a)
{
assert(val_a.mv_size == sizeof (*this));
static_assert (sizeof (account) + sizeof (balance) == 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::block_info::block_info (rai::account const & account_a, rai::amount const & balance_a) :
account (account_a),
balance (balance_a)
{
}
void rai::block_info::serialize (rai::stream & stream_a) const
{
rai::write (stream_a, account.bytes);
rai::write (stream_a, balance.bytes);
}
bool rai::block_info::deserialize (rai::stream & stream_a)
{
auto result (rai::read (stream_a, account.bytes));
if (!result)
{
result = rai::read (stream_a, balance.bytes);
}
return result;
}
bool rai::block_info::operator == (rai::block_info const & other_a) const
{
return account == other_a.account && balance == other_a.balance;
}
rai::mdb_val rai::block_info::val () const
{
return rai::mdb_val (sizeof (*this), const_cast <rai::block_info *> (this));
}
rai::uint128_t rai::block_store::representation_get (MDB_txn * transaction_a, rai::account const & account_a)
{
MDB_val value;
@ -2808,10 +2941,18 @@ void balance_visitor::send_block (rai::send_block const & block_a)
void balance_visitor::receive_block (rai::receive_block const & block_a)
{
amount_visitor source (transaction, store);
source.compute (block_a.hashables.source);
result += source.result;
current = block_a.hashables.previous;
amount_visitor source (transaction, store);
source.compute (block_a.hashables.source);
rai::block_info block_info;
if (!store.block_info_get (transaction, block_a.hash (), block_info))
{
result += block_info.balance.number ();
current = 0;
}
else {
result += source.result;
current = block_a.hashables.previous;
}
}
void balance_visitor::open_block (rai::open_block const & block_a)
@ -2824,7 +2965,15 @@ void balance_visitor::open_block (rai::open_block const & block_a)
void balance_visitor::change_block (rai::change_block const & block_a)
{
current = block_a.hashables.previous;
rai::block_info block_info;
if (!store.block_info_get (transaction, block_a.hash (), block_info))
{
result += block_info.balance.number ();
current = 0;
}
else {
current = block_a.hashables.previous;
}
}
// Rollback this block
@ -2855,6 +3004,10 @@ public:
ledger.store.frontier_del (transaction, hash);
ledger.store.frontier_put (transaction, block_a.hashables.previous, pending.source);
ledger.store.block_successor_clear (transaction, block_a.hashables.previous);
if (!(info.block_count % ledger.store.block_info_max))
{
ledger.store.block_info_del (transaction, hash);
}
}
void receive_block (rai::receive_block const & block_a) override
{
@ -2872,6 +3025,10 @@ public:
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);
if (!(info.block_count % ledger.store.block_info_max))
{
ledger.store.block_info_del (transaction, hash);
}
}
void open_block (rai::open_block const & block_a) override
{
@ -2901,6 +3058,10 @@ public:
ledger.store.frontier_del (transaction, hash);
ledger.store.frontier_put (transaction, block_a.hashables.previous, account);
ledger.store.block_successor_clear (transaction, block_a.hashables.previous);
if (!(info.block_count % ledger.store.block_info_max))
{
ledger.store.block_info_del (transaction, hash);
}
}
MDB_txn * transaction;
rai::ledger & ledger;
@ -2947,6 +3108,13 @@ rai::uint128_t rai::ledger::balance (MDB_txn * transaction_a, rai::block_hash co
return visitor.result;
}
rai::uint128_t rai::block_store::block_balance (MDB_txn * transaction_a, rai::block_hash const & hash_a)
{
balance_visitor visitor (transaction_a, *this);
visitor.compute (hash_a);
return visitor.result;
}
// Balance for an account by account number
rai::uint128_t rai::ledger::account_balance (MDB_txn * transaction_a, rai::account const & account_a)
{
@ -3054,7 +3222,8 @@ rai::account rai::ledger::account (MDB_txn * transaction_a, rai::block_hash cons
assert (store.block_exists (transaction_a, hash_a));
auto hash (hash_a);
rai::block_hash successor (1);
while (!successor.is_zero ())
rai::block_info block_info;
while (!successor.is_zero () && store.block_info_get (transaction_a, successor, block_info))
{
successor = store.block_successor (transaction_a, hash);
if (!successor.is_zero ())
@ -3062,7 +3231,15 @@ rai::account rai::ledger::account (MDB_txn * transaction_a, rai::block_hash cons
hash = successor;
}
}
auto result (store.frontier_get (transaction_a, hash));
rai::account result;
if (successor.is_zero ())
{
result = store.frontier_get (transaction_a, hash);
}
else
{
result = block_info.account;
}
assert (!result.is_zero ());
return result;
}
@ -3161,6 +3338,13 @@ void rai::ledger::change_latest (MDB_txn * transaction_a, rai::account const & a
info.modified = store.now ();
info.block_count = block_count_a;
store.account_put (transaction_a, account_a, info);
if (!(block_count_a % store.block_info_max))
{
rai::block_info block_info;
block_info.account = account_a;
block_info.balance = balance_a;
store.block_info_put (transaction_a, hash_a, block_info);
}
checksum_update (transaction_a, hash_a);
}
else

View file

@ -303,6 +303,19 @@ public:
rai::account account;
rai::block_hash hash;
};
class block_info
{
public:
block_info ();
block_info (MDB_val const &);
block_info (rai::account const &, rai::amount const &);
void serialize (rai::stream &) const;
bool deserialize (rai::stream &);
bool operator == (rai::block_info const &) const;
rai::mdb_val val () const;
rai::account account;
rai::amount balance;
};
class block_counts
{
public:
@ -387,6 +400,16 @@ public:
rai::store_iterator pending_begin (MDB_txn *);
rai::store_iterator pending_end ();
void block_info_put (MDB_txn *, rai::block_hash const &, rai::block_info const &);
void block_info_del (MDB_txn *, rai::block_hash const &);
bool block_info_get (MDB_txn *, rai::block_hash const &, rai::block_info &);
bool block_info_exists (MDB_txn *, rai::block_hash const &);
rai::store_iterator block_info_begin (MDB_txn *, rai::block_hash const &);
rai::store_iterator block_info_begin (MDB_txn *);
rai::store_iterator block_info_end ();
rai::uint128_t block_balance (MDB_txn *, rai::block_hash const &);
static size_t const block_info_max = 32;
rai::uint128_t representation_get (MDB_txn *, rai::account const &);
void representation_put (MDB_txn *, rai::account const &, rai::uint128_t const &);
void representation_add (MDB_txn *, rai::account const &, rai::uint128_t const &);
@ -448,6 +471,7 @@ public:
void upgrade_v6_to_v7 (MDB_txn *);
void upgrade_v7_to_v8 (MDB_txn *);
void upgrade_v8_to_v9 (MDB_txn *);
void upgrade_v9_to_v10 (MDB_txn *);
void clear (MDB_dbi);
@ -466,6 +490,8 @@ public:
MDB_dbi change_blocks;
// block_hash -> sender, amount, destination // Pending blocks to sender account, amount, destination account
MDB_dbi pending;
// block_hash -> account, balance // Blocks info
MDB_dbi blocks_info;
// account -> weight // Representation
MDB_dbi representation;
// block_hash -> block // Unchecked bootstrap blocks