int main(int argc, char *argv[]) { bool pub = true, priv = true; opt_register_noarg("--help|-h", opt_usage_and_exit, "[<seeds>...]\n" "Generate (deterministic if seed) secp256k1 keys", "Print this message."); opt_register_noarg("--pub", opt_set_invbool, &priv, "Generate only the public key"); opt_register_noarg("--priv", opt_set_invbool, &pub, "Generate only the private key"); opt_register_version(); opt_parse(&argc, argv, opt_log_stderr_exit); if (!priv && !pub) opt_usage_exit_fail("Can't use --pub and --priv"); if (argc == 1) { srandom(time(NULL) + getpid()); print_keypair(pub, priv); } else { int i; for (i = 1; i < argc; i++) { srandom(atoi(argv[i])); print_keypair(pub, priv); } } return 0; }
int main(int argc, char *argv[]) { opt_register_noarg("-v", opt_version_and_exit, (const char *)"1.2.3", (const char *)"Print version"); return 0; }
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; }
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(int argc, char *argv[]) { const char *myname = argv[0]; plan_tests(37); /* Simple short arg.*/ opt_register_noarg("-a", test_noarg, NULL, "All"); opt_register_early_noarg("-b", test_noarg, NULL, "All"); /* Early parsing doesn't mangle. */ ok1(parse_early_args(&argc, &argv, "-a", NULL)); ok1(argc == 2); ok1(argv[0] == myname); ok1(strcmp(argv[1], "-a") == 0); ok1(argv[2] == NULL); ok1(test_cb_called == 0); /* ... even if it processes arg. */ ok1(parse_early_args(&argc, &argv, "-b", NULL)); ok1(argc == 2); ok1(argv[0] == myname); ok1(strcmp(argv[1], "-b") == 0); ok1(argv[2] == NULL); ok1(test_cb_called == 1); ok1(parse_early_args(&argc, &argv, "-ab", NULL)); ok1(argc == 2); ok1(argv[0] == myname); ok1(strcmp(argv[1], "-ab") == 0); ok1(argv[2] == NULL); ok1(test_cb_called == 2); ok1(parse_args(&argc, &argv, "-ab", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 3); opt_register_table(some_early_table, "Some early args"); ok1(parse_early_args(&argc, &argv, "--verbose", "-dddd", "-h", NULL)); ok1(argc == 4); ok1(argv[0] == myname); ok1(strcmp(argv[1], "--verbose") == 0); ok1(strcmp(argv[2], "-dddd") == 0); ok1(strcmp(argv[3], "-h") == 0); ok1(argv[4] == NULL); ok1(test_cb_called == 5); ok1(parse_args(&argc, &argv, "--verbose", "-d", "ddd", "-h", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 6); /* parse_args allocates argv */ free(argv); return exit_status(); }
int main(int argc, char *argv[]) { struct timespec start, curr; struct timers timers; struct list_head expired; struct timer t[PER_CONN_TIME]; unsigned int i, num; bool check = false; opt_register_noarg("-c|--check", opt_set_bool, &check, "Check timer structure during progress"); opt_parse(&argc, argv, opt_log_stderr_exit); num = argv[1] ? atoi(argv[1]) : (check ? 100000 : 100000000); list_head_init(&expired); curr = start = time_now(); timers_init(&timers, start); for (i = 0; i < num; i++) { curr = time_add(curr, time_from_msec(1)); if (check) timers_check(&timers, NULL); timers_expire(&timers, curr, &expired); if (check) timers_check(&timers, NULL); assert(list_empty(&expired)); if (i >= PER_CONN_TIME) { timer_del(&timers, &t[i%PER_CONN_TIME]); if (check) timers_check(&timers, NULL); } timer_add(&timers, &t[i%PER_CONN_TIME], time_add(curr, time_from_msec(CONN_TIMEOUT_MS))); if (check) timers_check(&timers, NULL); } if (num > PER_CONN_TIME) { for (i = 0; i < PER_CONN_TIME; i++) timer_del(&timers, &t[i]); } curr = time_sub(time_now(), start); if (check) timers_check(&timers, NULL); timers_cleanup(&timers); opt_free_table(); for (i = 0; i < ARRAY_SIZE(timers.level); i++) if (!timers.level[i]) break; printf("%u in %lu.%09lu (%u levels / %zu)\n", num, (long)curr.tv_sec, curr.tv_nsec, i, ARRAY_SIZE(timers.level)); return 0; }
int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); OpenChannel *o1, *o2; OpenAnchorScriptsigs *ss1, *ss2; struct bitcoin_tx *anchor; struct sha256_double txid; u8 *tx_arr; size_t *inmap, *outmap; char *tx_hex; err_set_progname(argv[0]); opt_register_noarg("--help|-h", opt_usage_and_exit, "<open-channel-file1> <open-channel-file2> <anchor-sig2-1> <anchor-sigs2>\n" "Output the anchor transaction by merging the scriptsigs", "Print this message."); opt_parse(&argc, argv, opt_log_stderr_exit); if (argc != 5) opt_usage_exit_fail("Expected 6 arguments"); o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; ss1 = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR_SCRIPTSIGS) ->open_anchor_scriptsigs; ss2 = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR_SCRIPTSIGS) ->open_anchor_scriptsigs; anchor = anchor_tx_create(ctx, o1, o2, &inmap, &outmap); if (!anchor) errx(1, "Failed transaction merge"); if (!anchor_add_scriptsigs(anchor, ss1, ss2, inmap)) errx(1, "Wrong number of scriptsigs"); bitcoin_txid(anchor, &txid); /* Print it out in hex. */ tx_arr = linearize_tx(ctx, anchor); 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 anchor 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, rval; struct pkt *pkt; unsigned update_num; err_set_progname(argv[0]); opt_register_noarg("--help|-h", opt_usage_and_exit, "<seed> <update-number> <r-value>\n" "Create a new HTLC complete message", "Print this message."); opt_register_version(); opt_parse(&argc, argv, opt_log_stderr_exit); if (argc != 4) opt_usage_exit_fail("Expected 3 arguments"); if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); update_num = atoi(argv[2]); if (!update_num) errx(1, "Update number %s invalid", argv[2]); if (!hex_decode(argv[3], strlen(argv[3]), &rval, sizeof(rval))) errx(1, "Invalid rvalue '%s' - need 256 hex bits", argv[3]); /* Get next revocation hash. */ shachain_from_seed(&seed, update_num, &revocation_hash); sha256(&revocation_hash, revocation_hash.u.u8, sizeof(revocation_hash.u.u8)); pkt = update_htlc_complete_pkt(ctx, &revocation_hash, &rval); if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) err(1, "Writing out packet"); tal_free(ctx); return 0; }
/* Test helpers. */ int main(int argc, char *argv[]) { char *output; char *longname = strdup("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); char *shortname = strdup("shortname"); plan_tests(48); opt_register_table(subtables, NULL); opt_register_noarg("--kkk|-k", my_cb, NULL, "magic kkk option"); opt_register_noarg("-?", opt_usage_and_exit, "<MyArgs>...", "This message"); opt_register_arg("--longname", opt_set_charp, opt_show_charp, &longname, "a really long option default"); opt_register_arg("--shortname", opt_set_charp, opt_show_charp, &shortname, "a short option default"); output = opt_usage("my name", "ExTrA Args"); diag("%s", output); ok1(strstr(output, "Usage: my name")); ok1(strstr(output, "--jjj|-j|--lll|-l <arg>")); ok1(strstr(output, "ExTrA Args")); ok1(strstr(output, "-a ")); ok1(strstr(output, " Description of a\n")); ok1(strstr(output, "-b <arg>")); ok1(strstr(output, " Description of b (default: b)\n")); ok1(strstr(output, "--ddd ")); ok1(strstr(output, " Description of ddd\n")); ok1(strstr(output, "--eee <filename> ")); ok1(strstr(output, " (default: eee)\n")); ok1(strstr(output, "long table options:\n")); ok1(strstr(output, "--ggg|-g ")); ok1(strstr(output, " Description of ggg\n")); ok1(strstr(output, "-h|--hhh <arg>")); ok1(strstr(output, " Description of hhh\n")); ok1(strstr(output, "--kkk|-k")); ok1(strstr(output, "magic kkk option")); /* This entry is hidden. */ ok1(!strstr(output, "--mmm|-m")); free(output); /* NULL should use string from registered options. */ output = opt_usage("my name", NULL); diag("%s", output); ok1(strstr(output, "Usage: my name")); ok1(strstr(output, "--jjj|-j|--lll|-l <arg>")); ok1(strstr(output, "<MyArgs>...")); ok1(strstr(output, "-a ")); ok1(strstr(output, " Description of a\n")); ok1(strstr(output, "-b <arg>")); ok1(strstr(output, " Description of b (default: b)\n")); ok1(strstr(output, "--ddd ")); ok1(strstr(output, " Description of ddd\n")); ok1(strstr(output, "--eee <filename> ")); ok1(strstr(output, " (default: eee)\n")); ok1(strstr(output, "long table options:\n")); ok1(strstr(output, "--ggg|-g ")); ok1(strstr(output, " Description of ggg\n")); ok1(strstr(output, "-h|--hhh <arg>")); ok1(strstr(output, " Description of hhh\n")); ok1(strstr(output, "--kkk|-k")); ok1(strstr(output, "magic kkk option")); ok1(strstr(output, "--longname")); ok1(strstr(output, "a really long option default")); ok1(strstr(output, "(default: \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"...)")); ok1(strstr(output, "--shortname")); ok1(strstr(output, "a short option default")); ok1(strstr(output, "(default: \"shortname\")")); /* This entry is hidden. */ ok1(!strstr(output, "--mmm|-m")); free(output); reset_options(); /* Empty table test. */ output = opt_usage("nothing", NULL); ok1(strstr(output, "Usage: nothing \n")); free(output); /* No short args. */ opt_register_noarg("--aaa", test_noarg, NULL, "AAAAll"); output = opt_usage("onearg", NULL); ok1(strstr(output, "Usage: onearg \n")); ok1(strstr(output, "--aaa")); ok1(strstr(output, "AAAAll")); free(output); free(shortname); free(longname); return exit_status(); }
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; Update *update; struct bitcoin_tx *anchor, *commit; struct sha256_double anchor_txid; struct pkt *pkt; struct bitcoin_signature sig; EC_KEY *privkey; bool testnet; struct pubkey pubkey1, pubkey2; u8 *redeemscript; int64_t delta; size_t i, p2sh_out; err_set_progname(argv[0]); opt_register_noarg("--help|-h", opt_usage_and_exit, "<seed> <anchor-tx> <open-channel-file1> <open-channel-file2> <commit-privkey> <update-protobuf> [previous-updates]\n" "Accept a new update message", "Print this message."); opt_parse(&argc, argv, opt_log_stderr_exit); if (argc < 6) opt_usage_exit_fail("Expected 5+ arguments"); if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); anchor = bitcoin_tx_from_file(ctx, argv[2]); bitcoin_txid(anchor, &anchor_txid); o1 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; o2 = pkt_from_file(argv[4], PKT__PKT_OPEN)->open; privkey = key_from_base58(argv[5], strlen(argv[5]), &testnet, &pubkey1); if (!privkey) errx(1, "Invalid private key '%s'", argv[5]); if (!testnet) errx(1, "Private key '%s' not on testnet!", argv[5]); update = pkt_from_file(argv[6], PKT__PKT_UPDATE)->update; /* Figure out cumulative delta since anchor. */ delta = update->delta; for (i = 7; i < argc; i++) { Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update; delta += u->delta; } /* Get next revocation hash. */ shachain_from_seed(&seed, argc - 6, &revocation_hash); sha256(&revocation_hash, revocation_hash.u.u8, sizeof(revocation_hash.u.u8)); /* Get pubkeys */ if (!proto_to_pubkey(o1->anchor->pubkey, &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->anchor->pubkey, &pubkey2)) errx(1, "Invalid o2 final pubkey"); /* This is what the anchor pays to; figure out whick output. */ redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); p2sh_out = find_p2sh_out(anchor, redeemscript); /* Now create THEIR new commitment tx to spend 2/2 output of anchor. */ proto_to_sha256(update->revocation_hash, &their_rhash); commit = create_commit_tx(ctx, o2, o1, &their_rhash, delta, &anchor_txid, p2sh_out); /* 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; }
int main(int argc, char *argv[]) { OpenChannel *o1, *o2; struct bitcoin_tx *anchor; const tal_t *ctx = tal_arr(NULL, char, 0); u64 anchor_fee, amount, total_in, change; struct input *in; u8 *redeemscript; size_t i; struct pubkey pubkey1, pubkey2; err_set_progname(argv[0]); anchor_fee = 10000; opt_register_noarg("--help|-h", opt_usage_and_exit, "<open-channel-file1> <open-channel-file2> <amount> <changepubkey> <txid>/<outnum>/<satoshis>/<script-in-hex>/<privkey>...\n" "A test program to create an anchor tx on stdout.", "Print this message."); opt_register_arg("--anchor-fee=<bits>", opt_set_bits, opt_show_bits, &anchor_fee, "100's of satoshi to pay for anchor"); opt_register_version(); opt_parse(&argc, argv, opt_log_stderr_exit); if (argc < 6) opt_usage_exit_fail("Expected 5 or more arguments"); o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; 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"); amount = atol(argv[3]); if (!amount) errx(1, "Invalid total: must be > 0"); in = tal_arr(ctx, struct input, argc - 5); total_in = 0; for (i = 0; i < tal_count(in); i++) { parse_anchor_input(argv[5+i], &in[i]); total_in += in[i].in.input_amount; } if (total_in < amount + anchor_fee) errx(1, "Only %llu satoshi in, and %llu out (+%llu fee)", (unsigned long long)total_in, (unsigned long long)amount, (unsigned long long)anchor_fee); change = total_in - (amount + anchor_fee); /* If there's change, we have an extra output. */ anchor = bitcoin_tx(ctx, tal_count(in), change ? 2 : 1); anchor->fee = anchor_fee; /* Commitment redeems this via 2 of 2 payment. */ redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); /* Set up outputs. */ anchor->output[0].amount = amount; anchor->output[0].script = scriptpubkey_p2sh(anchor, redeemscript); anchor->output[0].script_length = tal_count(anchor->output[0].script); if (change) { struct pubkey change_key; if (!pubkey_from_hexstr(argv[4], &change_key)) errx(1, "Invalid change key %s", argv[3]); redeemscript = bitcoin_redeem_single(anchor, &change_key); anchor->output[1].amount = change; anchor->output[1].script = scriptpubkey_p2sh(anchor, redeemscript); anchor->output[1].script_length = tal_count(anchor->output[1].script); } /* Set up inputs (leaving scripts empty for signing) */ for (i = 0; i < tal_count(in); i++) { anchor->input[i].input_amount = in[i].in.input_amount; anchor->input[i].txid = in[i].in.txid; anchor->input[i].index = in[i].in.index; } /* Now, sign each input. */ for (i = 0; i < tal_count(in); i++) { in[i].sig.stype = SIGHASH_ALL; if (!sign_tx_input(ctx, anchor, i, in[i].in.script, in[i].in.script_length, &in[i].privkey, &in[i].pubkey, &in[i].sig.sig)) errx(1, "Error signing input %zi", i); } /* Finally, complete inputs using signatures. */ for (i = 0; i < tal_count(in); i++) { if (!is_pay_to_pubkey_hash(in[i].in.script, in[i].in.script_length)) errx(1, "FIXME: Don't know how to handle input %zi", i); anchor->input[i].script = scriptsig_pay_to_pubkeyhash(anchor, &in[i].pubkey, &in[i].sig); anchor->input[i].script_length = tal_count(anchor->input[i].script); } /* Print it out in hex. */ if (!bitcoin_tx_write(STDOUT_FILENO, anchor)) 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; char *result_end; struct sockaddr_un addr; jsmntok_t *toks; const jsmntok_t *result, *error, *id; char *pettycoin_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); 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; 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_PETTYCOIN, "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_PETTYCOIN, "Malformed response '%s'", resp); 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); 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; }
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, 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(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 char *myname = argv[0]; plan_tests(215); /* Simple short arg.*/ opt_register_noarg("-a", test_noarg, NULL, "All"); ok1(parse_args(&argc, &argv, "-a", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 1); /* Simple long arg. */ opt_register_noarg("--aaa", test_noarg, NULL, "AAAAll"); ok1(parse_args(&argc, &argv, "--aaa", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 2); /* Both long and short args. */ opt_register_noarg("--aaa|-a", test_noarg, NULL, "AAAAAAll"); ok1(parse_args(&argc, &argv, "--aaa", "-a", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 4); /* Extra arguments preserved. */ ok1(parse_args(&argc, &argv, "--aaa", "-a", "extra", "args", NULL)); ok1(argc == 3); ok1(argv[0] == myname); ok1(strcmp(argv[1], "extra") == 0); ok1(strcmp(argv[2], "args") == 0); ok1(test_cb_called == 6); /* Malformed versions. */ ok1(!parse_args(&argc, &argv, "--aaa=arg", NULL)); ok1(strstr(err_output, ": --aaa: doesn't allow an argument")); ok1(!parse_args(&argc, &argv, "--aa", NULL)); ok1(strstr(err_output, ": --aa: unrecognized option")); ok1(!parse_args(&argc, &argv, "--aaargh", NULL)); ok1(strstr(err_output, ": --aaargh: unrecognized option")); /* Argument variants. */ reset_options(); test_cb_called = 0; opt_register_arg("-a|--aaa", test_arg, NULL, "aaa", "AAAAAAll"); ok1(parse_args(&argc, &argv, "--aaa", "aaa", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(test_cb_called == 1); ok1(parse_args(&argc, &argv, "--aaa=aaa", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(test_cb_called == 2); ok1(parse_args(&argc, &argv, "-a", "aaa", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(test_cb_called == 3); /* Malformed versions. */ ok1(!parse_args(&argc, &argv, "-a", NULL)); ok1(strstr(err_output, ": -a: requires an argument")); ok1(!parse_args(&argc, &argv, "--aaa", NULL)); ok1(strstr(err_output, ": --aaa: requires an argument")); ok1(!parse_args(&argc, &argv, "--aa", NULL)); ok1(strstr(err_output, ": --aa: unrecognized option")); ok1(!parse_args(&argc, &argv, "--aaargh", NULL)); ok1(strstr(err_output, ": --aaargh: unrecognized option")); /* Now, tables. */ /* Short table: */ reset_options(); test_cb_called = 0; opt_register_table(short_table, NULL); ok1(parse_args(&argc, &argv, "-a", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 1); /* This one needs an arg. */ ok1(parse_args(&argc, &argv, "-b", NULL) == false); ok1(test_cb_called == 1); ok1(parse_args(&argc, &argv, "-b", "b", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 2); /* Long table: */ reset_options(); test_cb_called = 0; opt_register_table(long_table, NULL); ok1(parse_args(&argc, &argv, "--ddd", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 1); /* This one needs an arg. */ ok1(parse_args(&argc, &argv, "--eee", NULL) == false); ok1(test_cb_called == 1); ok1(parse_args(&argc, &argv, "--eee", "eee", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 2); /* Short and long, both. */ reset_options(); test_cb_called = 0; opt_register_table(long_and_short_table, NULL); ok1(parse_args(&argc, &argv, "-g", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 1); ok1(parse_args(&argc, &argv, "--ggg", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 2); /* This one needs an arg. */ ok1(parse_args(&argc, &argv, "-h", NULL) == false); ok1(test_cb_called == 2); ok1(parse_args(&argc, &argv, "-h", "hhh", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 3); ok1(parse_args(&argc, &argv, "--hhh", NULL) == false); ok1(test_cb_called == 3); ok1(parse_args(&argc, &argv, "--hhh", "hhh", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 4); /* Those will all work as tables. */ test_cb_called = 0; reset_options(); opt_register_table(subtables, NULL); ok1(parse_args(&argc, &argv, "-a", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 1); /* This one needs an arg. */ ok1(parse_args(&argc, &argv, "-b", NULL) == false); ok1(test_cb_called == 1); ok1(parse_args(&argc, &argv, "-b", "b", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 2); ok1(parse_args(&argc, &argv, "--ddd", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 3); /* This one needs an arg. */ ok1(parse_args(&argc, &argv, "--eee", NULL) == false); ok1(test_cb_called == 3); ok1(parse_args(&argc, &argv, "--eee", "eee", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 4); /* Short and long, both. */ ok1(parse_args(&argc, &argv, "-g", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 5); ok1(parse_args(&argc, &argv, "--ggg", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 6); /* This one needs an arg. */ ok1(parse_args(&argc, &argv, "-h", NULL) == false); ok1(test_cb_called == 6); ok1(parse_args(&argc, &argv, "-h", "hhh", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 7); ok1(parse_args(&argc, &argv, "--hhh", NULL) == false); ok1(test_cb_called == 7); ok1(parse_args(&argc, &argv, "--hhh", "hhh", NULL)); ok1(argc == 1); ok1(argv[0] == myname); ok1(argv[1] == NULL); ok1(test_cb_called == 8); /* Now the tricky one: -? must not be confused with an unknown option */ test_cb_called = 0; reset_options(); /* glibc's getopt does not handle ? with arguments. */ opt_register_noarg("-?", test_noarg, NULL, "Help"); ok1(parse_args(&argc, &argv, "-?", NULL)); ok1(test_cb_called == 1); ok1(parse_args(&argc, &argv, "-a", NULL) == false); ok1(test_cb_called == 1); ok1(strstr(err_output, ": -a: unrecognized option")); ok1(parse_args(&argc, &argv, "--aaaa", NULL) == false); ok1(test_cb_called == 1); ok1(strstr(err_output, ": --aaaa: unrecognized option")); test_cb_called = 0; reset_options(); /* Corner cases involving short arg parsing weirdness. */ opt_register_noarg("-a|--aaa", test_noarg, NULL, "a"); opt_register_arg("-b|--bbb", test_arg, NULL, "bbb", "b"); opt_register_arg("-c|--ccc", test_arg, NULL, "aaa", "c"); /* -aa == -a -a */ ok1(parse_args(&argc, &argv, "-aa", NULL)); ok1(test_cb_called == 2); ok1(parse_args(&argc, &argv, "-aab", NULL) == false); ok1(test_cb_called == 4); ok1(strstr(err_output, ": -b: requires an argument")); ok1(parse_args(&argc, &argv, "-bbbb", NULL)); ok1(test_cb_called == 5); ok1(parse_args(&argc, &argv, "-aabbbb", NULL)); ok1(test_cb_called == 8); ok1(parse_args(&argc, &argv, "-aabbbb", "-b", "bbb", NULL)); ok1(test_cb_called == 12); ok1(parse_args(&argc, &argv, "-aabbbb", "--bbb", "bbb", NULL)); ok1(test_cb_called == 16); ok1(parse_args(&argc, &argv, "-aabbbb", "--bbb=bbb", NULL)); ok1(test_cb_called == 20); ok1(parse_args(&argc, &argv, "-aacaaa", NULL)); ok1(test_cb_called == 23); ok1(parse_args(&argc, &argv, "-aacaaa", "-a", NULL)); ok1(test_cb_called == 27); ok1(parse_args(&argc, &argv, "-aacaaa", "--bbb", "bbb", "-aacaaa", NULL)); ok1(test_cb_called == 34); test_cb_called = 0; reset_options(); /* -- and POSIXLY_CORRECT */ opt_register_noarg("-a|--aaa", test_noarg, NULL, "a"); ok1(parse_args(&argc, &argv, "-a", "--", "-a", NULL)); ok1(test_cb_called == 1); ok1(argc == 2); ok1(strcmp(argv[1], "-a") == 0); ok1(!argv[2]); unsetenv("POSIXLY_CORRECT"); ok1(parse_args(&argc, &argv, "-a", "somearg", "-a", "--", "-a", NULL)); ok1(test_cb_called == 3); ok1(argc == 3); ok1(strcmp(argv[1], "somearg") == 0); ok1(strcmp(argv[2], "-a") == 0); ok1(!argv[3]); setenv("POSIXLY_CORRECT", "1", 1); ok1(parse_args(&argc, &argv, "-a", "somearg", "-a", "--", "-a", NULL)); ok1(test_cb_called == 4); ok1(argc == 5); ok1(strcmp(argv[1], "somearg") == 0); ok1(strcmp(argv[2], "-a") == 0); ok1(strcmp(argv[3], "--") == 0); ok1(strcmp(argv[4], "-a") == 0); ok1(!argv[5]); /* parse_args allocates argv */ free(argv); return exit_status(); }
int main(int argc, char *argv[]) { struct io_conn *conn = tal(NULL, struct io_conn); struct wireaddr_internal addr; int af = -1; struct pubkey us, them; const char *err_msg; const char *at; struct addrinfo *ai = NULL; setup_locale(); secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); opt_register_noarg("--initial-sync", opt_set_bool, &initial_sync, "Stream complete gossip history at start"); opt_register_arg("--max-messages", opt_set_ulongval, opt_show_ulongval, &max_messages, "Terminate after reading this many messages (> 0)"); opt_register_noarg("--stdin", opt_set_bool, &stream_stdin, "Stream gossip messages from stdin."); opt_register_noarg("--help|-h", opt_usage_and_exit, "id@addr[:port] [hex-msg-tosend...]\n" "Connect to a lightning peer and relay gossip messages from it", "Print this message."); opt_parse(&argc, argv, opt_log_stderr_exit); if (argc < 2) opt_usage_exit_fail("Need an id@addr to connect to"); at = strchr(argv[1], '@'); if (!at) opt_usage_exit_fail("Need id@addr"); if (!pubkey_from_hexstr(argv[1], at - argv[1], &them)) opt_usage_exit_fail("Invalid id %.*s", (int)(at - argv[1]), argv[1]); if (!parse_wireaddr_internal(at+1, &addr, DEFAULT_PORT, NULL, true, false, &err_msg)) opt_usage_exit_fail("%s '%s'", err_msg, argv[1]); switch (addr.itype) { case ADDR_INTERNAL_SOCKNAME: af = AF_LOCAL; ai = wireaddr_internal_to_addrinfo(conn, &addr); break; case ADDR_INTERNAL_ALLPROTO: case ADDR_INTERNAL_AUTOTOR: case ADDR_INTERNAL_FORPROXY: opt_usage_exit_fail("Don't support proxy use"); case ADDR_INTERNAL_WIREADDR: switch (addr.u.wireaddr.type) { case ADDR_TYPE_TOR_V2: case ADDR_TYPE_TOR_V3: opt_usage_exit_fail("Don't support proxy use"); break; case ADDR_TYPE_IPV4: af = AF_INET; break; case ADDR_TYPE_IPV6: af = AF_INET6; break; } ai = wireaddr_to_addrinfo(tmpctx, &addr.u.wireaddr); } if (af == -1 || ai == NULL) err(1, "Initializing socket"); conn->fd = socket(af, SOCK_STREAM, 0); if (conn->fd < 0) err(1, "Creating socket"); memset(¬sosecret, 0x42, sizeof(notsosecret)); if (!pubkey_from_secret(¬sosecret, &us)) errx(1, "Creating pubkey"); if (connect(conn->fd, ai->ai_addr, ai->ai_addrlen) != 0) err(1, "Connecting to %s", at+1); initiator_handshake(conn, &us, &them, &addr, handshake_success, argv+2); exit(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; }
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[]) { secp256k1_context *ctx; struct onion onion; bool generate = false, decode = false; assert(EVP_CIPHER_iv_length(EVP_aes_128_ctr()) == sizeof(struct iv)); opt_register_noarg("--help|-h", opt_usage_and_exit, "--generate <pubkey>... OR\n" "--decode <privkey>\n" "Either create an onion message, or decode one step", "Print this message."); opt_register_noarg("--generate", opt_set_bool, &generate, "Generate onion through the given hex pubkeys"); opt_register_noarg("--decode", opt_set_bool, &decode, "Decode onion given the private key"); opt_register_version(); opt_parse(&argc, argv, opt_log_stderr_exit); ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); if (generate) { secp256k1_pubkey pubkeys[MAX_HOPS]; char *msgs[MAX_HOPS]; size_t i; if (argc == 1) opt_usage_exit_fail("Expected at least one pubkey"); if (argc-1 > MAX_HOPS) opt_usage_exit_fail("Expected at most %u pubkeys", MAX_HOPS); for (i = 1; i < argc; i++) { if (!parse_onion_pubkey(ctx, argv[i], &pubkeys[i-1])) errx(1, "Bad pubkey '%s'", argv[i]); msgs[i-1] = make_message(ctx, &pubkeys[i-1]); } if (!create_onion(pubkeys, msgs, argc - 1, &onion)) errx(1, "Creating onion packet failed"); if (!write_all(STDOUT_FILENO, &onion, sizeof(onion))) err(1, "Writing onion packet"); return 0; } else if (decode) { struct seckey seckey; secp256k1_pubkey pubkey; struct enckey enckey; struct iv pad_iv; if (argc != 2) opt_usage_exit_fail("Expect a privkey with --decode"); if (!hex_decode(argv[1], strlen(argv[1]), &seckey, sizeof(seckey))) errx(1, "Invalid private key hex '%s'", argv[1]); if (!secp256k1_ec_pubkey_create(ctx, &pubkey, seckey.u.u8)) errx(1, "Invalid private key '%s'", argv[1]); if (!read_all(STDIN_FILENO, &onion, sizeof(onion))) errx(1, "Reading in onion"); if (!decrypt_onion(&seckey, &onion, &enckey, &pad_iv)) errx(1, "Failed decrypting onion for '%s'", argv[1]); if (strncmp((char *)myhop(&onion)->msg, make_message(ctx, &pubkey), sizeof(myhop(&onion)->msg))) errx(1, "Bad message '%s'", (char *)myhop(&onion)->msg); if (!peel_onion(&onion, &enckey, &pad_iv)) errx(1, "Peeling onion for '%s'", argv[1]); if (!write_all(STDOUT_FILENO, &onion, sizeof(onion))) err(1, "Writing onion packet"); return 0; } else opt_usage_exit_fail("Need --decode or --generate"); secp256k1_context_destroy(ctx); return 0; }
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; uint64_t our_amount, their_amount; 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_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. */ gather_updates(o1, o2, a, close->close_fee, argv + 6, &our_amount, &their_amount, 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, our_amount, their_amount); /* 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; }
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; }