Skip to content

Commit

Permalink
Fixing corruption where rollbacks were incorrectly setting rep_block.
Browse files Browse the repository at this point in the history
  • Loading branch information
clemahieu committed Apr 30, 2016
1 parent 87553eb commit b7e17f9
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 45 deletions.
11 changes: 10 additions & 1 deletion rai/core_test/block_store.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -597,17 +597,19 @@ TEST (block_store, upgrade_v2_v3)
{
rai::keypair key1;
rai::keypair key2;
rai::block_hash change_hash;
auto path (rai::unique_path ());
{
bool init (false);
rai::block_store store (init, path);
ASSERT_TRUE (!init);
rai::transaction transaction (store.environment, nullptr, true);
rai::genesis genesis;
auto hash (genesis.hash ());
rai::transaction transaction (store.environment, nullptr, true);
genesis.initialize (transaction, store);
rai::ledger ledger (store);
rai::change_block change (hash, key1.pub, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
change_hash = change.hash ();
ASSERT_EQ (rai::process_result::progress, ledger.process (transaction, change).code);
ASSERT_EQ (0, ledger.weight(transaction, rai::test_genesis_key.pub));
ASSERT_EQ (rai::genesis_amount, ledger.weight (transaction, key1.pub));
Expand All @@ -617,6 +619,10 @@ TEST (block_store, upgrade_v2_v3)
ASSERT_EQ (2, store.version_get (transaction));
store.representation_put (transaction, key2.pub, 6);
ASSERT_EQ (6, ledger.weight (transaction, key2.pub));
rai::account_info info;
ASSERT_FALSE (store.account_get (transaction, rai::test_genesis_key.pub, info));
info.rep_block = 42;
store.account_put (transaction, rai::test_genesis_key.pub, info);
}
bool init (false);
rai::block_store store (init, path);
Expand All @@ -626,4 +632,7 @@ TEST (block_store, upgrade_v2_v3)
ASSERT_EQ (3, 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);
}
12 changes: 12 additions & 0 deletions rai/core_test/ledger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,15 +289,27 @@ TEST (ledger, rollback_representation)
ASSERT_EQ (rai::process_result::progress, ledger.process (transaction, receive1).code);
ASSERT_EQ (1, ledger.weight (transaction, key3.pub));
ASSERT_EQ (rai::genesis_amount - 1, ledger.weight (transaction, key4.pub));
rai::account_info info1;
ASSERT_FALSE (store.account_get (transaction, key2.pub, info1));
ASSERT_EQ (open.hash (), info1.rep_block);
ledger.rollback (transaction, receive1.hash ());
rai::account_info info2;
ASSERT_FALSE (store.account_get (transaction, key2.pub, info2));
ASSERT_EQ (open.hash (), info2.rep_block);
ASSERT_EQ (0, ledger.weight (transaction, key2.pub));
ASSERT_EQ (rai::genesis_amount - 50, ledger.weight (transaction, key4.pub));
ledger.rollback (transaction, open.hash ());
ASSERT_EQ (1, ledger.weight (transaction, key3.pub));
ASSERT_EQ (0, ledger.weight (transaction, key4.pub));
ledger.rollback (transaction, send1.hash ());
ASSERT_EQ (rai::genesis_amount, ledger.weight (transaction, key3.pub));
rai::account_info info3;
ASSERT_FALSE (store.account_get (transaction, rai::test_genesis_key.pub, info3));
ASSERT_EQ (change2.hash (), info3.rep_block);
ledger.rollback (transaction, change2.hash ());
rai::account_info info4;
ASSERT_FALSE (store.account_get (transaction, rai::test_genesis_key.pub, info4));
ASSERT_EQ (change1.hash (), info4.rep_block);
ASSERT_EQ (rai::genesis_amount, ledger.weight (transaction, key5.pub));
ASSERT_EQ (0, ledger.weight (transaction, key3.pub));
}
Expand Down
94 changes: 50 additions & 44 deletions rai/secure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1606,14 +1606,62 @@ void rai::block_store::upgrade_v1_to_v2 (MDB_txn * transaction_a)
}
}

// Determine the representative for this block
class representative_visitor : public rai::block_visitor
{
public:
representative_visitor (MDB_txn * transaction_a, rai::block_store & store_a) :
transaction (transaction_a),
store (store_a),
result (0)
{
}
void compute (rai::block_hash const & hash_a)
{
current = hash_a;
while (result.is_zero ())
{
auto block (store.block_get (transaction, current));
assert (block != nullptr);
block->visit (*this);
}
}
void send_block (rai::send_block const & block_a) override
{
current = block_a.previous ();
}
void receive_block (rai::receive_block const & block_a) override
{
current = block_a.previous ();
}
void open_block (rai::open_block const & block_a) override
{
result = block_a.hash ();
}
void change_block (rai::change_block const & block_a) override
{
result = block_a.hash ();
}
MDB_txn * transaction;
rai::block_store & store;
rai::block_hash current;
rai::account result;
};

void rai::block_store::upgrade_v2_to_v3 (MDB_txn * transaction_a)
{
version_put (transaction_a, 3);
mdb_drop (transaction_a, representation, 0);
for (auto i (latest_begin (transaction_a)), n (latest_end ()); i != n; ++i)
{
rai::account account_l (i->first);
account_info info (i->second);
representation_add (transaction_a, info.rep_block, info.balance.number());
representative_visitor visitor (transaction_a, *this);
visitor.compute (info.head);
assert (!visitor.result.is_zero ());
info.rep_block = visitor.result;
mdb_cursor_put (i.cursor, account_l.val (), info.val (), MDB_CURRENT);
representation_add (transaction_a, visitor.result, info.balance.number());
}
}

Expand Down Expand Up @@ -2444,48 +2492,6 @@ void balance_visitor::change_block (rai::change_block const & block_a)
current = block_a.hashables.previous;
}

// Determine the representative for this block
class representative_visitor : public rai::block_visitor
{
public:
representative_visitor (MDB_txn * transaction_a, rai::block_store & store_a) :
transaction (transaction_a),
store (store_a),
result (0)
{
}
void compute (rai::block_hash const & hash_a)
{
current = hash_a;
while (result.is_zero ())
{
auto block (store.block_get (transaction, current));
assert (block != nullptr);
block->visit (*this);
}
}
void send_block (rai::send_block const & block_a) override
{
current = block_a.previous ();
}
void receive_block (rai::receive_block const & block_a) override
{
current = block_a.previous ();
}
void open_block (rai::open_block const & block_a) override
{
result = block_a.hash ();
}
void change_block (rai::change_block const & block_a) override
{
result = block_a.hash ();
}
MDB_txn * transaction;
rai::block_store & store;
rai::block_hash current;
rai::account result;
};

// Rollback this block
class rollback_visitor : public rai::block_visitor
{
Expand Down Expand Up @@ -2517,7 +2523,7 @@ class rollback_visitor : public rai::block_visitor
void receive_block (rai::receive_block const & block_a) override
{
auto hash (block_a.hash ());
auto representative (ledger.representative (transaction, block_a.hashables.source));
auto representative (ledger.representative (transaction, block_a.hashables.previous));
auto amount (ledger.amount (transaction, block_a.hashables.source));
auto destination_account (ledger.account (transaction, hash));
ledger.store.representation_add (transaction, ledger.representative (transaction, hash), 0 - amount);
Expand Down

0 comments on commit b7e17f9

Please sign in to comment.