static void read_input(struct space *space, struct file *f, off_t *poff, struct bitcoin_transaction_input *input) { pull_hash(f, poff, input->hash); input->index = pull_u32(f, poff); input->script_length = pull_varint(f, poff); input->script = space_alloc(space, input->script_length); pull_bytes(f, poff, input->script, input->script_length); input->sequence_number = pull_u32(f, poff); }
void read_bitcoin_transaction(struct space *space, struct bitcoin_transaction *trans, struct file *f, off_t *poff) { size_t i; off_t start = *poff; SHA256_CTX sha256; trans->version = pull_u32(f, poff); trans->input_count = pull_varint(f, poff); trans->input = space_alloc_arr(space, struct bitcoin_transaction_input, trans->input_count); for (i = 0; i < trans->input_count; i++) read_input(space, f, poff, trans->input + i); trans->output_count = pull_varint(f, poff); trans->output = space_alloc_arr(space, struct bitcoin_transaction_output, trans->output_count); for (i = 0; i < trans->output_count; i++) read_output(space, f, poff, trans->output + i); trans->lock_time = pull_u32(f, poff); /* Bitcoin uses double sha (it's not quite known why...) */ SHA256_Init(&sha256); if (likely(f->mmap)) { SHA256_Update(&sha256, f->mmap + start, *poff - start); } else { u8 *buf = tal_arr(NULL, u8, *poff - start); file_read(f, start, *poff - start, buf); SHA256_Update(&sha256, buf, *poff - start); tal_free(buf); } SHA256_Final(trans->sha256, &sha256); SHA256_Init(&sha256); SHA256_Update(&sha256, trans->sha256, sizeof(trans->sha256)); SHA256_Final(trans->sha256, &sha256); trans->len = *poff - start; }
/* Inefficient, but blk*.dat can have zero(?) padding. */ bool next_block_header_prefix(struct file *f, off_t *off, const u32 marker) { while (*off + sizeof(u32) <= f->len) { u32 val; /* Inefficent, but don't expect it to be far. */ val = pull_u32(f, off); *off -= 4; if (val == marker) return true; (*off)++; } return false; }
static bool pull_foo(const char **p, size_t *len, struct foo *foo) { int ret; ret = pull_u64(p, len, &foo->vu64) + pull_u32(p, len, &foo->vu32) + pull_u16(p, len, &foo->vu16) + pull_u8(p, len, &foo->vu8) + pull_uchar(p, len, &foo->vuchar) + pull_s64(p, len, &foo->vs64) + pull_s32(p, len, &foo->vs32) + pull_s16(p, len, &foo->vs16) + pull_s8(p, len, &foo->vs8) + pull_char(p, len, &foo->vchar) + pull_bytes(p, len, foo->bytes, sizeof(foo->bytes)); if (ret != 11) ok1(len == 0 && *p == NULL); return ret == 11; }
bool read_bitcoin_block_header(struct bitcoin_block *block, struct file *f, off_t *off, u8 block_md[SHA256_DIGEST_LENGTH], const u32 marker) { SHA256_CTX sha256; off_t start; block->D9B4BEF9 = pull_u32(f, off); assert(block->D9B4BEF9 == marker); block->len = pull_u32(f, off); /* Hash only covers version to nonce, inclusive. */ start = *off; block->version = pull_u32(f, off); pull_hash(f, off, block->prev_hash); pull_hash(f, off, block->merkle_hash); block->timestamp = pull_u32(f, off); block->target = pull_u32(f, off); block->nonce = pull_u32(f, off); /* Bitcoin uses double sha (it's not quite known why...) */ SHA256_Init(&sha256); if (likely(f->mmap)) { SHA256_Update(&sha256, f->mmap + start, *off - start); } else { u8 *buf = tal_arr(NULL, u8, *off - start); file_read(f, start, *off - start, buf); SHA256_Update(&sha256, buf, *off - start); tal_free(buf); } SHA256_Final(block_md, &sha256); SHA256_Init(&sha256); SHA256_Update(&sha256, block_md, SHA256_DIGEST_LENGTH); SHA256_Final(block_md, &sha256); block->transaction_count = pull_varint(f, off); return block; }