struct channel_state *initial_funding(const tal_t *ctx, const OpenChannel *a, const OpenChannel *b, const OpenAnchor *anchor, uint64_t fee) { struct channel_state *state = talz(ctx, struct channel_state); state->a.htlcs = tal_arr(state, UpdateAddHtlc *, 0); state->b.htlcs = tal_arr(state, UpdateAddHtlc *, 0); if (fee > anchor->amount) return tal_free(state); /* Initially, all goes back to funder. */ state->a.pay = anchor->amount - fee; state->a.fee = fee; /* If B (not A) is funder, invert. */ if (is_funder(b)) invert_cstate(state); /* This checks we only have 1 anchor, and is nice code reuse. */ if (!funding_delta(a, b, anchor, 0, 0, &state->a, &state->b)) return tal_free(state); return state; }
/* Encoding is <blockhdr> <varint-num-txs> <tx>... */ struct bitcoin_block *bitcoin_block_from_hex(const tal_t *ctx, const char *hex, size_t hexlen) { struct bitcoin_block *b; u8 *linear_tx; const u8 *p; size_t len, i, num; if (hexlen && hex[hexlen-1] == '\n') hexlen--; /* Set up the block for success. */ b = tal(ctx, struct bitcoin_block); /* De-hex the array. */ len = hex_data_size(hexlen); p = linear_tx = tal_arr(ctx, u8, len); if (!hex_decode(hex, hexlen, linear_tx, len)) return tal_free(b); pull(&p, &len, &b->hdr, sizeof(b->hdr)); num = pull_varint(&p, &len); b->tx = tal_arr(b, struct bitcoin_tx *, num); for (i = 0; i < num; i++) b->tx[i] = pull_bitcoin_tx(b->tx, &p, &len); /* We should end up not overrunning, nor have extra */ if (!p || len) return tal_free(b); tal_free(linear_tx); return b; }
struct bitcoin_tx *bitcoin_tx_from_hex(const tal_t *ctx, const char *hex, size_t hexlen) { const char *end; u8 *linear_tx; const u8 *p; struct bitcoin_tx *tx; size_t len; end = memchr(hex, '\n', hexlen); if (!end) end = hex + hexlen; len = hex_data_size(end - hex); p = linear_tx = tal_arr(ctx, u8, len); if (!hex_decode(hex, end - hex, linear_tx, len)) goto fail; tx = pull_bitcoin_tx(ctx, &p, &len); if (!tx) goto fail; if (len) goto fail_free_tx; tal_free(linear_tx); return tx; fail_free_tx: tal_free(tx); fail: tal_free(linear_tx); return NULL; }
int main(void) { int *p; char name[] = "test name"; plan_tests(6); p = tal(NULL, int); ok1(strcmp(tal_name(p), "int") == 0); tal_set_name(p, "some literal"); ok1(strcmp(tal_name(p), "some literal") == 0); tal_set_name(p, name); ok1(strcmp(tal_name(p), name) == 0); /* You can't reuse my pointer though! */ ok1(tal_name(p) != name); tal_set_name(p, "some other literal"); ok1(strcmp(tal_name(p), "some other literal") == 0); tal_free(p); p = tal_arr(NULL, int, 2); ok1(strcmp(tal_name(p), "int[]") == 0); tal_free(p); tal_cleanup(); return exit_status(); }
jsmntok_t *json_parse_input(const char *input, int len, bool *valid) { jsmn_parser parser; jsmntok_t *toks; jsmnerr_t ret; toks = tal_arr(input, jsmntok_t, 10); again: jsmn_init(&parser); ret = jsmn_parse(&parser, input, len, toks, tal_count(toks) - 1); switch (ret) { case JSMN_ERROR_INVAL: *valid = false; return tal_free(toks); case JSMN_ERROR_PART: *valid = true; return tal_free(toks); case JSMN_ERROR_NOMEM: tal_resize(&toks, tal_count(toks) * 2); goto again; } /* Cut to length and return. */ *valid = true; tal_resize(&toks, ret + 1); /* Make sure last one is always referencable. */ toks[ret].type = -1; toks[ret].start = toks[ret].end = toks[ret].size = 0; return toks; }
void command_fail(struct command *cmd, const char *fmt, ...) { char *quote, *error; struct json_connection *jcon = cmd->jcon; va_list ap; if (!jcon) { log_unusual(cmd->dstate->base_log, "Command failed after jcon close"); tal_free(cmd); return; } va_start(ap, fmt); error = tal_vfmt(cmd, fmt, ap); va_end(ap); log_debug(jcon->log, "Failing: %s", error); /* Remove " */ while ((quote = strchr(error, '"')) != NULL) *quote = '\''; /* Now surround in quotes. */ quote = tal_fmt(cmd, "\"%s\"", error); assert(jcon->current == cmd); json_result(jcon, cmd->id, "null", quote); jcon->current = tal_free(cmd); }
/* Returns leaks, and sets errs[] */ static char *analyze_output(const char *output, char **errs) { char *leaks = tal_strdup(output, ""); unsigned int i; char **lines = tal_strsplit(output, output, "\n", STR_EMPTY_OK); *errs = tal_strdup(output, ""); for (i = 0; i < tal_count(lines) - 1; i++) { unsigned int preflen = strspn(lines[i], "=0123456789"); char *prefix, **sublines; /* Ignore erased lines, or weird stuff. */ if (preflen == 0) continue; prefix = tal_strndup(output, lines[i], preflen); sublines = extract_matching(prefix, lines); leaks = tal_strcat(output, take(leaks), take(get_leaks(sublines, errs))); } if (!leaks[0]) { tal_free(leaks); leaks = NULL; } if (!(*errs)[0]) { tal_free(*errs); *errs = NULL; } return leaks; }
struct channel *new_initial_channel(const tal_t *ctx, const struct bitcoin_blkid *chain_hash, const struct bitcoin_txid *funding_txid, unsigned int funding_txout, u64 funding_satoshis, u64 local_msatoshi, u32 feerate_per_kw, const struct channel_config *local, const struct channel_config *remote, const struct basepoints *local_basepoints, const struct basepoints *remote_basepoints, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, enum side funder) { struct channel *channel = tal(ctx, struct channel); channel->funding_txid = *funding_txid; channel->funding_txout = funding_txout; if (funding_satoshis > UINT64_MAX / 1000) return tal_free(channel); channel->funding_msat = funding_satoshis * 1000; if (local_msatoshi > channel->funding_msat) return tal_free(channel); channel->funder = funder; channel->config[LOCAL] = local; channel->config[REMOTE] = remote; channel->funding_pubkey[LOCAL] = *local_funding_pubkey; channel->funding_pubkey[REMOTE] = *remote_funding_pubkey; channel->htlcs = NULL; channel->changes_pending[LOCAL] = channel->changes_pending[REMOTE] = false; channel->view[LOCAL].feerate_per_kw = channel->view[REMOTE].feerate_per_kw = feerate_per_kw; channel->view[LOCAL].owed_msat[LOCAL] = channel->view[REMOTE].owed_msat[LOCAL] = local_msatoshi; channel->view[REMOTE].owed_msat[REMOTE] = channel->view[LOCAL].owed_msat[REMOTE] = channel->funding_msat - local_msatoshi; channel->basepoints[LOCAL] = *local_basepoints; channel->basepoints[REMOTE] = *remote_basepoints; channel->commitment_number_obscurer = commit_number_obscurer(&channel->basepoints[funder].payment, &channel->basepoints[!funder].payment); channel->chainparams = chainparams_by_chainhash(chain_hash); if (channel->chainparams == NULL) return tal_free(channel); return channel; }
static struct io_plan *handshake_success(struct io_conn *conn, const struct pubkey *them, const struct wireaddr_internal *addr, const struct crypto_state *orig_cs, char **args) { u8 *msg; struct crypto_state cs = *orig_cs; u8 *localfeatures; if (initial_sync) { localfeatures = tal(conn, u8); localfeatures[0] = (1 << 3); } else localfeatures = NULL; msg = towire_init(NULL, NULL, localfeatures); sync_crypto_write(&cs, conn->fd, take(msg)); /* Ignore their init message. */ tal_free(sync_crypto_read(NULL, &cs, conn->fd)); /* Did they ask us to send any messages? Do so now. */ if (stream_stdin) { beint16_t be_inlen; while (read_all(STDIN_FILENO, &be_inlen, sizeof(be_inlen))) { u32 msglen = be16_to_cpu(be_inlen); u8 *msg = tal_arr(NULL, u8, msglen); if (!read_all(STDIN_FILENO, msg, msglen)) err(1, "Only read partial message"); sync_crypto_write(&cs, conn->fd, take(msg)); } } while (*args) { u8 *m = tal_hexdata(NULL, *args, strlen(*args)); if (!m) errx(1, "Invalid hexdata '%s'", *args); sync_crypto_write(&cs, conn->fd, take(m)); args++; } /* Now write out whatever we get. */ while ((msg = sync_crypto_read(NULL, &cs, conn->fd)) != NULL) { be16 len = cpu_to_be16(tal_bytelen(msg)); if (!write_all(STDOUT_FILENO, &len, sizeof(len)) || !write_all(STDOUT_FILENO, msg, tal_bytelen(msg))) err(1, "Writing out msg"); tal_free(msg); if (--max_messages == 0) exit(0); } err(1, "Reading msg"); }
static struct io_plan *read_json(struct io_conn *conn, struct json_connection *jcon) { jsmntok_t *toks; bool valid; log_io(jcon->log, true, jcon->buffer + jcon->used, jcon->len_read); /* Resize larger if we're full. */ jcon->used += jcon->len_read; if (jcon->used == tal_count(jcon->buffer)) tal_resize(&jcon->buffer, jcon->used * 2); again: toks = json_parse_input(jcon->buffer, jcon->used, &valid); if (!toks) { if (!valid) { log_unusual(jcon->dstate->base_log, "Invalid token in json input: '%.*s'", (int)jcon->used, jcon->buffer); return io_close(conn); } /* We need more. */ goto read_more; } /* Empty buffer? (eg. just whitespace). */ if (tal_count(toks) == 1) { jcon->used = 0; goto read_more; } parse_request(jcon, toks); /* Remove first {}. */ memmove(jcon->buffer, jcon->buffer + toks[0].end, tal_count(jcon->buffer) - toks[0].end); jcon->used -= toks[0].end; tal_free(toks); /* Need to wait for command to finish? */ if (jcon->current) { jcon->len_read = 0; return io_wait(conn, jcon, read_json, jcon); } /* See if we can parse the rest. */ goto again; read_more: tal_free(toks); return io_read_partial(conn, jcon->buffer + jcon->used, tal_count(jcon->buffer) - jcon->used, &jcon->len_read, read_json, jcon); }
int main(void) { char *path, *ctx = tal_strdup(NULL, "ctx"); plan_tests(26); path = path_basename(ctx, "/usr/lib"); ok1(streq(path, "lib")); ok1(tal_parent(path) == ctx); path = path_basename(ctx, "/usr/"); ok1(streq(path, "usr")); ok1(tal_parent(path) == ctx); path = path_basename(ctx, "/usr//"); ok1(streq(path, "usr")); ok1(tal_parent(path) == ctx); path = path_basename(ctx, "usr"); ok1(streq(path, "usr")); ok1(tal_parent(path) == ctx); path = path_basename(ctx, "/"); ok1(streq(path, "/")); ok1(tal_parent(path) == ctx); path = path_basename(ctx, "//"); ok1(streq(path, "/")); ok1(tal_parent(path) == ctx); path = path_basename(ctx, "."); ok1(streq(path, ".")); ok1(tal_parent(path) == ctx); path = path_basename(ctx, "./"); ok1(streq(path, ".")); ok1(tal_parent(path) == ctx); path = path_basename(ctx, ".."); ok1(streq(path, "..")); ok1(tal_parent(path) == ctx); path = path_basename(ctx, "../"); ok1(streq(path, "..")); ok1(tal_parent(path) == ctx); tal_free(ctx); ctx = tal_strdup(NULL, "ctx"); ok1(!tal_first(ctx)); /* Test take */ path = path_basename(ctx, take(tal_strdup(ctx, ".."))); ok1(streq(path, "..")); ok1(tal_parent(path) == ctx); ok1(tal_first(ctx) == path && !tal_next(ctx, path)); tal_free(path); ok1(path_basename(ctx, take(NULL)) == NULL); ok1(!tal_first(ctx)); tal_free(ctx); return exit_status(); }
int main(void) { char *parent, *c; plan_tests(21); /* We can take NULL. */ ok1(take(NULL) == NULL); ok1(is_taken(NULL)); ok1(taken(NULL)); /* Undoes take() */ ok1(!is_taken(NULL)); ok1(!taken(NULL)); parent = tal(NULL, char); ok1(parent); ok1(take(parent) == parent); ok1(is_taken(parent)); ok1(taken(parent)); /* Undoes take() */ ok1(!is_taken(parent)); ok1(!taken(parent)); c = tal(parent, char); *c = 'h'; c = tal_dup(parent, char, take(c), 1, 0); ok1(c[0] == 'h'); ok1(tal_parent(c) == parent); c = tal_dup(parent, char, take(c), 1, 2); ok1(c[0] == 'h'); strcpy(c, "hi"); ok1(tal_parent(c) == parent); /* dup must reparent child. */ c = tal_dup(NULL, char, take(c), 1, 0); ok1(c[0] == 'h'); ok1(tal_parent(c) == NULL); /* No leftover allocations. */ tal_free(c); ok1(talloc_total_blocks(parent) == 1); tal_free(parent); ok1(!taken_any()); /* NULL pass-through. */ c = NULL; ok1(tal_dup(NULL, char, take(c), 5, 5) == NULL); ok1(!taken_any()); return exit_status(); }
void command_success(struct command *cmd, struct json_result *result) { struct json_connection *jcon = cmd->jcon; if (!jcon) { log_unusual(cmd->dstate->base_log, "Command returned result after jcon close"); tal_free(cmd); return; } assert(jcon->current == cmd); json_result(jcon, cmd->id, json_result_string(result), "null"); jcon->current = tal_free(cmd); }
/* Simple LL(1) parser, inspired by Tridge's genstruct.pl. */ struct cdump_definitions *cdump_extract(const tal_t *ctx, const char *code, char **complaints) { struct parse_state ps; const struct token *toks; ps.defs = tal(ctx, struct cdump_definitions); ps.complaints = tal_strdup(ctx, ""); ps.code = code; strmap_init(&ps.defs->enums); strmap_init(&ps.defs->structs); strmap_init(&ps.defs->unions); tal_add_destructor(ps.defs, destroy_definitions); toks = ps.toks = tokenize(ps.defs, code); while (tok_peek(&ps.toks)) { if (tok_take_if(&ps.toks, "struct")) { if (!tok_take_conglom(&ps, CDUMP_STRUCT)) goto fail; } else if (tok_take_if(&ps.toks, "union")) { if (!tok_take_conglom(&ps, CDUMP_UNION)) goto fail; } else if (tok_take_if(&ps.toks, "enum")) { if (!tok_take_enum(&ps)) goto fail; } else tok_take_unknown_statement(&ps); } /* Now, remove any undefined types! */ remove_undefined(&ps.defs->enums); remove_undefined(&ps.defs->structs); remove_undefined(&ps.defs->unions); tal_free(toks); out: if (streq(ps.complaints, "")) ps.complaints = tal_free(ps.complaints); if (complaints) *complaints = ps.complaints; else tal_free(ps.complaints); return ps.defs; fail: ps.defs = tal_free(ps.defs); goto out; }
int main(void) { char cwd[1024], *path, *path2, *ctx = tal_strdup(NULL, "ctx"); plan_tests(15); if (!getcwd(cwd, sizeof(cwd))) abort(); unlink("run-canon-link"); rmdir("run-canon-foo"); if (mkdir("run-canon-foo", 0700) != 0) abort(); if (symlink("run-canon-foo", "run-canon-link") != 0) abort(); path = path_canon(ctx, "run-canon-foo"); ok1(tal_parent(path) == ctx); ok1(strends(path, "run-canon-foo")); ok1(strstarts(path, cwd)); ok1(path[strlen(cwd)] == PATH_SEP); ok1(strlen(path) == strlen(cwd) + 1 + strlen("run-canon-foo")); tal_free(path); ok1(!path_canon(ctx, take(NULL))); ok1(tal_first(ctx) == NULL); /* Test take doesn't leak. */ ok1(tal_first(ctx) == NULL); path = path_canon(ctx, take(tal_strdup(ctx, "run-canon-foo"))); ok1(strends(path, "run-canon-foo")); ok1(strstarts(path, cwd)); ok1(path[strlen(cwd)] == PATH_SEP); ok1(strlen(path) == strlen(cwd) + 1 + strlen("run-canon-foo")); ok1(tal_first(ctx) == path && tal_next(path) == NULL); path2 = path_canon(ctx, "run-canon-link"); ok1(streq(path2, path)); unlink("run-canon-link"); if (symlink(".", "run-canon-link") != 0) abort(); path = path_canon(ctx, "run-canon-link"); ok1(streq(path, cwd)); tal_free(ctx); return exit_status(); }
tx *get_tx(const bitcoin_txid &txid, bool must_exist) { char filename[sizeof("txcache/01234567890123456789012345678901234567890123456789012345678901234567")] = "txcache/"; char *txstring; const u8 *txbytes; u8 *bytes; size_t len; u64 fee; tx *t; txstring = filename + strlen("txcache/"); if (!hex_encode(txid.shad.sha.u.u8, sizeof(txid.shad.sha.u.u8), txstring, sizeof(filename) - strlen("txcache/"))) throw std::logic_error("txid doesn't fit in filename"); txbytes = bytes = (u8 *)grab_file(NULL, filename); if (!txbytes) { if (must_exist) errx(1, "Could not find tx %s", txstring); return NULL; } len = tal_count(txbytes)-1; if (len < 8) errx(1, "Truncated %s", filename); memcpy(&fee, txbytes, 8); txbytes += 8; len -= 8; t = new tx(fee, new bitcoin_tx(&txbytes, &len)); assert(t->txid == txid); tal_free(bytes); return t; }
/* Wrap (and own!) member inside Pkt */ static Pkt *make_pkt(const tal_t *ctx, Pkt__PktCase type, const void *msg) { Pkt *pkt = tal(ctx, Pkt); pkt__init(pkt); pkt->pkt_case = type; /* This is a union, so doesn't matter which we assign. */ pkt->error = (Error *)tal_steal(pkt, msg); /* This makes sure all packets are valid. */ #ifndef NDEBUG { size_t len; u8 *packed; Pkt *cpy; len = pkt__get_packed_size(pkt); packed = tal_arr(pkt, u8, len); pkt__pack(pkt, packed); cpy = pkt__unpack(NULL, len, memcheck(packed, len)); assert(cpy); pkt__free_unpacked(cpy, NULL); tal_free(packed); } #endif return pkt; }
int main(void) { int *a; const int arr[] = { 1, 2 }; plan_tests(13); a = tal_arrz(NULL, int, 1); ok1(a); ok1(tal_expand(&a, arr, 2)); ok1(tal_count(a) == 3); ok1(a[0] == 0); ok1(a[1] == 1); ok1(a[2] == 2); ok1(tal_expand(&a, take(tal_arrz(NULL, int, 1)), 1)); ok1(tal_count(a) == 4); ok1(a[0] == 0); ok1(a[1] == 1); ok1(a[2] == 2); ok1(a[3] == 0); ok1(tal_first(NULL) == a && !tal_next(a) && !tal_first(a)); tal_free(a); tal_cleanup(); return exit_status(); }
static void log_to_file(const char *prefix, enum log_level level, bool continued, const struct timeabs *time, const char *str, const u8 *io, size_t io_len, FILE *logf) { char iso8601_msec_fmt[sizeof("YYYY-mm-ddTHH:MM:SS.%03dZ")]; strftime(iso8601_msec_fmt, sizeof(iso8601_msec_fmt), "%FT%T.%%03dZ", gmtime(&time->ts.tv_sec)); char iso8601_s[sizeof("YYYY-mm-ddTHH:MM:SS.nnnZ")]; snprintf(iso8601_s, sizeof(iso8601_s), iso8601_msec_fmt, (int) time->ts.tv_nsec / 1000000); if (level == LOG_IO_IN || level == LOG_IO_OUT) { const char *dir = level == LOG_IO_IN ? "[IN]" : "[OUT]"; char *hex = tal_hexstr(NULL, io, io_len); fprintf(logf, "%s %s%s%s %s\n", iso8601_s, prefix, str, dir, hex); tal_free(hex); } else if (!continued) { fprintf(logf, "%s %s %s\n", iso8601_s, prefix, str); } else { fprintf(logf, "%s %s \t%s\n", iso8601_s, prefix, str); } fflush(logf); }
int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); OpenAnchorScriptsigs *s; struct pkt *pkt; err_set_progname(argv[0]); opt_register_noarg("--help|-h", opt_usage_and_exit, "<open-anchor-sig-file>\n" "Create LeakAnchorSigsAndPretendWeDidnt to stdout", "Print this message."); opt_register_version(); opt_parse(&argc, argv, opt_log_stderr_exit); if (argc != 2) opt_usage_exit_fail("Expected 1 argument"); s = pkt_from_file(argv[1], PKT__PKT_OPEN_ANCHOR_SCRIPTSIGS) ->open_anchor_scriptsigs; pkt = leak_anchor_sigs_and_pretend_we_didnt_pkt(ctx, s); if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) err(1, "Writing out packet"); tal_free(ctx); return 0; }
int main(void) { char cwd[1024], *path, *ctx = tal_strdup(NULL, "ctx"); plan_tests(6); if (!getcwd(cwd, sizeof(cwd))) abort(); unlink("run-is_dir-dir-link"); unlink("run-is_dir-file-link"); unlink("run-is_dir-dir/file"); rmdir("run-is_dir-dir"); if (mkdir("run-is_dir-dir", 0700) != 0) abort(); if (symlink("run-is_dir-dir", "run-is_dir-dir-link") != 0) abort(); if (symlink("run-is_dir-dir/file", "run-is_dir-file-link") != 0) abort(); close(open("run-is_dir-dir/file", O_WRONLY|O_CREAT, 0600)); ok1(path_is_dir("run-is_dir-dir-link")); ok1(!path_is_dir("run-is_dir-file-link")); ok1(!path_is_dir("run-is_dir-dir/file")); ok1(path_is_dir("run-is_dir-dir")); path = path_join(ctx, cwd, "run-is_dir-dir/file"); ok1(!path_is_dir(path)); ok1(path_is_dir(cwd)); tal_free(ctx); return exit_status(); }
int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); struct bitcoin_tx *tx; struct sha256_double txid; char str[hex_str_size(sizeof(txid))]; err_set_progname(argv[0]); /* FIXME: Take update.pbs to adjust channel */ opt_register_noarg("--help|-h", opt_usage_and_exit, "<tx>\n" "Print txid of the transaction in the file", "Print this message."); opt_register_version(); opt_parse(&argc, argv, opt_log_stderr_exit); if (argc != 2) opt_usage_exit_fail("Expected 1 argument"); tx = bitcoin_tx_from_file(ctx, argv[1]); bitcoin_txid(tx, &txid); if (!bitcoin_txid_to_hex(&txid, str, sizeof(str))) abort(); /* Print it out. */ if (!write_all(STDOUT_FILENO, str, strlen(str))) err(1, "Writing out txid"); tal_free(ctx); return 0; }
static void test_full(void) { struct full_graphr fgr; int i, j; full_graphr_init(&fgr, FULL_LEN); for (i = 1; i <= FULL_LEN; i++) { struct agar_state *sr; ok1(sr = agar_dijkstra_new(NULL, &fgr.gr, int2ptr(i))); for (j = 1; j <= FULL_LEN; j++) { aga_icost_t cost; const void *node, *edge; ok1(agar_dijkstra_path(sr, int2ptr(j), &cost, &node, &edge)); if (i == j) { ok1(cost == 0); } else { ok1(cost == 1); ok1(node == int2ptr(i)); ok1(edge == int2ptr(j)); } } tal_free(sr); } }
void publish_complaint(struct state *state, struct block *block, const void *complaint, struct peer *origin) { /* Don't complaint storm. */ if (block->complaint) { tal_free(complaint); return; } /* FIXME: Save complaint to blockfile! */ /* If it's invalid, so are any descendents. */ complaint_on_all(state, block, complaint); /* We have dumped all the txs from those blocks into pending. */ recheck_pending_txs(state); /* Recalc everything. Slow, but should be rare. */ update_block_ptrs_invalidated(state, block); /* Tell everyone (except origin!) */ broadcast_to_peers(state, complaint, origin); }
static struct io_plan *write_json(struct io_conn *conn, struct json_connection *jcon) { struct json_output *out; out = list_pop(&jcon->output, struct json_output, list); if (!out) { if (jcon->stop) { log_unusual(jcon->log, "JSON-RPC shutdown"); /* Return us to toplevel lightningd.c */ io_break(jcon->dstate); return io_close(conn); } /* Reader can go again now. */ io_wake(jcon); return io_out_wait(conn, jcon, write_json, jcon); } jcon->outbuf = tal_steal(jcon, out->json); tal_free(out); log_io(jcon->log, false, jcon->outbuf, strlen(jcon->outbuf)); return io_write(conn, jcon->outbuf, strlen(jcon->outbuf), write_json, jcon); }
struct bitcoin_tx *create_close_tx(const tal_t *ctx, const u8 *our_script, const u8 *their_script, const struct bitcoin_txid *anchor_txid, unsigned int anchor_index, struct amount_sat funding, struct amount_sat to_us, struct amount_sat to_them, struct amount_sat dust_limit) { struct bitcoin_tx *tx; size_t num_outputs = 0; struct amount_sat total_out; u8 *script; assert(amount_sat_add(&total_out, to_us, to_them)); assert(amount_sat_less_eq(total_out, funding)); /* BOLT #3: * * ## Closing Transaction * * Note that there are two possible variants for each node. * * * version: 2 * * locktime: 0 * * txin count: 1 */ /* Now create close tx: one input, two outputs. */ tx = bitcoin_tx(ctx, 1, 2); /* Our input spends the anchor tx output. */ bitcoin_tx_add_input(tx, anchor_txid, anchor_index, BITCOIN_TX_DEFAULT_SEQUENCE, &funding, NULL); if (amount_sat_greater_eq(to_us, dust_limit)) { script = tal_dup_arr(tx, u8, our_script, tal_count(our_script), 0); /* One output is to us. */ bitcoin_tx_add_output(tx, script, &to_us); num_outputs++; } if (amount_sat_greater_eq(to_them, dust_limit)) { script = tal_dup_arr(tx, u8, their_script, tal_count(their_script), 0); /* Other output is to them. */ bitcoin_tx_add_output(tx, script, &to_them); num_outputs++; } /* Can't have no outputs at all! */ if (num_outputs == 0) return tal_free(tx); permute_outputs(tx, NULL, NULL); assert(bitcoin_tx_check(tx)); return tx; }
char *short_channel_id_dir_to_str(const tal_t *ctx, const struct short_channel_id_dir *scidd) { char *str, *scidstr = short_channel_id_to_str(NULL, &scidd->scid); str = tal_fmt(ctx, "%s/%u", scidstr, scidd->dir); tal_free(scidstr); return str; }
struct secret *hsm_do_ecdh(const tal_t *ctx, const struct pubkey *point) { struct secret *ss = tal(ctx, struct secret); if (secp256k1_ecdh(secp256k1_ctx, ss->data, &point->pubkey, notsosecret.data, NULL, NULL) != 1) return tal_free(ss); return ss; }
void json_add_hex(char **result, const char *fieldname, const void *data, size_t len) { char *hex = to_hex(*result, data, len); json_add_string(result, fieldname, hex); tal_free(hex); }
void json_add_address(char **result, const char *fieldname, bool test_net, const struct protocol_address *addr) { char *str = pettycoin_to_base58(*result, test_net, addr, false); json_add_string(result, fieldname, str); tal_free(str); }