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[]) { 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; }
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); }