Process or initialize from a block. */
| 186 | |
| 187 | /* Process or initialize from a block. */ |
| 188 | static struct command_result *handle_block(struct command *cmd, |
| 189 | const char *method UNUSED, |
| 190 | const char *buf, |
| 191 | const jsmntok_t *result, |
| 192 | ptrint_t *block_heightptr) |
| 193 | { |
| 194 | struct bwatch *bwatch = bwatch_of(cmd->plugin); |
| 195 | struct bitcoin_blkid blockhash; |
| 196 | struct bitcoin_block *block; |
| 197 | bool is_init = (bwatch->current_height == 0); |
| 198 | u32 block_height = ptr2int(block_heightptr); |
| 199 | |
| 200 | block = block_from_response(buf, result, &blockhash); |
| 201 | if (!block) { |
| 202 | plugin_log(cmd->plugin, LOG_UNUSUAL, |
| 203 | "Failed to get/parse block %u: '%.*s'", |
| 204 | block_height, |
| 205 | json_tok_full_len(result), |
| 206 | json_tok_full(buf, result)); |
| 207 | return poll_finished(cmd); |
| 208 | } |
| 209 | |
| 210 | if (!is_init) { |
| 211 | /* Verify the parent of the new block is our current tip; if |
| 212 | * not, we have a reorg. Pop the tip and refetch the block |
| 213 | * until we find a common ancestor, then roll forward from |
| 214 | * there. Skip when history is empty (rollback exhausted it). */ |
| 215 | if (tal_count(bwatch->block_history) > 0 && |
| 216 | !bitcoin_blkid_eq(&block->hdr.prev_hash, &bwatch->current_blockhash)) { |
| 217 | plugin_log(cmd->plugin, LOG_INFORM, |
| 218 | "Reorg detected at block %u: expected parent %s, got %s (fetched block hash: %s)", |
| 219 | block_height, |
| 220 | fmt_bitcoin_blkid(tmpctx, &bwatch->current_blockhash), |
| 221 | fmt_bitcoin_blkid(tmpctx, &block->hdr.prev_hash), |
| 222 | fmt_bitcoin_blkid(tmpctx, &blockhash)); |
| 223 | bwatch_remove_tip(cmd, bwatch); |
| 224 | return fetch_block_handle(cmd, bwatch->current_height + 1); |
| 225 | } |
| 226 | |
| 227 | /* Depth first: restart-marker watches (e.g. onchaind/ |
| 228 | * channel_close) start subdaemons before outpoint watches |
| 229 | * fire for the same block. */ |
| 230 | bwatch_check_blockdepth_watches(cmd, bwatch, block_height); |
| 231 | bwatch_process_block_txs(cmd, bwatch, block, block_height, |
| 232 | &blockhash, NULL); |
| 233 | } |
| 234 | |
| 235 | /* Update state */ |
| 236 | bwatch->current_height = block_height; |
| 237 | bwatch->current_blockhash = blockhash; |
| 238 | |
| 239 | /* Update in-memory history immediately */ |
| 240 | bwatch_add_block_to_history(bwatch, bwatch->current_height, &blockhash, |
| 241 | &block->hdr.prev_hash); |
| 242 | |
| 243 | struct block_record_wire br = { |
| 244 | bwatch->current_height, |
| 245 | bwatch->current_blockhash, |
nothing calls this directly
no test coverage detected