| 282 | } |
| 283 | |
| 284 | u64 account_onchain_closeheight(const struct bkpr *bkpr, |
| 285 | struct command *cmd, |
| 286 | const struct account *acct) |
| 287 | { |
| 288 | const u8 *ctx = tal(NULL, u8); |
| 289 | struct txo_set **sets; |
| 290 | struct chain_event *close_ev; |
| 291 | u64 height; |
| 292 | |
| 293 | assert(acct->closed_count > 0); |
| 294 | |
| 295 | close_ev = find_chain_event_by_id(ctx, bkpr, cmd, |
| 296 | *acct->closed_event_db_id); |
| 297 | |
| 298 | if (find_txo_chain(ctx, bkpr, cmd, acct, &sets)) { |
| 299 | /* Ok now we find the max block height of the |
| 300 | * spending chain_events for this channel */ |
| 301 | bool ok; |
| 302 | const char *buf; |
| 303 | const jsmntok_t *result, *rows, *row; |
| 304 | size_t i; |
| 305 | |
| 306 | /* Have we accounted for all the outputs */ |
| 307 | ok = false; |
| 308 | for (i = 0; i < tal_count(sets); i++) { |
| 309 | if (bitcoin_txid_eq(sets[i]->txid, |
| 310 | close_ev->spending_txid)) { |
| 311 | |
| 312 | ok = tal_count(sets[i]->pairs) |
| 313 | == acct->closed_count; |
| 314 | break; |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | if (!ok) { |
| 319 | tal_free(ctx); |
| 320 | return 0; |
| 321 | } |
| 322 | |
| 323 | result = sql_req(tmpctx, cmd, &buf, |
| 324 | "SELECT blockheight" |
| 325 | " FROM chainmoves" |
| 326 | " WHERE account_id = '%s'" |
| 327 | " AND spending_txid IS NOT NULL" |
| 328 | " AND created_index <= %"PRIu64 |
| 329 | " ORDER BY blockheight DESC" |
| 330 | " LIMIT 1", |
| 331 | sql_string(tmpctx, acct->name), |
| 332 | bkpr->chainmoves_index); |
| 333 | |
| 334 | rows = json_get_member(buf, result, "rows"); |
| 335 | assert(rows && rows->type == JSMN_ARRAY); |
| 336 | |
| 337 | height = 0; |
| 338 | json_for_each_arr(i, row, rows) { |
| 339 | const jsmntok_t *val = row + 1; |
| 340 | assert(row->size == 1); |
| 341 | ok = json_to_u64(buf, val, &height); |
no test coverage detected