Skip to content

Commit

Permalink
Don't check the entire chain every time.
Browse files Browse the repository at this point in the history
With over 1700 blocks, this was taking a *lot* of CPU.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
rustyrussell committed Jul 30, 2014
1 parent de2e9c8 commit 89841d3
Show file tree
Hide file tree
Showing 11 changed files with 67 additions and 46 deletions.
6 changes: 4 additions & 2 deletions block.c
@@ -1,6 +1,7 @@
#include "block.h"
#include "blockfile.h"
#include "chain.h"
#include "check_block.h"
#include "difficulty.h"
#include "features.h"
#include "generating.h"
Expand Down Expand Up @@ -116,13 +117,14 @@ struct block *block_add(struct state *state,

block->complaint = prev->complaint;
if (block->complaint) {
check_chains(state);
check_chains(state, false);
/* It's not a candidate for real use. */
return block;
}

update_block_ptrs_new_block(state, block);
check_chains(state);
check_chains(state, false);
check_block(state, block, false);
return block;
}

Expand Down
5 changes: 5 additions & 0 deletions blockfile.c
@@ -1,5 +1,6 @@
#include "block.h"
#include "blockfile.h"
#include "chain.h"
#include "check_block.h"
#include "marshal.h"
#include "packet_io.h"
Expand Down Expand Up @@ -123,6 +124,10 @@ void load_blocks(struct state *state)
out:
/* Now we can save more. */
state->blockfd = fd;

log_info(state->log, "Checking chains...");
check_chains(state, true);
log_add(state->log, " ...completed");
}

void save_block(struct state *state, struct block *new)
Expand Down
70 changes: 36 additions & 34 deletions chain.c
Expand Up @@ -73,7 +73,7 @@ static bool find_connected_pair(const struct state *state,
return false;
}

void check_chains(struct state *state)
void check_chains(struct state *state, bool all)
{
const struct block *i;
size_t n, num_next_level = 1;
Expand All @@ -88,6 +88,37 @@ void check_chains(struct state *state)
assert(cmp_work(state->longest_knowns[n],
state->longest_knowns[0]) == 0);


/* preferred_chain should be a descendent of longest_knowns[0] */
for (i = state->preferred_chain;
i != state->longest_knowns[0];
i = i->prev) {
assert(i != genesis_block(state));
assert(!i->all_known);
}

/*
* preferred_chain is *not* state->longest_chains[0], then no
* chain should connect any longest_knowns to longest_chains.
*/
if (state->preferred_chain != state->longest_chains[0]) {
size_t a, b;
assert(!find_connected_pair(state, &a, &b));
}

/* We ignore blocks which have a problem. */
assert(!state->preferred_chain->complaint);

for (n = 0; n < tal_count(state->longest_knowns); n++)
assert(!state->longest_knowns[n]->complaint);

for (n = 0; n < tal_count(state->longest_chains); n++)
assert(!state->longest_chains[n]->complaint);

/* Checking the actual blocks is expensive! */
if (!all)
return;

for (n = 0; n < tal_count(state->block_depth); n++) {
size_t num_this_level = num_next_level;
list_check(state->block_depth[n], "bad block depth");
Expand All @@ -109,42 +140,16 @@ void check_chains(struct state *state)
cmp_work(i, state->longest_chains[0]) <= 0);
if (!i->complaint && i->all_known)
assert(cmp_work(i, state->longest_knowns[0]) <= 0);

list_for_each(&i->children, b, sibling) {
num_next_level++;
assert(b->prev == i);
}
check_block(state, i);
check_block(state, i, all);
}
assert(num_this_level == 0);
assert(num_this_level == 0);
}
assert(num_next_level == 0);

/* preferred_chain should be a descendent of longest_knowns[0] */
for (i = state->preferred_chain;
i != state->longest_knowns[0];
i = i->prev) {
assert(i != genesis_block(state));
assert(!i->all_known);
}

/*
* preferred_chain is *not* state->longest_chains[0], then no
* chain should connect any longest_knowns to longest_chains.
*/
if (state->preferred_chain != state->longest_chains[0]) {
size_t a, b;
assert(!find_connected_pair(state, &a, &b));
}

/* We ignore blocks which have a problem. */
assert(!state->preferred_chain->complaint);

for (n = 0; n < tal_count(state->longest_knowns); n++)
assert(!state->longest_knowns[n]->complaint);

for (n = 0; n < tal_count(state->longest_chains); n++)
assert(!state->longest_chains[n]->complaint);
}

static void swap_blockptr(const struct block **a, const struct block **b)
Expand Down Expand Up @@ -301,7 +306,6 @@ static bool update_known(struct state *state, struct block *block)

order_block_pointers(state);
update_preferred_chain(state);
check_chains(state);

if (state->longest_knowns[0] != prev_known) {
/* Any transactions from old branch go into pending. */
Expand Down Expand Up @@ -409,8 +413,6 @@ void update_block_ptrs_new_block(struct state *state, struct block *block)

/* FIXME: Only needed if a descendent of known[0] */
update_preferred_chain(state);

check_chains(state);
}

/* Filled a new shard; update state->longest_chains, state->longest_knowns,
Expand Down Expand Up @@ -446,7 +448,7 @@ void update_block_ptrs_invalidated(struct state *state,
find_longest_descendents(g, &state->longest_chains);
update_known(state, cast_const(struct block *, g));

check_chains(state);
check_chains(state, false);

/* We don't need to know anything about this or any decendents. */
forget_about_all(state, block);
Expand Down
2 changes: 1 addition & 1 deletion chain.h
Expand Up @@ -51,5 +51,5 @@ void update_block_ptrs_new_shard(struct state *state, struct block *block,
void update_block_ptrs_invalidated(struct state *state, const struct block *block);

/* Debugging check */
void check_chains(struct state *state);
void check_chains(struct state *state, bool all);
#endif /* PETTYCOIN_CHAIN_H */
15 changes: 12 additions & 3 deletions check_block.c
Expand Up @@ -249,6 +249,9 @@ void put_tx_in_shard(struct state *state,

/* Tell peers about the new tx in block. */
send_tx_in_block_to_peers(state, source, block, shard->shardnum, txoff);

/* Debugging check */
check_block_shard(state, block, shard);
}

bool put_txhash_in_shard(struct state *state,
Expand Down Expand Up @@ -278,6 +281,10 @@ bool put_txhash_in_shard(struct state *state,

/* This could eliminate a pending tx. */
state->pending->needs_recheck = true;

/* Debugging check */
check_block_shard(state, block, shard);

return true;
}

Expand Down Expand Up @@ -356,7 +363,7 @@ bool check_prev_txhashes(struct state *state, const struct block *block,
return true;
}

void check_block(struct state *state, const struct block *block)
void check_block(struct state *state, const struct block *block, bool all)
{
u32 diff = le32_to_cpu(block->tailer->difficulty);
struct protocol_double_sha sha;
Expand All @@ -381,8 +388,10 @@ void check_block(struct state *state, const struct block *block)

/* FIXME: check block->prev_txhashes! */

for (shard = 0; shard < num_shards(block->hdr); shard++) {
check_block_shard(state, block, block->shard[shard]);
if (all) {
for (shard = 0; shard < num_shards(block->hdr); shard++) {
check_block_shard(state, block, block->shard[shard]);
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion check_block.h
Expand Up @@ -74,5 +74,5 @@ bool check_tx_inputs_and_refs(struct state *state,
struct protocol_input_ref *refs);

/* Various assertions about a block */
void check_block(struct state *state, const struct block *block);
void check_block(struct state *state, const struct block *block, bool all);
#endif /* PETTYCOIN_CHECK_BLOCK_H */
2 changes: 1 addition & 1 deletion test/run-02-prev_txhashes.c
Expand Up @@ -83,7 +83,7 @@ size_t marshal_input_ref_len(const union protocol_tx *tx)
return 0;
}

void check_block(struct state *state, const struct block *block)
void check_block(struct state *state, const struct block *block, bool all)
{
}

Expand Down
2 changes: 1 addition & 1 deletion test/run-03-check_block.c
Expand Up @@ -224,7 +224,7 @@ int main(int argc, char *argv[])
/* We need enough of state to use the real init function here. */
pseudorand_init();
s = new_state(true);
check_chains(s);
check_chains(s, true);

fake_time = le32_to_cpu(genesis_tlr.timestamp) + 1;

Expand Down
2 changes: 1 addition & 1 deletion test/run-08-simple-chain.c
Expand Up @@ -14,7 +14,7 @@
void block_to_pending(struct state *state, const struct block *block)
{ fprintf(stderr, "block_to_pending called!\n"); abort(); }
/* Generated stub for check_block */
void check_block(struct state *state, const struct block *block)
void check_block(struct state *state, const struct block *block, bool all)
{ fprintf(stderr, "check_block called!\n"); abort(); }
/* Generated stub for check_prev_txhashes */
bool check_prev_txhashes(struct state *state, const struct block *block,
Expand Down
5 changes: 4 additions & 1 deletion test/run-08-tx_shard.c
Expand Up @@ -13,8 +13,11 @@
#include "helper_gateway_key.h"

/* AUTOGENERATED MOCKS START */
/* Generated stub for check_block */
void check_block(struct state *state, const struct block *block, bool all)
{ fprintf(stderr, "check_block called!\n"); abort(); }
/* Generated stub for check_chains */
void check_chains(struct state *state)
void check_chains(struct state *state, bool all)
{ fprintf(stderr, "check_chains called!\n"); abort(); }
/* Generated stub for check_tx */
enum protocol_ecode check_tx(struct state *state, const union protocol_tx *tx,
Expand Down
2 changes: 1 addition & 1 deletion test/run-09-chain.c
Expand Up @@ -63,7 +63,7 @@ void block_to_pending(struct state *state, const struct block *block)
{
}

void check_block(struct state *state, const struct block *block)
void check_block(struct state *state, const struct block *block, bool all)
{
}

Expand Down

0 comments on commit 89841d3

Please sign in to comment.