#include "bitcoin/block.h" #include "bitcoin/tx.h" #include "bitcoind.h" #include "chaintopology.h" #include "lightningd.h" #include "log.h" #include "peer.h" #include "timeout.h" #include "utils.h" #include "watch.h" #include #include #include #include #include #include struct block { int height; /* Actual header. */ struct bitcoin_block_hdr hdr; /* Previous block (if any). */ struct block *prev; /* Next block (if any). */ struct block *next; /* Key for hash table */ struct sha256_double blkid; /* 0 if not enough predecessors. */ u32 mediantime; /* Transactions in this block we care about */ struct sha256_double *txids; /* Full copy of txs (trimmed to txs list in connect_block) */ struct bitcoin_tx **full_txs; }; /* Hash blocks by sha */ static const struct sha256_double *keyof_block_map(const struct block *b) { return &b->blkid; } static size_t hash_sha(const struct sha256_double *key) { size_t ret; memcpy(&ret, key, sizeof(ret)); return ret; } static bool block_eq(const struct block *b, const struct sha256_double *key) { return structeq(&b->blkid, key); } HTABLE_DEFINE_TYPE(struct block, keyof_block_map, hash_sha, block_eq, block_map); struct topology { struct block *root; struct block *tip; struct block_map block_map; u64 feerate; bool startup; }; static void start_poll_chaintip(struct lightningd_state *dstate); static void next_topology_timer(struct lightningd_state *dstate) { if (dstate->topology->startup) { dstate->topology->startup = false; io_break(dstate); } new_reltimer(dstate, dstate, dstate->config.poll_time, start_poll_chaintip, dstate); } static int cmp_times(const u32 *a, const u32 *b, void *unused) { if (*a > *b) return -1; else if (*b > * a) return 1; return 0; } /* Mediantime is median of this and previous 10 blocks. */ static u32 get_mediantime(const struct topology *topo, const struct block *b) { unsigned int i; u32 times[11]; for (i = 0; i < ARRAY_SIZE(times); i++) { if (!b) return 0; times[i] = le32_to_cpu(b->hdr.timestamp); b = b->prev; } asort(times, ARRAY_SIZE(times), cmp_times, NULL); return times[ARRAY_SIZE(times) / 2]; } /* FIXME: Remove tx from block when peer done. */ static void add_tx_to_block(struct block *b, const struct sha256_double *txid) { size_t n = tal_count(b->txids); tal_resize(&b->txids, n+1); b->txids[n] = *txid; } static bool we_broadcast(struct lightningd_state *dstate, const struct sha256_double *txid) { struct peer *peer; list_for_each(&dstate->peers, peer, list) { struct outgoing_tx *otx; list_for_each(&peer->outgoing_txs, otx, list) { if (structeq(&otx->txid, txid)) return true; } } return false; } /* Fills in prev, height, mediantime. */ static void connect_block(struct lightningd_state *dstate, struct block *prev, struct block *b) { struct topology *topo = dstate->topology; size_t i; assert(b->height == -1); assert(b->mediantime == 0); assert(b->prev == NULL); assert(prev->next == b); b->prev = prev; b->height = b->prev->height + 1; b->mediantime = get_mediantime(topo, b); block_map_add(&topo->block_map, b); /* Now we see if any of those txs are interesting. */ for (i = 0; i < tal_count(b->full_txs); i++) { struct bitcoin_tx *tx = b->full_txs[i]; struct sha256_double txid; size_t j; /* Tell them if it spends a txo we care about. */ for (j = 0; j < tx->input_count; j++) { struct txwatch_output out; struct txowatch *txo; out.txid = tx->input[j].txid; out.index = tx->input[j].index; txo = txowatch_hash_get(&dstate->txowatches, &out); if (txo) txowatch_fire(dstate, txo, tx, j); } /* We did spends first, in case that tells us to watch tx. */ bitcoin_txid(tx, &txid); if (watching_txid(dstate, &txid) || we_broadcast(dstate, &txid)) add_tx_to_block(b, &txid); } b->full_txs = tal_free(b->full_txs); } static bool tx_in_block(const struct block *b, const struct sha256_double *txid) { size_t i, n = tal_count(b->txids); for (i = 0; i < n; i++) { if (structeq(&b->txids[i], txid)) return true; } return false; } /* FIXME: Use hash table. */ static struct block *block_for_tx(struct lightningd_state *dstate, const struct sha256_double *txid) { struct topology *topo = dstate->topology; struct block *b; for (b = topo->tip; b; b = b->prev) { if (tx_in_block(b, txid)) return b; } return NULL; } size_t get_tx_depth(struct lightningd_state *dstate, const struct sha256_double *txid) { struct topology *topo = dstate->topology; const struct block *b; b = block_for_tx(dstate, txid); if (!b) return 0; return topo->tip->height - b->height + 1; } /* We just sent the last entry in txs[]. Shrink and send the next last. */ static void broadcast_remainder(struct lightningd_state *dstate, int exitstatus, const char *msg, char **txs) { size_t num_txs = tal_count(txs); const char *sent_tx, *next_tx; sent_tx = txs[num_txs-1]; /* These are expected. */ if (strstr(msg, "txn-mempool-conflict") || strstr(msg, "transaction already in block chain")) log_debug(dstate->base_log, "Expected error broadcasting tx %s: %s", sent_tx, msg); else if (exitstatus) log_unusual(dstate->base_log, "Broadcasting tx %s: %i %s", sent_tx, exitstatus, msg); /* Strip off last one. */ tal_resize(&txs, --num_txs); if (num_txs == 0) { tal_free(txs); return; } /* Broadcast next one. */ next_tx = txs[num_txs-1]; bitcoind_sendrawtx(NULL, dstate, next_tx, broadcast_remainder, txs); } /* FIXME: This is dumb. We can group txs and avoid bothering bitcoind * if any one tx is in the main chain. */ static void rebroadcast_txs(struct lightningd_state *dstate) { /* Copy txs now (peers may go away, and they own txs). */ size_t num_txs = 0; char **txs = tal_arr(dstate, char *, 0); struct peer *peer; list_for_each(&dstate->peers, peer, list) { struct outgoing_tx *otx; list_for_each(&peer->outgoing_txs, otx, list) { if (block_for_tx(dstate, &otx->txid)) continue; tal_resize(&txs, num_txs+1); txs[num_txs] = tal_strdup(txs, otx->hextx); num_txs++; } } if (num_txs) bitcoind_sendrawtx(NULL, dstate, txs[num_txs-1], broadcast_remainder, txs); else tal_free(txs); } static void destroy_outgoing_tx(struct outgoing_tx *otx) { list_del_from(&otx->peer->outgoing_txs, &otx->list); } static void broadcast_done(struct lightningd_state *dstate, int exitstatus, const char *msg, struct outgoing_tx *otx) { if (otx->failed && exitstatus != 0) { otx->failed(otx->peer, exitstatus, msg); tal_free(otx); } else { /* For continual rebroadcasting */ list_add_tail(&otx->peer->outgoing_txs, &otx->list); tal_add_destructor(otx, destroy_outgoing_tx); } } void broadcast_tx(struct peer *peer, const struct bitcoin_tx *tx, void (*failed)(struct peer *peer, int exitstatus, const char *err)) { struct outgoing_tx *otx = tal(peer, struct outgoing_tx); const u8 *rawtx = linearize_tx(otx, tx); otx->peer = peer; bitcoin_txid(tx, &otx->txid); otx->hextx = tal_hexstr(otx, rawtx, tal_count(rawtx)); otx->failed = failed; tal_free(rawtx); log_add_struct(peer->log, " (tx %s)", struct sha256_double, &otx->txid); bitcoind_sendrawtx(peer, peer->dstate, otx->hextx, broadcast_done, otx); } static void free_blocks(struct lightningd_state *dstate, struct block *b) { struct block *next; while (b) { size_t i, n = tal_count(b->txids); /* Notify that txs are kicked out. */ for (i = 0; i < n; i++) txwatch_fire(dstate, &b->txids[i], 0); next = b->next; tal_free(b); b = next; } } static void update_fee(struct lightningd_state *dstate, u64 rate, u64 *feerate) { log_debug(dstate->base_log, "Feerate %"PRIu64" -> %"PRIu64, rate, *feerate); *feerate = rate; } /* B is the new chain (linked by ->next); update topology */ static void topology_changed(struct lightningd_state *dstate, struct block *prev, struct block *b) { /* Eliminate any old chain. */ if (prev->next) free_blocks(dstate, prev->next); prev->next = b; do { connect_block(dstate, prev, b); dstate->topology->tip = prev = b; b = b->next; } while (b); /* Tell watch code to re-evaluate all txs. */ watch_topology_changed(dstate); /* Maybe need to rebroadcast. */ rebroadcast_txs(dstate); /* Once per new block head, update fee estimate. */ bitcoind_estimate_fee(dstate, update_fee, &dstate->topology->feerate); } static struct block *new_block(struct lightningd_state *dstate, struct bitcoin_block *blk, struct block *next) { struct topology *topo = dstate->topology; struct block *b = tal(topo, struct block); sha256_double(&b->blkid, &blk->hdr, sizeof(blk->hdr)); log_debug_struct(dstate->base_log, "Adding block %s", struct sha256_double, &b->blkid); assert(!block_map_get(&topo->block_map, &b->blkid)); b->next = next; /* We fill these out in topology_changed */ b->height = -1; b->mediantime = 0; b->prev = NULL; b->hdr = blk->hdr; b->txids = tal_arr(b, struct sha256_double, 0); b->full_txs = tal_steal(b, blk->tx); return b; } static void gather_blocks(struct lightningd_state *dstate, struct bitcoin_block *blk, struct block *next) { struct topology *topo = dstate->topology; struct block *b, *prev; b = new_block(dstate, blk, next); /* Recurse if we need prev. */ prev = block_map_get(&topo->block_map, &blk->hdr.prev_hash); if (!prev) { bitcoind_getrawblock(dstate, &blk->hdr.prev_hash, gather_blocks, b); return; } /* All done. */ topology_changed(dstate, prev, b); next_topology_timer(dstate); } static void check_chaintip(struct lightningd_state *dstate, const struct sha256_double *tipid, void *arg) { struct topology *topo = dstate->topology; /* 0 is the main tip. */ if (!structeq(tipid, &topo->tip->blkid)) bitcoind_getrawblock(dstate, tipid, gather_blocks, (struct block *)NULL); else /* Next! */ next_topology_timer(dstate); } static void start_poll_chaintip(struct lightningd_state *dstate) { if (!list_empty(&dstate->bitcoin_req)) { log_unusual(dstate->base_log, "Delaying start poll: commands in progress"); next_topology_timer(dstate); } else bitcoind_get_chaintip(dstate, check_chaintip, NULL); } static void init_topo(struct lightningd_state *dstate, struct bitcoin_block *blk, ptrint_t *p) { struct topology *topo = dstate->topology; topo->root = new_block(dstate, blk, NULL); topo->root->height = ptr2int(p); block_map_add(&topo->block_map, topo->root); topo->tip = topo->root; /* Now grab chaintip immediately. */ bitcoind_get_chaintip(dstate, check_chaintip, NULL); } static void get_init_block(struct lightningd_state *dstate, const struct sha256_double *blkid, ptrint_t *blknum) { bitcoind_getrawblock(dstate, blkid, init_topo, blknum); } static void get_init_blockhash(struct lightningd_state *dstate, u32 blockcount, void *unused) { u32 start; struct peer *peer; if (blockcount < 100) start = 0; else start = blockcount - 100; /* If loaded from database, go back to earliest possible peer anchor. */ list_for_each(&dstate->peers, peer, list) { if (peer->anchor.min_depth && peer->anchor.min_depth < start) start = peer->anchor.min_depth; } /* Start topology from 100 blocks back. */ bitcoind_getblockhash(dstate, start, get_init_block, int2ptr(start)); } u32 get_tx_mediantime(struct lightningd_state *dstate, const struct sha256_double *txid) { struct block *b; b = block_for_tx(dstate, txid); if (b) return b->mediantime; fatal("Tx %s not found for get_tx_mediantime", tal_hexstr(dstate, txid, sizeof(*txid))); } u32 get_tip_mediantime(struct lightningd_state *dstate) { return dstate->topology->tip->mediantime; } u32 get_block_height(struct lightningd_state *dstate) { return dstate->topology->tip->height; } u64 get_feerate(struct lightningd_state *dstate) { if (dstate->config.override_fee_rate) { log_debug(dstate->base_log, "Forcing fee rate, ignoring estimate"); return dstate->config.override_fee_rate; } else if (dstate->topology->feerate == 0) { log_info(dstate->base_log, "No fee estimate: using default fee rate"); return dstate->config.default_fee_rate; } return dstate->topology->feerate; } struct txlocator *locate_tx(const void *ctx, struct lightningd_state *dstate, const struct sha256_double *txid) { struct block *block = block_for_tx(dstate, txid); if (block == NULL) { return NULL; } struct txlocator *loc = talz(ctx, struct txlocator); loc->blkheight = block->height; size_t i, n = tal_count(block->txids); for (i = 0; i < n; i++) { if (structeq(&block->txids[i], txid)){ loc->index = i; break; } } return loc; } void setup_topology(struct lightningd_state *dstate) { dstate->topology = tal(dstate, struct topology); block_map_init(&dstate->topology->block_map); dstate->topology->startup = true; dstate->topology->feerate = 0; bitcoind_getblockcount(dstate, get_init_blockhash, NULL); /* Once it gets topology, it calls io_break() and we return. */ io_loop(NULL, NULL); assert(!dstate->topology->startup); }