Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rustyrussell/pettycoin
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 83f94ae2b2a4
Choose a base ref
...
head repository: rustyrussell/pettycoin
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1e592c6657e6
Choose a head ref
  • 4 commits
  • 39 files changed
  • 1 contributor

Commits on Aug 4, 2014

  1. jsonrpc: make command structures const

    Needs a slight tweak to test/mockup.sh to find them.
    
    Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
    rustyrussell committed Aug 4, 2014
    Copy the full SHA
    d8f9587 View commit details

Commits on Aug 5, 2014

  1. jsonrpc: add getblock command

    Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
    rustyrussell committed Aug 5, 2014
    Copy the full SHA
    972580f View commit details
  2. protocol: rename depth to height

    Doesn't change the protocol on the wire, just the field names.
    
    In bitcoin, "depth" usually means number of confirmations; "height" is
    used to mean number of blocks since the genesis block.
    
    Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
    rustyrussell committed Aug 5, 2014
    Copy the full SHA
    bbcfe38 View commit details
  3. jsonrpc: add getblockhash command

    Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
    rustyrussell committed Aug 5, 2014
    Copy the full SHA
    1e592c6 View commit details
22 changes: 11 additions & 11 deletions block.c
Original file line number Diff line number Diff line change
@@ -85,27 +85,27 @@ struct block *block_add(struct state *state,
const u8 *prev_txhashes,
const struct protocol_block_tailer *tailer)
{
u32 depth = le32_to_cpu(hdr->depth);
u32 height = le32_to_cpu(hdr->height);
struct block *block;

log_debug(state->log, "Adding block %u ", depth);
log_debug(state->log, "Adding block %u ", height);
log_add_struct(state->log, struct protocol_double_sha, sha);

block = new_block(state, &prev->total_work, sha, hdr, shard_nums,
merkles, prev_txhashes, tailer);
block->prev = prev;

/* Add to list for that generation. */
if (depth >= tal_count(state->block_depth)) {
/* We can only increment block depths. */
assert(depth == tal_count(state->block_depth));
tal_arr_append(&state->block_depth,
tal(state->block_depth, struct list_head));
list_head_init(state->block_depth[depth]);
if (height >= tal_count(state->block_height)) {
/* We can only increment block heights. */
assert(height == tal_count(state->block_height));
tal_arr_append(&state->block_height,
tal(state->block_height, struct list_head));
list_head_init(state->block_height[height]);
}

/* We give some priority to blocks hear about first. */
list_add_tail(state->block_depth[depth], &block->list);
list_add_tail(state->block_height[height], &block->list);

block->pending_features = pending_features(block);

@@ -132,12 +132,12 @@ struct block *block_add(struct state *state,
struct block *block_find_any(struct state *state,
const struct protocol_double_sha *sha)
{
int i, n = tal_count(state->block_depth);
int i, n = tal_count(state->block_height);
struct block *b;

/* Search recent blocks first. */
for (i = n - 1; i >= 0; i--) {
list_for_each(state->block_depth[i], b, list) {
list_for_each(state->block_height[i], b, list) {
if (structeq(&b->sha, sha))
return b;
}
4 changes: 2 additions & 2 deletions block.h
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
#include <stdbool.h>

struct block {
/* In state->block_depths[le32_to_cpu(hdr->depth)]. */
/* In state->block_height[le32_to_cpu(hdr->height)]. */
struct list_node list;

/* Links through sibling. */
@@ -65,7 +65,7 @@ bool block_empty(const struct block *block);

static inline const struct block *genesis_block(const struct state *state)
{
return list_top(state->block_depth[0], struct block, list);
return list_top(state->block_height[0], struct block, list);
}

/* Create a new block and add into the state structure. */
160 changes: 154 additions & 6 deletions chain.c
Original file line number Diff line number Diff line change
@@ -3,13 +3,17 @@
#include "check_block.h"
#include "complain.h"
#include "generating.h"
#include "hex.h"
#include "jsonrpc.h"
#include "peer.h"
#include "pending.h"
#include "shard.h"
#include "tal_arr.h"
#include "todo.h"
#include "tx.h"
#include <ccan/cast/cast.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/str/str.h>
#include <time.h>

/* Simply block array helpers */
@@ -24,15 +28,15 @@ struct block *step_towards(const struct block *curr, const struct block *target)
const struct block *prev_target;

/* Move back towards target. */
while (le32_to_cpu(curr->hdr->depth) > le32_to_cpu(target->hdr->depth))
while (le32_to_cpu(curr->hdr->height) > le32_to_cpu(target->hdr->height))
curr = curr->prev;

/* Already past it, or equal to it */
if (curr == target)
return NULL;

/* Move target back towards curr. */
while (le32_to_cpu(target->hdr->depth) > le32_to_cpu(curr->hdr->depth)) {
while (le32_to_cpu(target->hdr->height) > le32_to_cpu(curr->hdr->height)) {
prev_target = target;
target = target->prev;
}
@@ -119,13 +123,13 @@ void check_chains(struct state *state, bool all)
if (!all)
return;

for (n = 0; n < tal_count(state->block_depth); n++) {
for (n = 0; n < tal_count(state->block_height); n++) {
size_t num_this_level = num_next_level;
list_check(state->block_depth[n], "bad block depth");
list_check(state->block_height[n], "bad block height");
num_next_level = 0;
list_for_each(state->block_depth[n], i, list) {
list_for_each(state->block_height[n], i, list) {
const struct block *b;
assert(le32_to_cpu(i->hdr->depth) == n);
assert(le32_to_cpu(i->hdr->height) == n);
assert(num_this_level);
num_this_level--;
if (n == 0)
@@ -456,3 +460,147 @@ void update_block_ptrs_invalidated(struct state *state,
/* Tell peers everything changed. */
wake_peers(state);
}

static void json_add_tx(char **response,
const struct block_shard *s,
unsigned int txoff)
{
if (shard_is_tx(s, txoff)) {
const union protocol_tx *tx = s->u[txoff].txp.tx;
struct protocol_double_sha sha;
const struct protocol_input_ref *refs;
unsigned int i;

/* Unknown? We leave object empty. */
if (!tx)
return;

hash_tx(s->u[txoff].txp.tx, &sha);
/* "tx" indicates that we know this tx. */
json_add_double_sha(response, "tx", &sha);
json_array_start(response, "refs");
refs = refs_for(s->u[txoff].txp);
for (i = 0; i < num_inputs(tx); i++) {
json_object_start(response, NULL);
json_add_num(response, "blocks_ago",
le32_to_cpu(refs[i].blocks_ago));
json_add_num(response, "shard",
le16_to_cpu(refs[i].shard));
json_add_num(response, "txoff", refs[i].txoff);
json_object_end(response);
}
json_array_end(response);
} else {
/* We know hash, but not actual tx. */
const struct protocol_txrefhash *hash = s->u[txoff].hash;

json_add_double_sha(response, "txhash", &hash->txhash);
json_add_double_sha(response, "refhash", &hash->refhash);
}
}

static char *json_getblock(struct json_connection *jcon,
const jsmntok_t *params,
char **response)
{
struct protocol_double_sha sha;
const struct block *b, *b2;
jsmntok_t *block;
unsigned int shardnum, i;

json_get_params(jcon->buffer, params, "block", &block, NULL);
if (!block)
return "Need block param";

if (!from_hex(jcon->buffer + block->start,
block->end - block->start, &sha, sizeof(sha)))
return tal_fmt(jcon, "Invalid block hex %.*s",
json_tok_len(block),
json_tok_contents(jcon->buffer, block));

b = block_find_any(jcon->state, &sha);
if (!b)
return tal_fmt(jcon, "Unknown block %.*s",
json_tok_len(block),
json_tok_contents(jcon->buffer, block));

json_object_start(response, NULL);
json_add_double_sha(response, "hash", &b->sha);
json_add_num(response, "version", b->hdr->version);
json_add_num(response, "features_vote", b->hdr->features_vote);
json_add_num(response, "shard_order", b->hdr->shard_order);
json_add_num(response, "nonce1", le32_to_cpu(b->tailer->nonce1));
json_add_hex(response, "nonce2", b->hdr->nonce2,
sizeof(b->hdr->nonce2));
json_add_num(response, "height", le32_to_cpu(b->hdr->height));
json_add_address(response, "fees_to",
jcon->state->test_net, &b->hdr->fees_to);
json_add_num(response, "timestamp",
le32_to_cpu(b->tailer->timestamp));
json_add_num(response, "difficulty",
le32_to_cpu(b->tailer->difficulty));
json_add_double_sha(response, "prev", &b->hdr->prev_block);
json_array_start(response, "next");
list_for_each(&b->children, b2, sibling)
json_add_double_sha(response, NULL, &b2->sha);
json_array_end(response);

json_array_start(response, "merkles");
for (shardnum = 0; shardnum < num_shards(b->hdr); shardnum++)
json_add_double_sha(response, NULL, &b->merkles[shardnum]);
json_array_end(response);

json_array_start(response, "shards");
for (shardnum = 0; shardnum < num_shards(b->hdr); shardnum++) {
struct block_shard *s = b->shard[shardnum];

json_array_start(response, NULL);
for (i = 0; i < s->size; i++) {
json_object_start(response, NULL);
json_add_tx(response, s, i);
json_object_end(response);
}
json_array_end(response);
}
json_array_end(response);
json_object_end(response);
return NULL;
}

const struct json_command getblock_command = {
"getblock",
json_getblock,
"Get a description of a given block",
"hash, version, features_vote, shard_order, nonce1, nonce2, height, fees_to, timestamp, difficulty, prev, next[], merkles[], shards[ [{tx,refs[]}|{}|{txhash,refhash} ] ]"
};

static char *json_getblockhash(struct json_connection *jcon,
const jsmntok_t *params,
char **response)
{
jsmntok_t *height;
unsigned int h;

json_get_params(jcon->buffer, params, "height", &height, NULL);
if (!height)
return "Need height param";

if (!json_tok_number(jcon->buffer, height, &h))
return "height must be a number";

json_array_start(response, NULL);
if (h < tal_count(jcon->state->block_height)) {
struct block *b;
list_for_each(jcon->state->block_height[h], b, list)
json_add_double_sha(response, NULL, &b->sha);
}
json_array_end(response);
return NULL;
}

const struct json_command getblockhash_command = {
"getblockhash",
json_getblockhash,
"Get a hashes of blocks at a given height",
"Takes 'height', returns hash[]"
};
2 changes: 1 addition & 1 deletion chain.h
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ static inline bool block_preceeds(const struct block *a, const struct block *b)
if (a == b)
return true;

if (le32_to_cpu(a->hdr->depth) >= le32_to_cpu(b->hdr->depth))
if (le32_to_cpu(a->hdr->height) >= le32_to_cpu(b->hdr->height))
return false;

return block_preceeds(a, b->prev);
8 changes: 4 additions & 4 deletions check_block.c
Original file line number Diff line number Diff line change
@@ -68,8 +68,8 @@ check_block_header(struct state *state,
if (hdr->shard_order != next_shard_order(*prev))
return PROTOCOL_ECODE_BAD_SHARD_ORDER;

if (le32_to_cpu(hdr->depth) != le32_to_cpu((*prev)->hdr->depth)+1)
return PROTOCOL_ECODE_BAD_DEPTH;
if (le32_to_cpu(hdr->height) != le32_to_cpu((*prev)->hdr->height)+1)
return PROTOCOL_ECODE_BAD_HEIGHT;

/* Can't go backwards, can't be more than 2 hours in future. */
if (!check_timestamp(state, le32_to_cpu(tailer->timestamp), *prev))
@@ -345,8 +345,8 @@ bool check_prev_txhashes(struct state *state, const struct block *block,
log_unusual(state->log,
"Incorrect prev_txhash block %u:"
" block %u shard %u was %u not %u",
le32_to_cpu(block->hdr->depth),
le32_to_cpu(block->hdr->depth) - i,
le32_to_cpu(block->hdr->height),
le32_to_cpu(block->hdr->height) - i,
j,
prev_txh,
block->prev_txhashes[off+j]);
10 changes: 5 additions & 5 deletions complain.c
Original file line number Diff line number Diff line change
@@ -70,7 +70,7 @@ void complain_bad_input(struct state *state,
struct protocol_pkt_complain_tx_bad_input *pkt;

assert(tx_input(tx, bad_input));
log_unusual(state->log, "Block %u ", le32_to_cpu(block->hdr->depth));
log_unusual(state->log, "Block %u ", le32_to_cpu(block->hdr->height));
log_add_struct(state->log, struct protocol_double_sha, &block->sha);
log_add(state->log, " invalid due to tx %u in shard %u ",
proof->pos.txoff, le16_to_cpu(proof->pos.shard));
@@ -99,7 +99,7 @@ void complain_bad_amount(struct state *state,
unsigned int i;

assert(num_inputs(tx));
log_unusual(state->log, "Block %u ", le32_to_cpu(block->hdr->depth));
log_unusual(state->log, "Block %u ", le32_to_cpu(block->hdr->height));
log_add_struct(state->log, struct protocol_double_sha, &block->sha);
log_add(state->log, " invalid amounts in tx %u of shard %u ",
proof->pos.txoff, le16_to_cpu(proof->pos.shard));
@@ -139,7 +139,7 @@ void complain_misorder(struct state *state,
conflict_tx = block_get_tx(block, shardnum, conflict_txoff);
conflict_refs = block_get_refs(block, shardnum, conflict_txoff);

log_unusual(state->log, "Block %u ", le32_to_cpu(block->hdr->depth));
log_unusual(state->log, "Block %u ", le32_to_cpu(block->hdr->height));
log_add_struct(state->log, struct protocol_double_sha, &block->sha);
log_add(state->log, " invalid due to misorder shard %u tx %u vs %u ",
shardnum, conflict_txoff, proof->pos.txoff);
@@ -180,7 +180,7 @@ void complain_bad_input_ref(struct state *state,
le16_to_cpu(bad_ref->shard),
bad_ref->txoff);

log_unusual(state->log, "Block %u ", le32_to_cpu(block->hdr->depth));
log_unusual(state->log, "Block %u ", le32_to_cpu(block->hdr->height));
log_add_struct(state->log, struct protocol_double_sha, &block->sha);
log_unusual(state->log, " tx %u of shard %u ",
proof->pos.txoff, le16_to_cpu(proof->pos.shard));
@@ -275,7 +275,7 @@ void complain_bad_tx(struct state *state,
abort();
}

log_unusual(state->log, "Block %u ", le32_to_cpu(block->hdr->depth));
log_unusual(state->log, "Block %u ", le32_to_cpu(block->hdr->height));
log_add_struct(state->log, struct protocol_double_sha, &block->sha);
log_add(state->log, " invalid due to tx %u of shard %u ",
proof->pos.txoff, le16_to_cpu(proof->pos.shard));
4 changes: 2 additions & 2 deletions create_refs.c
Original file line number Diff line number Diff line change
@@ -35,8 +35,8 @@ static bool resolve_input(struct state *state,

/* Add offset: it might be going to go into *next* block */
ref->blocks_ago =
cpu_to_le32(le32_to_cpu(prev_block->hdr->depth) -
le32_to_cpu(te->u.block->hdr->depth) + offset);
cpu_to_le32(le32_to_cpu(prev_block->hdr->height) -
le32_to_cpu(te->u.block->hdr->height) + offset);
ref->shard = cpu_to_le16(te->shardnum);
ref->txoff = te->txoff;
ref->unused = 0;
4 changes: 2 additions & 2 deletions difficulty.c
Original file line number Diff line number Diff line change
@@ -97,11 +97,11 @@ u32 get_difficulty(struct state *state, const struct block *prev)
prev_difficulty = le32_to_cpu(prev->tailer->difficulty);

/* Same as last block? */
if ((le32_to_cpu(prev->hdr->depth) + 1) % interval)
if ((le32_to_cpu(prev->hdr->height) + 1) % interval)
return prev_difficulty;

/* This creates an out-by-one error for genesis period: that's OK */
if (le32_to_cpu(prev->hdr->depth) == interval - 1)
if (le32_to_cpu(prev->hdr->height) == interval - 1)
start = genesis;
else
/* Bitcoin has this out-by-one error, but nice to test against it. */
2 changes: 1 addition & 1 deletion features.c
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ u8 pending_features(const struct block *block)
u8 result = 0;

/* We only update pending features every FEATURE_VOTE_BLOCKS blocks */
if (le32_to_cpu(block->hdr->depth) % PROTOCOL_FEATURE_VOTE_BLOCKS != 0)
if (le32_to_cpu(block->hdr->height) % PROTOCOL_FEATURE_VOTE_BLOCKS != 0)
return block->prev->pending_features;

for (b = block, i = 0;
Loading