int main(int argc, char *argv[]) { int fd, i, off; const char *method; char *cmd, *resp, *idstr, *rpc_filename; char *result_end; struct sockaddr_un addr; jsmntok_t *toks; const jsmntok_t *result, *error, *id; char *lightning_dir; const tal_t *ctx = tal(NULL, char); size_t num_opens, num_closes; bool valid; err_set_progname(argv[0]); opt_set_alloc(opt_allocfn, tal_reallocfn, tal_freefn); configdir_register_opts(ctx, &lightning_dir, &rpc_filename); opt_register_noarg("--help|-h", opt_usage_and_exit, "<command> [<params>...]", "Show this message"); opt_register_version(); opt_early_parse(argc, argv, opt_log_stderr_exit); opt_parse(&argc, argv, opt_log_stderr_exit); method = argv[1]; if (!method) errx(ERROR_USAGE, "Need at least one argument\n%s", opt_usage(argv[0], NULL)); if (chdir(lightning_dir) != 0) err(ERROR_TALKING_TO_LIGHTNINGD, "Moving into '%s'", lightning_dir); fd = socket(AF_UNIX, SOCK_STREAM, 0); if (strlen(rpc_filename) + 1 > sizeof(addr.sun_path)) errx(ERROR_USAGE, "rpc filename '%s' too long", rpc_filename); strcpy(addr.sun_path, rpc_filename); addr.sun_family = AF_UNIX; if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) err(ERROR_TALKING_TO_LIGHTNINGD, "Connecting to '%s'", rpc_filename); idstr = tal_fmt(ctx, "lightning-cli-%i", getpid()); cmd = tal_fmt(ctx, "{ \"method\" : \"%s\", \"id\" : \"%s\", \"params\" : [ ", method, idstr); for (i = 2; i < argc; i++) { /* Numbers are left unquoted, and quoted things left alone. */ if (strspn(argv[i], "0123456789") == strlen(argv[i]) || argv[i][0] == '"') tal_append_fmt(&cmd, "%s", argv[i]); else tal_append_fmt(&cmd, "\"%s\"", argv[i]); if (i != argc - 1) tal_append_fmt(&cmd, ", "); } tal_append_fmt(&cmd, "] }"); if (!write_all(fd, cmd, strlen(cmd))) err(ERROR_TALKING_TO_LIGHTNINGD, "Writing command"); resp = tal_arr(cmd, char, 100); off = 0; num_opens = num_closes = 0; while ((i = read(fd, resp + off, tal_count(resp) - 1 - off)) > 0) { resp[off + i] = '\0'; num_opens += strcount(resp + off, "{"); num_closes += strcount(resp + off, "}"); off += i; if (off == tal_count(resp) - 1) tal_resize(&resp, tal_count(resp) * 2); /* parsing huge outputs is slow: do quick check first. */ if (num_opens == num_closes && strstr(resp, "\"result\"")) break; } if (i < 0) err(ERROR_TALKING_TO_LIGHTNINGD, "reading response"); /* Parsing huge results is too slow, so hack fastpath common case */ result_end = tal_fmt(ctx, ", \"error\" : null, \"id\" : \"%s\" }\n", idstr); if (strstarts(resp, "{ \"result\" : ") && strends(resp, result_end)) { /* Result is OK, so dump it */ resp += strlen("{ \"result\" : "); printf("%.*s\n", (int)(strlen(resp) - strlen(result_end)), resp); tal_free(ctx); return 0; } toks = json_parse_input(resp, off, &valid); if (!toks || !valid) errx(ERROR_TALKING_TO_LIGHTNINGD, "Malformed response '%s'", resp); if (toks->type != JSMN_OBJECT) errx(ERROR_TALKING_TO_LIGHTNINGD, "Non-object response '%s'", resp); result = json_get_member(resp, toks, "result"); if (!result) errx(ERROR_TALKING_TO_LIGHTNINGD, "Missing 'result' in response '%s'", resp); error = json_get_member(resp, toks, "error"); if (!error) errx(ERROR_TALKING_TO_LIGHTNINGD, "Missing 'error' in response '%s'", resp); id = json_get_member(resp, toks, "id"); if (!id) errx(ERROR_TALKING_TO_LIGHTNINGD, "Missing 'id' in response '%s'", resp); if (!json_tok_streq(resp, id, idstr)) errx(ERROR_TALKING_TO_LIGHTNINGD, "Incorrect 'id' in response: %.*s", json_tok_len(id), json_tok_contents(resp, id)); if (json_tok_is_null(resp, error)) { printf("%.*s\n", json_tok_len(result), json_tok_contents(resp, result)); tal_free(ctx); return 0; } printf("%.*s\n", json_tok_len(error), json_tok_contents(resp, error)); tal_free(ctx); return 1; }
static enum channel_add_err add_htlc(struct channel *channel, enum htlc_state state, u64 id, struct amount_msat amount, u32 cltv_expiry, const struct sha256 *payment_hash, const u8 routing[TOTAL_PACKET_SIZE], struct htlc **htlcp, bool enforce_aggregate_limits) { struct htlc *htlc, *old; struct amount_msat msat_in_htlcs, committed_msat, adding_msat, removing_msat; struct amount_sat fee; enum side sender = htlc_state_owner(state), recipient = !sender; const struct htlc **committed, **adding, **removing; const struct channel_view *view; bool ok; size_t i; htlc = tal(tmpctx, struct htlc); htlc->id = id; htlc->amount = amount; htlc->state = state; htlc->shared_secret = NULL; /* FIXME: Change expiry to simple u32 */ /* BOLT #2: * * A receiving node: *... * - if sending node sets `cltv_expiry` to greater or equal to * 500000000: * - SHOULD fail the channel. */ if (!blocks_to_abs_locktime(cltv_expiry, &htlc->expiry)) { return CHANNEL_ERR_INVALID_EXPIRY; } htlc->rhash = *payment_hash; htlc->fail = NULL; htlc->failcode = 0; htlc->failed_scid = NULL; htlc->r = NULL; htlc->routing = tal_dup_arr(htlc, u8, routing, TOTAL_PACKET_SIZE, 0); old = htlc_get(channel->htlcs, htlc->id, htlc_owner(htlc)); if (old) { if (old->state != htlc->state || !amount_msat_eq(old->amount, htlc->amount) || old->expiry.locktime != htlc->expiry.locktime || !sha256_eq(&old->rhash, &htlc->rhash)) return CHANNEL_ERR_DUPLICATE_ID_DIFFERENT; else return CHANNEL_ERR_DUPLICATE; } /* We're always considering the recipient's view of the channel here */ view = &channel->view[recipient]; /* BOLT #2: * * A receiving node: * - receiving an `amount_msat` equal to 0, OR less than its own * `htlc_minimum_msat`: * - SHOULD fail the channel. */ if (amount_msat_eq(htlc->amount, AMOUNT_MSAT(0))) { return CHANNEL_ERR_HTLC_BELOW_MINIMUM; } if (amount_msat_less(htlc->amount, channel->config[recipient].htlc_minimum)) { return CHANNEL_ERR_HTLC_BELOW_MINIMUM; } /* BOLT #2: * * - for channels with `chain_hash` identifying the Bitcoin blockchain: * - MUST set the four most significant bytes of `amount_msat` to 0. */ if (amount_msat_greater(htlc->amount, channel->chainparams->max_payment)) { return CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED; } /* Figure out what receiver will already be committed to. */ gather_htlcs(tmpctx, channel, recipient, &committed, &removing, &adding); htlc_arr_append(&adding, htlc); /* BOLT #2: * * - if a sending node adds more than receiver `max_accepted_htlcs` * HTLCs to its local commitment transaction... * - SHOULD fail the channel. */ if (tal_count(committed) - tal_count(removing) + tal_count(adding) > channel->config[recipient].max_accepted_htlcs) { return CHANNEL_ERR_TOO_MANY_HTLCS; } /* These cannot overflow with HTLC amount limitations, but * maybe adding could later if they try to add a maximal HTLC. */ if (!sum_offered_msatoshis(&committed_msat, committed, htlc_owner(htlc)) || !sum_offered_msatoshis(&removing_msat, removing, htlc_owner(htlc)) || !sum_offered_msatoshis(&adding_msat, adding, htlc_owner(htlc))) { return CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED; } if (!amount_msat_add(&msat_in_htlcs, committed_msat, adding_msat) || !amount_msat_sub(&msat_in_htlcs, msat_in_htlcs, removing_msat)) { return CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED; } /* BOLT #2: * * - if a sending node... adds more than receiver * `max_htlc_value_in_flight_msat` worth of offered HTLCs to its * local commitment transaction: * - SHOULD fail the channel. */ /* We don't enforce this for channel_force_htlcs: some might already * be fulfilled/failed */ if (enforce_aggregate_limits && amount_msat_greater(msat_in_htlcs, channel->config[recipient].max_htlc_value_in_flight)) { return CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED; } /* BOLT #2: * * A receiving node: *... * - receiving an `amount_msat` that the sending node cannot afford at * the current `feerate_per_kw` (while maintaining its channel * reserve): * - SHOULD fail the channel. */ if (channel->funder == htlc_owner(htlc)) { u32 feerate = view->feerate_per_kw; struct amount_sat dust_limit = channel->config[recipient].dust_limit; size_t untrimmed; untrimmed = commit_tx_num_untrimmed(committed, feerate, dust_limit, recipient) + commit_tx_num_untrimmed(adding, feerate, dust_limit, recipient) - commit_tx_num_untrimmed(removing, feerate, dust_limit, recipient); fee = commit_tx_base_fee(feerate, untrimmed); } else fee = AMOUNT_SAT(0); assert((s64)fee.satoshis >= 0); /* Raw: explicit signedness test */ if (enforce_aggregate_limits) { /* Figure out what balance sender would have after applying all * pending changes. */ struct amount_msat balance = view->owed[sender]; /* This is a little subtle: * * The change is being applied to the receiver but it will * come back to the sender after revoke_and_ack. So the check * here is that the balance to the sender doesn't go below the * sender's reserve. */ const struct amount_sat reserve = channel->config[!sender].channel_reserve; assert(amount_msat_greater_eq(balance, AMOUNT_MSAT(0))); ok = true; for (i = 0; i < tal_count(removing); i++) ok &= balance_remove_htlc(&balance, removing[i], sender); assert(amount_msat_greater_eq(balance, AMOUNT_MSAT(0))); for (i = 0; i < tal_count(adding); i++) ok &= balance_add_htlc(&balance, adding[i], sender); /* Overflow shouldn't happen, but if it does, complain */ if (!ok) { status_broken("Failed to add %zu remove %zu htlcs", tal_count(adding), tal_count(removing)); return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; } if (!amount_msat_sub_sat(&balance, balance, fee)) { status_trace("Cannot afford fee %s with balance %s", type_to_string(tmpctx, struct amount_sat, &fee), type_to_string(tmpctx, struct amount_msat, &balance)); return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; } if (!amount_msat_greater_eq_sat(balance, reserve)) { status_trace("Cannot afford fee %s: would make balance %s" " below reserve %s", type_to_string(tmpctx, struct amount_sat, &fee), type_to_string(tmpctx, struct amount_msat, &balance), type_to_string(tmpctx, struct amount_sat, &reserve)); return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; }
/* * We add changes to both our staging cstate (as they did when they sent * it) and theirs (as they will when we ack it). */ Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt) { const UpdateAddHtlc *u = pkt->update_add_htlc; struct sha256 rhash; struct abs_locktime expiry; struct htlc *htlc; union htlc_staging stage; /* BOLT #2: * * `amount_msat` MUST BE greater than 0. */ if (u->amount_msat == 0) return pkt_err(peer, "Invalid amount_msat"); proto_to_sha256(u->r_hash, &rhash); if (!proto_to_abs_locktime(u->expiry, &expiry)) return pkt_err(peer, "Invalid HTLC expiry"); if (abs_locktime_is_seconds(&expiry)) return pkt_err(peer, "HTLC expiry in seconds not supported!"); /* BOLT #2: * * A node MUST NOT add a HTLC if it would result in it * offering more than 300 HTLCs in the remote commitment transaction. */ if (tal_count(peer->remote.staging_cstate->side[THEIRS].htlcs) == 300) return pkt_err(peer, "Too many HTLCs"); /* BOLT #2: * * A node MUST set `id` to a unique identifier for this HTLC * amongst all past or future `update_add_htlc` messages. */ /* Note that it's not *our* problem if they do this, it's * theirs (future confusion). Nonetheless, we detect and * error for them. */ if (htlc_map_get(&peer->remote.htlcs, u->id)) return pkt_err(peer, "HTLC id %"PRIu64" clashes for you", u->id); /* BOLT #2: * * ...and the receiving node MUST add the HTLC addition to the * unacked changeset for its local commitment. */ htlc = peer_new_htlc(peer, u->id, u->amount_msat, &rhash, abs_locktime_to_blocks(&expiry), u->route->info.data, u->route->info.len, NULL, THEIRS); /* BOLT #2: * * A node MUST NOT offer `amount_msat` it cannot pay for in * the remote commitment transaction at the current `fee_rate` (see * "Fee Calculation" ). A node SHOULD fail the connection if * this occurs. */ if (!cstate_add_htlc(peer->local.staging_cstate, htlc, THEIRS)) { tal_free(htlc); return pkt_err(peer, "Cannot afford %"PRIu64" milli-satoshis" " in our commitment tx", u->amount_msat); } stage.add.add = HTLC_ADD; stage.add.htlc = htlc; add_unacked(&peer->local, &stage); return NULL; }
int main(int argc, char *argv[]) { u8 version; beint16_t be_inlen; struct amount_sat sat; bool verbose = false; char *infile = NULL, *outfile = NULL, *scidfile = NULL, *csat = NULL; int infd = 0, outfd; FILE * scidfd; struct scidsat * scids = NULL; unsigned max = -1U; setup_locale(); opt_register_noarg("--verbose|-v", opt_set_bool, &verbose, "Print progress to stderr"); opt_register_arg("--output|-o", opt_set_charp, NULL, &outfile, "Send output to this file instead of stdout"); opt_register_arg("--input|-i", opt_set_charp, NULL, &infile, "Read input from this file instead of stdin"); opt_register_arg("--scidfile", opt_set_charp, NULL, &scidfile, "Input for 'scid, satshis' csv"); opt_register_arg("--sat", opt_set_charp, NULL, &csat, "default satoshi value if --scidfile flag not present"); opt_register_arg("--max", opt_set_uintval, opt_show_uintval, &max, "maximum number of messages to read"); opt_register_noarg("--help|-h", opt_usage_and_exit, "Create gossip store, from be16 / input messages", "Print this message."); opt_parse(&argc, argv, opt_log_stderr_exit); if (scidfile) { scidfd = fopen(scidfile, "r"); if (scidfd < 0) err(1, "opening %s", scidfile); scids = load_scid_file(scidfd); fclose(scidfd); } else if (csat) { if (!parse_amount_sat(&sat, csat, strlen(csat))) { errx(1, "Invalid satoshi amount %s", csat); } } else { err(1, "must contain either --sat xor --scidfile"); } if (infile) { infd = open(infile, O_RDONLY); if (infd < 0) err(1, "opening %s", infile); } if (outfile) { outfd = open(outfile, O_WRONLY|O_TRUNC|O_CREAT, 0666); if (outfd < 0) err(1, "opening %s", outfile); } else outfd = STDOUT_FILENO; version = GOSSIP_STORE_VERSION; if (!write_all(outfd, &version, sizeof(version))) err(1, "Writing version"); int scidi = 0; int channels = 0; int nodes = 0; int updates = 0; while (read_all(infd, &be_inlen, sizeof(be_inlen))) { u32 msglen = be16_to_cpu(be_inlen); u8 *inmsg = tal_arr(NULL, u8, msglen), *outmsg; beint32_t be_outlen; beint32_t becsum; if (!read_all(infd, inmsg, msglen)) err(1, "Only read partial message"); switch (fromwire_peektype(inmsg)) { case WIRE_CHANNEL_ANNOUNCEMENT: if (scids) { sat = scids[scidi].sat; scidi += 1; } channels += 1; outmsg = towire_gossip_store_channel_announcement(inmsg, inmsg, sat); break; case WIRE_CHANNEL_UPDATE: outmsg = towire_gossip_store_channel_update(inmsg, inmsg); updates += 1; break; case WIRE_NODE_ANNOUNCEMENT: outmsg = towire_gossip_store_node_announcement(inmsg, inmsg); nodes += 1; break; default: warnx("Unknown message %u (%s)", fromwire_peektype(inmsg), wire_type_name(fromwire_peektype(inmsg))); tal_free(inmsg); continue; } if (verbose) fprintf(stderr, "%s->%s\n", wire_type_name(fromwire_peektype(inmsg)), gossip_store_type_name(fromwire_peektype(outmsg))); becsum = cpu_to_be32(crc32c(0, outmsg, tal_count(outmsg))); be_outlen = cpu_to_be32(tal_count(outmsg)); if (!write_all(outfd, &be_outlen, sizeof(be_outlen)) || !write_all(outfd, &becsum, sizeof(becsum)) || !write_all(outfd, outmsg, tal_count(outmsg))) { exit(1); } tal_free(inmsg); if (--max == 0) break; } fprintf(stderr, "channels %d, updates %d, nodes %d\n", channels, updates, nodes); free(scids); return 0; }
int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); OpenChannel *o1, *o2; struct bitcoin_tx *anchor, *close_tx; struct sha256_double anchor_txid; struct bitcoin_signature sig1, sig2; struct pubkey pubkey1, pubkey2; u8 *redeemscript, *tx_arr; char *tx_hex; CloseChannel *close; CloseChannelComplete *closecomplete; size_t i; int64_t delta; err_set_progname(argv[0]); /* FIXME: Take update.pbs to adjust channel */ opt_register_noarg("--help|-h", opt_usage_and_exit, "<anchor-tx> <open-channel-file1> <open-channel-file2> <close-protobuf> <close-complete-protobuf> [update-protobuf]...\n" "Create the close transaction from the signatures", "Print this message."); opt_parse(&argc, argv, opt_log_stderr_exit); if (argc < 6) opt_usage_exit_fail("Expected 5+ arguments"); anchor = bitcoin_tx_from_file(ctx, argv[1]); o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; close = pkt_from_file(argv[4], PKT__PKT_CLOSE)->close; closecomplete = pkt_from_file(argv[5], PKT__PKT_CLOSE_COMPLETE)->close_complete; bitcoin_txid(anchor, &anchor_txid); /* Pubkeys well-formed? */ if (!proto_to_pubkey(o1->anchor->pubkey, &pubkey1)) errx(1, "Invalid anchor-1 key"); if (!proto_to_pubkey(o2->anchor->pubkey, &pubkey2)) errx(1, "Invalid anchor-2 key"); /* Get delta by accumulting all the updates. */ delta = 0; for (i = 6; i < argc; i++) { Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update; delta += u->delta; } /* This is what the anchor pays to; figure out which output. */ redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); /* Now create the close tx to spend 2/2 output of anchor. */ close_tx = create_close_tx(ctx, o1, o2, delta, &anchor_txid, find_p2sh_out(anchor, redeemscript)); /* Signatures well-formed? */ sig1.stype = sig2.stype = SIGHASH_ALL; if (!proto_to_signature(close->sig, &sig1.sig)) errx(1, "Invalid close-packet"); if (!proto_to_signature(closecomplete->sig, &sig2.sig)) errx(1, "Invalid closecomplete-packet"); /* Combined signatures must validate correctly. */ if (!check_2of2_sig(close_tx, 0, redeemscript, tal_count(redeemscript), &pubkey1, &pubkey2, &sig1, &sig2)) errx(1, "Signature failed"); /* Create p2sh input for close_tx */ close_tx->input[0].script = scriptsig_p2sh_2of2(close_tx, &sig1, &sig2, &pubkey1, &pubkey2); close_tx->input[0].script_length = tal_count(close_tx->input[0].script); /* Print it out in hex. */ tx_arr = linearize_tx(ctx, close_tx); tx_hex = tal_arr(tx_arr, char, hex_str_size(tal_count(tx_arr))); hex_encode(tx_arr, tal_count(tx_arr), tx_hex, tal_count(tx_hex)); if (!write_all(STDOUT_FILENO, tx_hex, strlen(tx_hex))) err(1, "Writing out transaction"); tal_free(ctx); return 0; }
int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); struct sha256 seed, revocation_hash, their_rhash; OpenChannel *o1, *o2; OpenAnchor *a; struct bitcoin_tx *commit; struct pkt *pkt; struct bitcoin_signature sig; struct privkey privkey; bool testnet; size_t num_updates; struct pubkey pubkey1, pubkey2; u8 *redeemscript; struct channel_state *cstate; err_set_progname(argv[0]); opt_register_noarg("--help|-h", opt_usage_and_exit, "<seed> <open-channel-file1> <open-channel-file2> <open-anchor-file> <commit-privkey> <all-updates...>\n" "Accept a new update message", "Print this message."); opt_register_version(); opt_parse(&argc, argv, opt_log_stderr_exit); if (argc < 7) opt_usage_exit_fail("Expected 6+ arguments"); if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; a = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; if (!key_from_base58(argv[5], strlen(argv[5]), &testnet, &privkey, &pubkey1)) errx(1, "Invalid private key '%s'", argv[5]); if (!testnet) errx(1, "Private key '%s' not on testnet!", argv[5]); /* Figure out cumulative delta since anchor. */ cstate = gather_updates(ctx, o1, o2, a, commit_fee(o1, o2), argv + 6, &num_updates, NULL, &their_rhash, NULL); /* Get next revocation hash. */ shachain_from_seed(&seed, num_updates, &revocation_hash); sha256(&revocation_hash, revocation_hash.u.u8, sizeof(revocation_hash.u.u8)); /* Get pubkeys */ if (!proto_to_pubkey(o1->commit_key, &pubkey2)) errx(1, "Invalid o1 commit pubkey"); if (!pubkey_eq(&pubkey1, &pubkey2)) errx(1, "o1 pubkey != this privkey"); if (!proto_to_pubkey(o2->commit_key, &pubkey2)) errx(1, "Invalid o2 commit pubkey"); /* This is what the anchor pays to; figure out whick output. */ redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); /* Now create THEIR new commitment tx to spend 2/2 output of anchor. */ invert_cstate(cstate); commit = create_commit_tx(ctx, o2, o1, a, &their_rhash, cstate); /* If contributions don't exceed fees, this fails. */ if (!commit) errx(1, "Delta too large"); /* Sign it for them. */ sign_tx_input(ctx, commit, 0, redeemscript, tal_count(redeemscript), &privkey, &pubkey1, &sig.sig); pkt = update_accept_pkt(ctx, &sig.sig, &revocation_hash); if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) err(1, "Writing out packet"); tal_free(ctx); return 0; }
static void tal_hexeq(const u8 *p, const char *hex) { hexeq(p, tal_count(p),hex); }
/* * We add changes to both our staging cstate (as they did when they sent * it) and theirs (as they will when we ack it). */ Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt) { const UpdateAddHtlc *u = pkt->update_add_htlc; struct sha256 rhash; struct abs_locktime expiry; /* BOLT #2: * * `amount_msat` MUST BE greater than 0. */ if (u->amount_msat == 0) return pkt_err(peer, "Invalid amount_msat"); proto_to_sha256(u->r_hash, &rhash); if (!proto_to_abs_locktime(u->expiry, &expiry)) return pkt_err(peer, "Invalid HTLC expiry"); /* FIXME: Handle block-based expiry! */ if (!abs_locktime_is_seconds(&expiry)) return pkt_err(peer, "HTLC expiry in blocks not supported!"); /* BOLT #2: * * A node MUST NOT add a HTLC if it would result in it * offering more than 1500 HTLCs in either commitment transaction. */ if (tal_count(peer->them.staging_cstate->a.htlcs) == 1500 || tal_count(peer->us.staging_cstate->b.htlcs) == 1500) return pkt_err(peer, "Too many HTLCs"); /* BOLT #2: * * A node MUST NOT set `id` equal to another HTLC which is in * the current staged commitment transaction. */ if (funding_htlc_by_id(&peer->them.staging_cstate->a, u->id) < tal_count(peer->them.staging_cstate->a.htlcs)) return pkt_err(peer, "HTLC id %"PRIu64" clashes for you", u->id); /* FIXME: Assert this... */ /* Note: these should be in sync, so this should be redundant! */ if (funding_htlc_by_id(&peer->us.staging_cstate->b, u->id) < tal_count(peer->us.staging_cstate->b.htlcs)) return pkt_err(peer, "HTLC id %"PRIu64" clashes for us", u->id); /* BOLT #2: * * A node MUST NOT offer `amount_msat` it cannot pay for in * both commitment transactions at the current `fee_rate` (see * "Fee Calculation" ). A node SHOULD fail the connection if * this occurs. */ /* FIXME: This is wrong! We may have already added more txs to * them.staging_cstate, driving that fee up. * We should check against the last version they acknowledged. */ if (!funding_a_add_htlc(peer->them.staging_cstate, u->amount_msat, &expiry, &rhash, u->id)) return pkt_err(peer, "Cannot afford %"PRIu64" milli-satoshis" " in your commitment tx", u->amount_msat); /* If we fail here, we've already changed them.staging_cstate, so * MUST terminate. */ if (!funding_b_add_htlc(peer->us.staging_cstate, u->amount_msat, &expiry, &rhash, u->id)) return pkt_err(peer, "Cannot afford %"PRIu64" milli-satoshis" " in our commitment tx", u->amount_msat); peer_add_htlc_expiry(peer, &expiry); /* FIXME: Fees must be sufficient. */ return NULL; }
int main(void) { struct protocol_double_sha dsha; struct protocol_net_address netaddr; int fds[2]; char *p, *mem1, *mem2, *mem3; int status; size_t maxmem = sizeof(struct log_entry) * 4 + 25 + 25 + 28 + 161; void *ctx = tal(NULL, char); struct log *log = new_log(ctx, NULL, "PREFIX", LOG_BROKEN+1, maxmem); assert(tal_parent(log) == ctx); my_time.ts.tv_sec = 1384064855; my_time.ts.tv_nsec = 500; log_debug(log, "This is a debug %s!", "message"); my_time.ts.tv_nsec++; log_info(log, "This is an info %s!", "message"); my_time.ts.tv_nsec++; log_unusual(log, "This is an unusual %s!", "message"); my_time.ts.tv_nsec++; log_broken(log, "This is a broken %s!", "message"); my_time.ts.tv_nsec++; log_add(log, "the sha is "); memset(&dsha, 0xFF, sizeof(dsha)); log_add_struct(log, struct protocol_double_sha, &dsha); log_add(log, " and the address is: "); memset(netaddr.addr, 0, 10); memset(netaddr.addr + 10, 0xFF, 2); netaddr.addr[12] = 127; netaddr.addr[13] = 0; netaddr.addr[14] = 0; netaddr.addr[15] = 1; netaddr.port = cpu_to_le16(65000); netaddr.time = time_now().ts.tv_sec - 10; log_add_struct(log, struct protocol_net_address, &netaddr); /* Make child write log, be sure it's correct. */ pipe(fds); switch (fork()) { case -1: err(1, "forking"); case 0: close(fds[0]); setenv("TZ", "UTC", 1); log_to_file(fds[1], log); tal_free(ctx); exit(0); } close(fds[1]); p = read_from(ctx, fds[0]); /* Shouldn't contain any NUL chars */ assert(strlen(p) + 1 == tal_count(p)); assert(tal_strreg(p, p, "PREFIX ([0-9])* bytes, Sun Nov 10 06:27:35 2013\n" "\\+0\\.000000500 DEBUG: This is a debug message!\n" "\\+0\\.000000501 INFO: This is an info message!\n" "\\+0\\.000000502 UNUSUAL: This is an unusual message!\n" "\\+0\\.000000503 BROKEN: This is a broken message!the sha is ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff and the address is: ::ffff:127\\.0\\.0\\.1:65000 \\(10 seconds old\\)\n\n", &mem1)); assert(atoi(mem1) < maxmem); tal_free(p); wait(&status); assert(WIFEXITED(status) && WEXITSTATUS(status) == 0); /* This cleans us out! */ log_debug(log, "Overflow!"); /* Make child write log, be sure it's correct. */ pipe(fds); switch (fork()) { case -1: err(1, "forking"); case 0: close(fds[0]); setenv("TZ", "UTC", 1); log_to_file(fds[1], log); tal_free(ctx); exit(0); } close(fds[1]); p = read_from(ctx, fds[0]); /* Shouldn't contain any NUL chars */ assert(strlen(p) + 1 == tal_count(p)); assert(tal_strreg(p, p, "PREFIX ([0-9]*) bytes, Sun Nov 10 06:27:35 2013\n" "\\.\\.\\. 4 skipped\\.\\.\\.\n" "\\+0.000000504 DEBUG: Overflow!\n" "\\+0.000000504 DEBUG: Log pruned 4 entries \\(mem ([0-9]*) -> ([0-9]*)\\)\n\n", &mem1, &mem2, &mem3)); assert(atoi(mem1) < maxmem); assert(atoi(mem2) >= maxmem); assert(atoi(mem3) < maxmem); tal_free(ctx); wait(&status); assert(WIFEXITED(status) && WEXITSTATUS(status) == 0); return 0; }
/* BIP 141: * It is followed by stack items, with each item starts with a var_int * to indicate the length. */ static void add_witness(const u8 *witness, void (*add)(const void *, size_t, void *), void *addp) { add_varint_blob(witness, tal_count(witness), add, addp); }
static void dump_tx(const char *str, const struct bitcoin_tx *tx) { u8 *linear = linearize_tx(NULL, tx); printf("%s:%s\n", str, hex_of(linear, linear, tal_count(linear))); tal_free(linear); }
/* We've added a whole heap of transactions, recheck them and set input refs. */ void recheck_pending_txs(struct state *state) { unsigned int unknown, known, total; unsigned int i, shard; const union protocol_tx **txs; struct pending_unknown_tx *utx; if (!state->pending->needs_recheck) return; state->pending->needs_recheck = false; /* Size up and allocate an array. */ unknown = state->pending->num_unknown; known = num_pending_known(state); /* Avoid logging if nothing pending. */ if (unknown == 0 && known == 0) return; txs = tal_arr(state, const union protocol_tx *, unknown + known); log_info(state->log, "Rechecking pending (%u known, %u unknown)", known, unknown); /* Now move pending from shards. */ total = 0; for (shard = 0; shard < ARRAY_SIZE(state->pending->pend); shard++) { struct pending_tx **pend = state->pending->pend[shard]; unsigned int i; for (i = 0; i < tal_count(pend); i++) { remove_pending_tx_from_hashes(state, pend[i]->tx); txs[total++] = tal_steal(txs, pend[i]->tx); } } /* And last we move the unknown ones. */ while ((utx = list_pop(&state->pending->unknown_tx, struct pending_unknown_tx, list)) != NULL) { remove_pending_tx_from_hashes(state, utx->tx); txs[total++] = tal_steal(txs, utx->tx); } assert(total == unknown + known); /* Clean up pending (frees everything above as a side effect). */ tal_free(state->pending); state->pending = new_pending_block(state); /* Now re-add them */ for (i = 0; i < tal_count(txs); i++) { unsigned int bad_input_num; struct protocol_double_sha sha; hash_tx(txs[i], &sha); add_pending_tx(state, txs[i], &sha, &bad_input_num, NULL); } /* Just to print the debug! */ known = 0; for (shard = 0; shard < ARRAY_SIZE(state->pending->pend); shard++) known += tal_count(state->pending->pend[shard]); log_info(state->log, "Now have %u known, %u unknown", known, state->pending->num_unknown); /* Restart generator on this block. */ restart_generating(state); }
int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); OpenChannel *o1, *o2; OpenAnchor *a; struct bitcoin_tx *close_tx; struct pkt *pkt; struct signature sig; struct privkey privkey; bool testnet; struct pubkey pubkey1, pubkey2; u8 *redeemscript; char *close_file = NULL; u64 close_fee = 10000; struct channel_state *cstate; err_set_progname(argv[0]); opt_register_arg("--complete=<close-msg-file>", opt_set_charp, NULL, &close_file, "Create a close_transaction_complete msg instead"); opt_register_noarg("--help|-h", opt_usage_and_exit, "<open-channel-file1> <open-channel-file2> <anchor-file> <commit-privkey> [{+/-}update-protobuf]...\n" "Create the signature needed for the close transaction", "Print this message."); opt_register_arg("--close-fee=<bits>", opt_set_bits, opt_show_bits, &close_fee, "100's of satoshi to pay for close tx"); opt_register_version(); opt_parse(&argc, argv, opt_log_stderr_exit); if (argc < 5) opt_usage_exit_fail("Expected 4+ arguments"); o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; a = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor; if (!key_from_base58(argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1)) errx(1, "Invalid private key '%s'", argv[4]); if (!testnet) errx(1, "Private key '%s' not on testnet!", argv[4]); if (close_file) { CloseChannel *c; c = pkt_from_file(close_file, PKT__PKT_CLOSE)->close; close_fee = c->close_fee; } cstate = gather_updates(ctx, o1, o2, a, close_fee, argv + 5, NULL, NULL, NULL, NULL); /* Get pubkeys */ if (!proto_to_pubkey(o1->commit_key, &pubkey2)) errx(1, "Invalid o1 commit pubkey"); if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2) || memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0) errx(1, "o1 pubkey != this privkey"); if (!proto_to_pubkey(o2->commit_key, &pubkey2)) errx(1, "Invalid o2 commit pubkey"); /* This is what the anchor pays to. */ redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); close_tx = create_close_tx(ctx, o1, o2, a, cstate->a.pay, cstate->b.pay); /* Sign it for them. */ sign_tx_input(ctx, close_tx, 0, redeemscript, tal_count(redeemscript), &privkey, &pubkey1, &sig); if (close_file) pkt = close_channel_complete_pkt(ctx, &sig); else pkt = close_channel_pkt(ctx, close_fee, &sig); if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) err(1, "Writing out packet"); tal_free(ctx); return 0; }
tal_count(peer->anchor.redeemscript), &peer->secrets->commit, &peer->us.commitkey, sig); } void peer_sign_spend(const struct peer *peer, struct bitcoin_tx *spend, const u8 *commit_redeemscript, struct signature *sig) { /* Spend tx only has one input: that of the commit tx. */ sign_tx_input(peer->dstate->secpctx, spend, 0, commit_redeemscript, tal_count(commit_redeemscript), &peer->secrets->final, &peer->us.finalkey, sig); } void peer_sign_mutual_close(const struct peer *peer, struct bitcoin_tx *close, struct signature *sig) { sign_tx_input(peer->dstate->secpctx, close, 0, peer->anchor.redeemscript, tal_count(peer->anchor.redeemscript), &peer->secrets->commit, &peer->us.commitkey,
int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); struct sha256 seed, our_rhash, their_rhash, preimage; OpenChannel *o1, *o2; OpenAnchor *a; struct pkt *pkt; struct bitcoin_tx *commit; struct pubkey pubkey1, pubkey2; size_t num_updates; struct bitcoin_signature sig; u8 *redeemscript; struct channel_state *cstate; err_set_progname(argv[0]); opt_register_noarg("--help|-h", opt_usage_and_exit, "<seed> <open-channel-file1> <open-channel-file2> <open-anchor-file> <all-previous-updates>\n" "Create a new update-complete message", "Print this message."); opt_register_version(); opt_parse(&argc, argv, opt_log_stderr_exit); if (argc < 7) opt_usage_exit_fail("Expected 6+ arguments"); if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; a = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; sig.stype = SIGHASH_ALL; /* This also checks that preimage is correct! */ cstate = gather_updates(ctx, o1, o2, a, commit_fee(o1, o2), argv + 5, &num_updates, &our_rhash, &their_rhash, &sig.sig); if (num_updates < 1) errx(1, "Expected at least one update!"); /* Get pubkeys */ if (!proto_to_pubkey(o1->commit_key, &pubkey1)) errx(1, "Invalid o1 commit pubkey"); if (!proto_to_pubkey(o2->commit_key, &pubkey2)) errx(1, "Invalid o2 commit pubkey"); /* This is what the anchor pays to. */ redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); /* Check their signature signs our new commit tx correctly. */ commit = create_commit_tx(ctx, o1, o2, a, &our_rhash, cstate); if (!commit) errx(1, "Delta too large"); if (!check_tx_sig(commit, 0, redeemscript, tal_count(redeemscript), &pubkey2, &sig)) errx(1, "Invalid signature."); /* Hand over our preimage for previous tx. */ shachain_from_seed(&seed, num_updates - 1, &preimage); pkt = update_complete_pkt(ctx, &preimage); if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) err(1, "Writing out packet"); tal_free(ctx); return 0; }
int main(int argc, char *argv[]) { size_t i, j, num; struct timeabs start, stop; char **w; ENTRY *words, *misswords; w = tal_strsplit(NULL, grab_file(NULL, argv[1] ? argv[1] : "/usr/share/dict/words"), "\n", STR_NO_EMPTY); num = tal_count(w) - 1; printf("%zu words\n", num); hcreate(num+num/3); words = tal_arr(w, ENTRY, num); for (i = 0; i < num; i++) { words[i].key = w[i]; words[i].data = words[i].key; } /* Append and prepend last char for miss testing. */ misswords = tal_arr(w, ENTRY, num); for (i = 0; i < num; i++) { char lastc; if (strlen(w[i])) lastc = w[i][strlen(w[i])-1]; else lastc = 'z'; misswords[i].key = tal_fmt(misswords, "%c%s%c%c", lastc, w[i], lastc, lastc); } printf("#01: Initial insert: "); fflush(stdout); start = time_now(); for (i = 0; i < num; i++) hsearch(words[i], ENTER); stop = time_now(); printf(" %zu ns\n", normalize(&start, &stop, num)); printf("#02: Initial lookup (match): "); fflush(stdout); start = time_now(); for (i = 0; i < num; i++) if (hsearch(words[i], FIND)->data != words[i].data) abort(); stop = time_now(); printf(" %zu ns\n", normalize(&start, &stop, num)); printf("#03: Initial lookup (miss): "); fflush(stdout); start = time_now(); for (i = 0; i < num; i++) { if (hsearch(misswords[i], FIND)) abort(); } stop = time_now(); printf(" %zu ns\n", normalize(&start, &stop, num)); /* Lookups in order are very cache-friendly for judy; try random */ printf("#04: Initial lookup (random): "); fflush(stdout); start = time_now(); for (i = 0, j = 0; i < num; i++, j = (j + 10007) % num) if (hsearch(words[i], FIND)->data != words[i].data) abort(); stop = time_now(); printf(" %zu ns\n", normalize(&start, &stop, num)); return 0; }
int main(int argc, char *argv[]) { struct state *s; struct working_block *w; unsigned int i; union protocol_tx *t; struct protocol_gateway_payment payment; struct block *prev, *b; struct block_shard *shard; u8 *prev_txhashes; enum protocol_ecode e; struct gen_update update; struct protocol_input_ref *refs; struct protocol_block_id sha; struct protocol_block_id prevs[PROTOCOL_NUM_PREV_IDS]; /* We need enough of state to use the real init function here. */ pseudorand_init(); s = new_state(true); check_chains(s, true); fake_time = le32_to_cpu(genesis_tlr.timestamp) + 1; /* Create a block after that, with a gateway tx in it. */ prev_txhashes = make_prev_txhashes(s, &genesis, helper_addr(1)); /* We should need 1 prev_merkle per shard per block. */ assert(num_prev_txhashes(&genesis) == (1 << genesis.bi.hdr->shard_order)); assert(tal_count(prev_txhashes) == num_prev_txhashes(&genesis)); memset(prevs, 0, sizeof(prevs)); prevs[0] = genesis.sha; w = new_working_block(s, 0x1ffffff0, prev_txhashes, tal_count(prev_txhashes), block_height(&genesis.bi) + 1, next_shard_order(&genesis), prevs, helper_addr(1)); payment.send_amount = cpu_to_le32(1000); payment.output_addr = *helper_addr(0); t = create_from_gateway_tx(s, helper_gateway_public_key(), 1, &payment, false, helper_gateway_key(s)); /* Gateway txs have empty refs, so this gives 0-len array. */ refs = create_refs(s, &genesis, t, 1); update.shard = shard_of_tx(t, next_shard_order(&genesis)); update.txoff = 0; update.features = 0; update.unused = 0; hash_tx_and_refs(t, refs, &update.hashes); assert(add_tx(w, &update)); for (i = 0; !solve_block(w); i++); e = check_block_header(s, &w->bi, &prev, &sha.sha); assert(e == PROTOCOL_ECODE_NONE); assert(prev == &genesis); b = block_add(s, prev, &sha, &w->bi); /* This is a NOOP, so should succeed. */ assert(check_prev_txhashes(s, b, NULL, NULL)); /* Put the single tx into the shard. */ shard = new_block_shard(s, update.shard, 1); shard->txcount = 1; shard->u[0].txp = txptr_with_ref(shard, t, refs); /* This should all be correct. */ check_block_shard(s, b, shard); b->shard[shard->shardnum] = shard; /* Should require a prev_merkle per shard for each of 2 prev blocks. */ assert(num_prev_txhashes(b) == (2 << genesis.bi.hdr->shard_order)); prev_txhashes = make_prev_txhashes(s, b, helper_addr(1)); assert(tal_count(prev_txhashes) == num_prev_txhashes(b)); /* Solve third block. */ fake_time++; prevs[0] = b->sha; prevs[1] = genesis.sha; w = new_working_block(s, 0x1ffffff0, prev_txhashes, num_prev_txhashes(b), block_height(&b->bi) + 1, next_shard_order(b), prevs, helper_addr(1)); for (i = 0; !solve_block(w); i++); e = check_block_header(s, &w->bi, &prev, &sha.sha); assert(e == PROTOCOL_ECODE_NONE); assert(prev == b); b = block_add(s, prev, &sha, &w->bi); /* This should be correct. */ assert(check_prev_txhashes(s, b, NULL, NULL)); tal_free(s); return 0; }
static void add(u8 **scriptp, const void *mem, size_t len) { size_t oldlen = tal_count(*scriptp); tal_resize(scriptp, oldlen + len); memcpy(*scriptp + oldlen, mem, len); }
int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); OpenChannel *o1, *o2; OpenAnchor *a; struct bitcoin_tx *close_tx; struct bitcoin_signature sig1, sig2; struct pubkey pubkey1, pubkey2; u8 *redeemscript; CloseChannel *close; CloseChannelComplete *closecomplete; struct channel_state *cstate; err_set_progname(argv[0]); /* FIXME: Take update.pbs to adjust channel */ opt_register_noarg("--help|-h", opt_usage_and_exit, "<open-channel-file1> <open-channel-file2> <open-anchor-file> <close-protobuf> <close-complete-protobuf> [update-protobuf]...\n" "Create the close transaction from the signatures", "Print this message."); opt_register_version(); opt_parse(&argc, argv, opt_log_stderr_exit); if (argc < 6) opt_usage_exit_fail("Expected 5+ arguments"); o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; a = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor; close = pkt_from_file(argv[4], PKT__PKT_CLOSE)->close; closecomplete = pkt_from_file(argv[5], PKT__PKT_CLOSE_COMPLETE)->close_complete; /* Pubkeys well-formed? */ if (!proto_to_pubkey(o1->commit_key, &pubkey1)) errx(1, "Invalid o1 commit_key"); if (!proto_to_pubkey(o2->commit_key, &pubkey2)) errx(1, "Invalid o2 commit_key"); /* Get delta by accumulting all the updates. */ cstate = gather_updates(ctx, o1, o2, a, close->close_fee, argv + 6, NULL, NULL, NULL, NULL); /* This is what the anchor pays to; figure out which output. */ redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); /* Now create the close tx to spend 2/2 output of anchor. */ close_tx = create_close_tx(ctx, o1, o2, a, cstate->a.pay_msat / 1000, cstate->b.pay_msat / 1000); /* Signatures well-formed? */ sig1.stype = sig2.stype = SIGHASH_ALL; if (!proto_to_signature(close->sig, &sig1.sig)) errx(1, "Invalid close-packet"); if (!proto_to_signature(closecomplete->sig, &sig2.sig)) errx(1, "Invalid closecomplete-packet"); /* Combined signatures must validate correctly. */ if (!check_2of2_sig(close_tx, 0, redeemscript, tal_count(redeemscript), &pubkey1, &pubkey2, &sig1, &sig2)) errx(1, "Signature failed"); /* Create p2sh input for close_tx */ close_tx->input[0].script = scriptsig_p2sh_2of2(close_tx, &sig1, &sig2, &pubkey1, &pubkey2); close_tx->input[0].script_length = tal_count(close_tx->input[0].script); /* Print it out in hex. */ if (!bitcoin_tx_write(STDOUT_FILENO, close_tx)) err(1, "Writing out transaction"); tal_free(ctx); return 0; }
/* Simple test code to create a gateway transaction */ int main(int argc, char *argv[]) { int fd, i, off; const char *method; char *cmd, *resp, *idstr, *rpc_filename; struct sockaddr_un addr; jsmntok_t *toks; const jsmntok_t *result, *error, *id; char *pettycoin_dir; const tal_t *ctx = tal(NULL, char); err_set_progname(argv[0]); opt_set_alloc(opt_allocfn, tal_reallocfn, tal_freefn); pettycoin_dir_register_opts(ctx, &pettycoin_dir, &rpc_filename); opt_register_noarg("--help|-h", opt_usage_and_exit, "<command> [<params>...]", "Show this message"); opt_register_noarg("--version|-V", opt_version_and_exit, VERSION, "Display version and exit"); opt_early_parse(argc, argv, opt_log_stderr_exit); opt_parse(&argc, argv, opt_log_stderr_exit); method = argv[1]; if (!method) errx(ERROR_USAGE, "Need at least one argument\n%s", opt_usage(argv[0], NULL)); if (chdir(pettycoin_dir) != 0) err(ERROR_TALKING_TO_PETTYCOIN, "Moving into '%s'", pettycoin_dir); fd = socket(AF_UNIX, SOCK_STREAM, 0); if (strlen(rpc_filename) + 1 > sizeof(addr.sun_path)) errx(ERROR_USAGE, "rpc filename '%s' too long", rpc_filename); strcpy(addr.sun_path, rpc_filename); addr.sun_family = AF_UNIX; if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) err(ERROR_TALKING_TO_PETTYCOIN, "Connecting to '%s'", rpc_filename); idstr = tal_fmt(ctx, "pettycoin_query-%i", getpid()); cmd = tal_fmt(ctx, "{ \"method\" : \"%s\", \"id\" : \"%s\", \"params\" : [ ", method, idstr); for (i = 2; i < argc; i++) { /* Numbers are left unquoted, and quoted things left alone. */ if (strspn(argv[i], "0123456789") == strlen(argv[i]) || argv[i][0] == '"') tal_append_fmt(&cmd, "%s", argv[i]); else tal_append_fmt(&cmd, "\"%s\"", argv[i]); if (i != argc - 1) tal_append_fmt(&cmd, ", "); } tal_append_fmt(&cmd, "] }"); if (!write_all(fd, cmd, strlen(cmd))) err(ERROR_TALKING_TO_PETTYCOIN, "Writing command"); resp = tal_arr(cmd, char, 100); off = 0; while ((i = read(fd, resp + off, tal_count(resp) - 1 - off)) > 0) { bool valid; off += i; if (off == tal_count(resp) - 1) tal_resize(&resp, tal_count(resp) * 2); toks = json_parse_input(resp, off, &valid); if (toks) break; if (!valid) errx(ERROR_TALKING_TO_PETTYCOIN, "Malformed response '%.*s'", off, resp); } resp[off] = '\0'; if (i < 0) err(ERROR_TALKING_TO_PETTYCOIN, "reading response"); result = json_get_member(resp, toks, "result"); if (!result) errx(ERROR_TALKING_TO_PETTYCOIN, "Missing 'result' in response '%s'", resp); error = json_get_member(resp, toks, "error"); if (!error) errx(ERROR_TALKING_TO_PETTYCOIN, "Missing 'error' in response '%s'", resp); id = json_get_member(resp, toks, "id"); if (!id) errx(ERROR_TALKING_TO_PETTYCOIN, "Missing 'id' in response '%s'", resp); if (!json_tok_streq(resp, id, idstr)) errx(ERROR_TALKING_TO_PETTYCOIN, "Incorrect 'id' in response: %.*s", json_tok_len(id), json_tok_contents(resp, id)); if (json_tok_is_null(resp, error)) { printf("%.*s\n", json_tok_len(result), json_tok_contents(resp, result)); tal_free(ctx); return 0; } printf("%.*s\n", json_tok_len(error), json_tok_contents(resp, error)); tal_free(ctx); return 1; }
int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); struct sha256 seed, preimage, our_rhash, their_rhash; OpenChannel *o1, *o2; OpenAnchor *a; struct bitcoin_tx *commit; struct pkt *pkt; struct bitcoin_signature sig; struct privkey privkey; bool testnet; struct pubkey pubkey1, pubkey2; u8 *redeemscript; size_t num_updates; struct channel_state *cstate; err_set_progname(argv[0]); opt_register_noarg("--help|-h", opt_usage_and_exit, "<seed> <open-channel-file1> <open-channel-file2> <open-anchor-file> <commit-privkey> <all-previous-updates>...\n" "Create a new update-channel-signature message", "Print this message."); opt_register_version(); opt_parse(&argc, argv, opt_log_stderr_exit); if (argc < 8) opt_usage_exit_fail("Expected 7+ arguments"); if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; a = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; if (!key_from_base58(argv[5], strlen(argv[5]), &testnet, &privkey, &pubkey1)) errx(1, "Invalid private key '%s'", argv[5]); if (!testnet) errx(1, "Private key '%s' not on testnet!", argv[5]); sig.stype = SIGHASH_ALL; /* Figure out cumulative delta since anchor. */ cstate = gather_updates(ctx, o1, o2, a, commit_fee(o1, o2), argv + 6, &num_updates, &our_rhash, &their_rhash, &sig.sig); if (num_updates < 1) errx(1, "Expected at least one update!"); /* Give up revocation preimage for old tx. */ shachain_from_seed(&seed, num_updates - 1, &preimage); /* Get pubkeys */ if (!proto_to_pubkey(o1->commit_key, &pubkey2)) errx(1, "Invalid o1 commit pubkey"); if (!pubkey_eq(&pubkey1, &pubkey2)) errx(1, "o1 pubkey != this privkey"); if (!proto_to_pubkey(o2->commit_key, &pubkey2)) errx(1, "Invalid o2 commit pubkey"); /* This is what the anchor pays to. */ redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); /* Check our new commit is signed correctly by them. */ commit = create_commit_tx(ctx, o1, o2, a, &our_rhash, cstate); if (!commit) errx(1, "Invalid packets"); /* Check their signature signs this input correctly. */ if (!check_tx_sig(commit, 0, redeemscript, tal_count(redeemscript), &pubkey2, &sig)) errx(1, "Invalid signature."); /* Now create THEIR new commitment tx to spend 2/2 output of anchor. */ invert_cstate(cstate); commit = create_commit_tx(ctx, o2, o1, a, &their_rhash, cstate); if (!commit) errx(1, "Invalid packets"); /* Their pubkey must be valid */ if (!proto_to_pubkey(o2->commit_key, &pubkey2)) errx(1, "Invalid public open-channel-file2"); /* Sign it for them. */ sign_tx_input(ctx, commit, 0, redeemscript, tal_count(redeemscript), &privkey, &pubkey1, &sig.sig); pkt = update_signature_pkt(ctx, &sig.sig, &preimage); if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) err(1, "Writing out packet"); tal_free(ctx); return 0; }
int main(void) { char *parent, *c; plan_tests(43); parent = tal(NULL, char); ok1(parent); c = tal_strdup(parent, "hello"); ok1(strcmp(c, "hello") == 0); ok1(tal_parent(c) == parent); ok1(tal_count(c) == strlen(c) + 1); tal_free(c); c = tal_strndup(parent, "hello", 3); ok1(strcmp(c, "hel") == 0); ok1(tal_parent(c) == parent); ok1(tal_count(c) == strlen(c) + 1); tal_free(c); #ifdef TAL_USE_TALLOC c = tal_talloc_typechk_(parent, char *); #else c = tal_typechk_(parent, char *); #endif c = tal_dup_arr(parent, char, "hello", 6, 0); ok1(strcmp(c, "hello") == 0); ok1(strcmp(tal_name(c), "char[]") == 0); ok1(tal_count(c) == 6); ok1(tal_parent(c) == parent); tal_free(c); /* Now with an extra byte. */ c = tal_dup_arr(parent, char, "hello", 6, 1); ok1(strcmp(c, "hello") == 0); ok1(strcmp(tal_name(c), "char[]") == 0); ok1(tal_count(c) == 7); ok1(tal_parent(c) == parent); strcat(c, "x"); tal_free(c); c = tal_fmt(parent, "hello %s", "there"); ok1(strcmp(c, "hello there") == 0); ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); tal_free(c); c = tal_strcat(parent, "hello ", "there"); ok1(strcmp(c, "hello there") == 0); ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); /* Make sure take works correctly. */ c = tal_strcat(parent, take(c), " again"); ok1(strcmp(c, "hello there again") == 0); ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); ok1(single_child(parent, c)); c = tal_strcat(parent, "And ", take(c)); ok1(tal_count(c) == strlen(c) + 1); ok1(strcmp(c, "And hello there again") == 0); ok1(tal_parent(c) == parent); ok1(single_child(parent, c)); /* NULL pass through works... */ c = tal_strcat(parent, take(NULL), take(c)); ok1(!c); ok1(no_children(parent)); c = tal_strcat(parent, take(tal_strdup(parent, "hi")), take(NULL)); ok1(!c); ok1(no_children(parent)); c = tal_strcat(parent, take(NULL), take(NULL)); ok1(!c); ok1(no_children(parent)); /* Appending formatted strings. */ c = tal_strdup(parent, "hi"); ok1(tal_count(c) == strlen(c) + 1); ok1(tal_append_fmt(&c, "%s %s", "there", "world")); ok1(strcmp(c, "hithere world") == 0); ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); ok1(!tal_append_fmt(&c, take(NULL), "there", "world")); ok1(strcmp(c, "hithere world") == 0); ok1(tal_count(c) == strlen(c) + 1); tal_free(parent); return exit_status(); }
int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); OpenChannel *o1, *o2; OpenAnchor *a; struct bitcoin_tx *commit, *tx; struct bitcoin_signature sig; struct privkey privkey; bool testnet; struct pubkey pubkey1, pubkey2, outpubkey; u8 *redeemscript; struct sha256 rhash; size_t p2sh_out; u64 fee = 10000; u32 locktime; err_set_progname(argv[0]); /* FIXME: If we've updated channel since, we need the final * revocation hash we sent (either update_accept or update_complete) */ opt_register_noarg("--help|-h", opt_usage_and_exit, "<commitment-tx> <open-channel-file1> <open-channel-file2> <open-anchor-file> <my-privoutkey> <someaddress> [previous-updates]\n" "Create the transaction to spend our commit transaction", "Print this message."); opt_register_arg("--fee=<bits>", opt_set_bits, opt_show_bits, &fee, "100's of satoshi to pay in transaction fee"); opt_register_version(); opt_parse(&argc, argv, opt_log_stderr_exit); if (argc < 6) opt_usage_exit_fail("Expected 5+ arguments"); commit = bitcoin_tx_from_file(ctx, argv[1]); o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; a = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; if (!proto_to_rel_locktime(o2->delay, &locktime)) errx(1, "Invalid locktime in o2"); /* We need our private key to spend commit output. */ if (!key_from_base58(argv[5], strlen(argv[5]), &testnet, &privkey, &pubkey1)) errx(1, "Invalid private key '%s'", argv[5]); if (!testnet) errx(1, "Private key '%s' not on testnet!", argv[5]); if (!pubkey_from_hexstr(argv[6], &outpubkey)) errx(1, "Invalid bitcoin pubkey '%s'", argv[6]); /* Get pubkeys */ if (!proto_to_pubkey(o1->final_key, &pubkey2)) errx(1, "Invalid o1 final pubkey"); if (!pubkey_eq(&pubkey1, &pubkey2)) errx(1, "o1 pubkey != this privkey"); if (!proto_to_pubkey(o2->final_key, &pubkey2)) errx(1, "Invalid o2 final pubkey"); /* We use this simply to get final revocation hash. */ gather_updates(ctx, o1, o2, a, commit_fee(o1, o2), argv + 7, NULL, &rhash, NULL, NULL); /* Create redeem script */ redeemscript = bitcoin_redeem_secret_or_delay(ctx, &pubkey1, locktime, &pubkey2, &rhash); /* Now, create transaction to spend it. */ tx = bitcoin_tx(ctx, 1, 1); bitcoin_txid(commit, &tx->input[0].txid); p2sh_out = find_p2sh_out(commit, redeemscript); tx->input[0].index = p2sh_out; tx->input[0].input_amount = commit->output[p2sh_out].amount; tx->fee = fee; tx->input[0].sequence_number = bitcoin_nsequence(locktime); if (commit->output[p2sh_out].amount <= fee) errx(1, "Amount of %llu won't exceed fee", (unsigned long long)commit->output[p2sh_out].amount); tx->output[0].amount = commit->output[p2sh_out].amount - fee; tx->output[0].script = scriptpubkey_p2sh(tx, bitcoin_redeem_single(tx, &outpubkey)); tx->output[0].script_length = tal_count(tx->output[0].script); /* Now get signature, to set up input script. */ if (!sign_tx_input(tx, tx, 0, redeemscript, tal_count(redeemscript), &privkey, &pubkey1, &sig.sig)) errx(1, "Could not sign tx"); sig.stype = SIGHASH_ALL; tx->input[0].script = scriptsig_p2sh_secret(tx, NULL, 0, &sig, redeemscript, tal_count(redeemscript)); tx->input[0].script_length = tal_count(tx->input[0].script); /* Print it out in hex. */ if (!bitcoin_tx_write(STDOUT_FILENO, tx)) err(1, "Writing out transaction"); tal_free(ctx); return 0; }
/* Takes complete update history, gets summary of last state. */ struct channel_state *gather_updates(const tal_t *ctx, const OpenChannel *o1, const OpenChannel *o2, const OpenAnchor *oa, uint64_t fee, char **argv, size_t *num_updates, struct sha256 *our_rhash, struct sha256 *their_rhash, struct signature *their_commit_sig) { Signature *sig = NULL; struct sha256 old_our_rhash, old_their_rhash, rhash1, rhash2; struct channel_state *cstate; /* Start sanity check. */ cstate = initial_funding(NULL, o1, o2, oa, fee); if (!cstate) errx(1, "Invalid open combination (need 1 anchor offer)"); /* If they don't want these, use dummy ones. */ if (!our_rhash) our_rhash = &rhash1; if (!their_rhash) their_rhash = &rhash2; proto_to_sha256(o1->revocation_hash, our_rhash); proto_to_sha256(o2->revocation_hash, their_rhash); assert(tal_count(cstate->a.htlcs) == 0); assert(tal_count(cstate->b.htlcs) == 0); /* If o2 sent anchor, it contains their commit sig. */ if (o2->anch == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR) sig = oa->commit_sig; if (num_updates) *num_updates = 0; while (*argv) { int64_t delta, amount; size_t n; bool received; Pkt *pkt; /* + marks messages sent by us, - for messages from them */ if (strstarts(*argv, "+")) { received = false; } else if (strstarts(*argv, "-")) { received = true; } else errx(1, "%s does not start with +/-", *argv); pkt = any_pkt_from_file(*argv + 1); switch (pkt->pkt_case) { case PKT__PKT_OPEN_COMMIT_SIG: if (received) sig = pkt->open_commit_sig->sig; break; case PKT__PKT_UPDATE_ADD_HTLC: amount = pkt->update_add_htlc->amount_msat; if (received) { if (!funding_delta(o2, o1, oa, 0, amount, &cstate->b, &cstate->a)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); add_htlc(&cstate->b, pkt->update_add_htlc, *argv); } else { if (!funding_delta(o1, o2, oa, 0, amount, &cstate->a, &cstate->b)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); add_htlc(&cstate->a, pkt->update_add_htlc, *argv); } update_rhash(pkt->update_add_htlc->revocation_hash, received, num_updates, &old_our_rhash, &old_their_rhash, our_rhash, their_rhash); break; case PKT__PKT_UPDATE_TIMEDOUT_HTLC: if (received) { n = find_htlc(&cstate->b, pkt->update_timedout_htlc->r_hash); if (n == tal_count(cstate->b.htlcs)) errx(1, "Unknown R hash in %s", *argv); amount = cstate->b.htlcs[n]->amount_msat; if (!funding_delta(o2, o1, oa, 0, -amount, &cstate->b, &cstate->a)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); remove_htlc(&cstate->b, n); } else { n = find_htlc(&cstate->a, pkt->update_timedout_htlc->r_hash); if (n == tal_count(cstate->a.htlcs)) errx(1, "Unknown R hash in %s", *argv); amount = cstate->a.htlcs[n]->amount_msat; if (!funding_delta(o1, o2, oa, 0, -amount, &cstate->a, &cstate->b)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); remove_htlc(&cstate->a, n); } update_rhash(pkt->update_timedout_htlc->revocation_hash, received, num_updates, &old_our_rhash, &old_their_rhash, our_rhash, their_rhash); break; /* HTLC acceptor sends this to initiator. */ case PKT__PKT_UPDATE_ROUTEFAIL_HTLC: if (received) { n = find_htlc(&cstate->a, pkt->update_routefail_htlc->r_hash); if (n == tal_count(cstate->a.htlcs)) errx(1, "Unknown R hash in %s", *argv); amount = cstate->a.htlcs[n]->amount_msat; if (!funding_delta(o1, o2, oa, 0, -amount, &cstate->a, &cstate->b)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); remove_htlc(&cstate->a, n); } else { n = find_htlc(&cstate->b, pkt->update_routefail_htlc->r_hash); if (n == tal_count(cstate->b.htlcs)) errx(1, "Unknown R hash in %s", *argv); amount = cstate->b.htlcs[n]->amount_msat; if (!funding_delta(o2, o1, oa, 0, -amount, &cstate->b, &cstate->a)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); remove_htlc(&cstate->b, n); } update_rhash(pkt->update_routefail_htlc->revocation_hash, received, num_updates, &old_our_rhash, &old_their_rhash, our_rhash, their_rhash); break; case PKT__PKT_UPDATE_FULFILL_HTLC: { struct sha256 r_hash, r_val; Sha256Hash *rh; /* Get hash, to find the HTLC. */ proto_to_sha256(pkt->update_fulfill_htlc->r, &r_val); sha256(&r_hash, &r_val, sizeof(r_val)); rh = sha256_to_proto(ctx, &r_hash); if (received) { /* HTLC was us->them, funds go to them. */ n = find_htlc(&cstate->a, rh); if (n == tal_count(cstate->a.htlcs)) errx(1, "Unknown R hash in %s", *argv); amount = cstate->a.htlcs[n]->amount_msat; if (!funding_delta(o1, o2, oa, amount, -amount, &cstate->a, &cstate->b)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); remove_htlc(&cstate->a, n); } else { /* HTLC was them->us, funds go to us. */ n = find_htlc(&cstate->b, rh); if (n == tal_count(cstate->b.htlcs)) errx(1, "Unknown R hash in %s", *argv); amount = cstate->b.htlcs[n]->amount_msat; if (!funding_delta(o2, o1, oa, amount, -amount, &cstate->b, &cstate->a)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); remove_htlc(&cstate->b, n); } update_rhash(pkt->update_fulfill_htlc->revocation_hash, received, num_updates, &old_our_rhash, &old_their_rhash, our_rhash, their_rhash); break; } case PKT__PKT_UPDATE: if (received) delta = -pkt->update->delta_msat; else delta = pkt->update->delta_msat; if (!funding_delta(o1, o2, oa, delta, 0, &cstate->a, &cstate->b)) errx(1, "Impossible funding update %lli %s", (long long)delta, *argv); update_rhash(pkt->update->revocation_hash, received, num_updates, &old_our_rhash, &old_their_rhash, our_rhash, their_rhash); break; case PKT__PKT_UPDATE_ACCEPT: if (received) sig = pkt->update_accept->sig; /* Does not increase num_updates */ update_rhash(pkt->update_accept->revocation_hash, received, NULL, &old_our_rhash, &old_their_rhash, our_rhash, their_rhash); break; case PKT__PKT_UPDATE_SIGNATURE: if (received) { sig = pkt->update_signature->sig; check_preimage(pkt->update_signature ->revocation_preimage, &old_their_rhash, their_rhash, *argv); } else { check_preimage(pkt->update_signature ->revocation_preimage, &old_our_rhash, our_rhash, *argv); } break; case PKT__PKT_UPDATE_COMPLETE: if (received) { check_preimage(pkt->update_complete ->revocation_preimage, &old_their_rhash, their_rhash, *argv); } else { check_preimage(pkt->update_complete ->revocation_preimage, &old_our_rhash, our_rhash, *argv); } break; default: errx(1, "Unexpected packet type %u", pkt->pkt_case); } argv++; } if (their_commit_sig) { if (!sig) errx(1, "No commit signature message found"); if (!proto_to_signature(sig, their_commit_sig)) errx(1, "Invalid signature"); } return cstate; }
static struct io_plan *write_done(struct io_conn *conn, struct data *d) { tal_resize(&d->pattern, tal_count(d->pattern) + 1); strcat(d->pattern, ">"); return write_more(conn, d); }
#include <assert.h> #include <ccan/endian/endian.h> #include <ccan/read_write_all/read_write_all.h> #include <errno.h> #include <wire/wire_io.h> #include <wire/wire_sync.h> bool wire_sync_write(int fd, const void *msg TAKES) { wire_len_t hdr = cpu_to_wirelen(tal_bytelen(msg)); bool ret; assert(tal_bytelen(msg) < WIRE_LEN_LIMIT); ret = write_all(fd, &hdr, sizeof(hdr)) && write_all(fd, msg, tal_count(msg)); if (taken(msg)) tal_free(msg); return ret; } u8 *wire_sync_read(const tal_t *ctx, int fd) { wire_len_t len; u8 *msg; if (!read_all(fd, &len, sizeof(len))) return NULL; if (wirelen_to_cpu(len) >= WIRE_LEN_LIMIT) { errno = E2BIG; return NULL;