BitcoinPubkey *pubkey_to_proto(const tal_t *ctx, const struct pubkey *key)
{
	BitcoinPubkey *p = tal(ctx, BitcoinPubkey);
	struct pubkey check;

	bitcoin_pubkey__init(p);
	p->key.len = pubkey_derlen(key);
	p->key.data = tal_dup_arr(p, u8, key->der, p->key.len, 0);

	{
		secp256k1_context *secpctx = secp256k1_context_create(0);
		assert(pubkey_from_der(secpctx, p->key.data, p->key.len, &check));
		assert(pubkey_eq(&check, key));
		secp256k1_context_destroy(secpctx);
	}
	return p;
}
Пример #2
0
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;
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
0
int main(void)
{
	setup_locale();

	struct privkey privkey;
	struct secret base_secret, per_commitment_secret;
	struct pubkey base_point, per_commitment_point, pubkey, pubkey2;

	setup_tmpctx();
	secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
						 | SECP256K1_CONTEXT_SIGN);

	base_secret = secret_from_hex("0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
	per_commitment_secret = secret_from_hex("0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100");

	printf("base_secret: 0x%s\n",
	       tal_hexstr(tmpctx, &base_secret, sizeof(base_secret)));
	printf("per_commitment_secret: 0x%s\n",
	       tal_hexstr(tmpctx, &per_commitment_secret,
			  sizeof(per_commitment_secret)));
	if (!secp256k1_ec_pubkey_create(secp256k1_ctx,
					&per_commitment_point.pubkey,
					per_commitment_secret.data))
		abort();
	if (!secp256k1_ec_pubkey_create(secp256k1_ctx,
					&base_point.pubkey,
					base_secret.data))
		abort();
	printf("base_point: 0x%s\n",
	       type_to_string(tmpctx, struct pubkey, &base_point));
	printf("per_commitment_point: 0x%s\n",
	       type_to_string(tmpctx, struct pubkey, &per_commitment_point));

	/* FIXME: Annotate internal steps. */
	if (!derive_simple_key(&base_point, &per_commitment_point, &pubkey))
		abort();
	printf("localkey: 0x%s\n",
	       type_to_string(tmpctx, struct pubkey, &pubkey));
	if (!derive_simple_privkey(&base_secret, &base_point,
				   &per_commitment_point, &privkey))
		abort();
	printf("localprivkey: 0x%s\n",
	       tal_hexstr(tmpctx, &privkey, sizeof(privkey)));
	pubkey_from_privkey(&privkey, &pubkey2);
	assert(pubkey_eq(&pubkey, &pubkey2));

	/* FIXME: Annotate internal steps. */
	if (!derive_revocation_key(&base_point, &per_commitment_point, &pubkey))
		abort();
	printf("revocationkey: 0x%s\n",
	       type_to_string(tmpctx, struct pubkey, &pubkey));
	if (!derive_revocation_privkey(&base_secret, &per_commitment_secret,
				       &base_point, &per_commitment_point,
				       &privkey))
		abort();
	printf("revocationprivkey: 0x%s\n",
	       tal_hexstr(tmpctx, &privkey, sizeof(privkey)));
	pubkey_from_privkey(&privkey, &pubkey2);
	assert(pubkey_eq(&pubkey, &pubkey2));

	/* No memory leaks please */
	secp256k1_context_destroy(secp256k1_ctx);
	tal_free(tmpctx);
	return 0;
}