diff --git a/lightningd/test/Makefile b/lightningd/test/Makefile index e211e1ede..f6935e7e9 100644 --- a/lightningd/test/Makefile +++ b/lightningd/test/Makefile @@ -33,3 +33,5 @@ lightningd-test-shutdown-2: lightningd-test-2-basic\ --reconnect VARIANT=2 daemon/test/scripts/shutdown.sh lightningd-blackbox-tests: lightningd-test-shutdown-0 #lightningd-test-shutdown-1 lightningd-test-shutdown-2 + +check-source-bolt: $(LIGHTNINGD_TEST_SRC:%=bolt-check/%) diff --git a/lightningd/test/run-commit_tx.c b/lightningd/test/run-commit_tx.c new file mode 100644 index 000000000..2a4e8aee1 --- /dev/null +++ b/lightningd/test/run-commit_tx.c @@ -0,0 +1,829 @@ +#include "../key_derive.c" +#include +#include +#include +static bool print_superverbose; +#define SUPERVERBOSE(...) \ + do { if (print_superverbose) printf(__VA_ARGS__); } while(0) +#include "../commit_tx.c" +#include "../htlc_tx.c" +#include +#include +#include +#include +#include + +static struct sha256 sha256_from_hex(const char *hex) +{ + struct sha256 sha256; + if (strstarts(hex, "0x")) + hex += 2; + if (!hex_decode(hex, strlen(hex), &sha256, sizeof(sha256))) + abort(); + return sha256; +} + +/* bitcoind loves its backwards txids! */ +static struct sha256_double txid_from_hex(const char *hex) +{ + struct sha256_double sha256; + struct sha256 rev = sha256_from_hex(hex); + size_t i; + + for (i = 0; i < sizeof(rev); i++) + sha256.sha.u.u8[sizeof(sha256) - 1 - i] = rev.u.u8[i]; + return sha256; +} + +static struct privkey privkey_from_hex(const char *hex) +{ + struct privkey pk; + size_t len; + if (strstarts(hex, "0x")) + hex += 2; + len = strlen(hex); + /* BOLT #3: + * + * private keys are displayed as 32 bytes plus a trailing 1 (bitcoin's + * convention for "compressed" private keys, i.e. keys for which the + * public key is compressed) + */ + if (len == 66 && strends(hex, "01")) + len -= 2; + if (!hex_decode(hex, len, &pk, sizeof(pk))) + abort(); + return pk; +} + +/* BOLT #3: + * + * htlc 0 direction: remote->local + * htlc 0 amount_msat: 1000000 + * htlc 0 expiry: 500 + * htlc 0 payment_preimage: 0000000000000000000000000000000000000000000000000000000000000000 + * htlc 1 direction: remote->local + * htlc 1 amount_msat: 2000000 + * htlc 1 expiry: 501 + * htlc 1 payment_preimage: 0101010101010101010101010101010101010101010101010101010101010101 + * htlc 2 direction: local->remote + * htlc 2 amount_msat: 2000000 + * htlc 2 expiry: 502 + * htlc 2 payment_preimage: 0202020202020202020202020202020202020202020202020202020202020202 + * htlc 3 direction: local->remote + * htlc 3 amount_msat: 3000000 + * htlc 3 expiry: 503 + * htlc 3 payment_preimage: 0303030303030303030303030303030303030303030303030303030303030303 + * htlc 4 direction: remote->local + * htlc 4 amount_msat: 4000000 + * htlc 4 expiry: 504 + * htlc 4 payment_preimage: 0404040404040404040404040404040404040404040404040404040404040404 + */ +static const struct htlc **setup_htlcs(const tal_t *ctx) +{ + const struct htlc **htlcs = tal_arr(ctx, const struct htlc *, 5); + int i; + + for (i = 0; i < 5; i++) { + struct htlc *htlc = tal(htlcs, struct htlc); + + htlc->id = i; + switch (i) { + case 0: + htlc->state = RCVD_ADD_ACK_REVOCATION; + htlc->msatoshi = 1000000; + break; + case 1: + htlc->state = RCVD_ADD_ACK_REVOCATION; + htlc->msatoshi = 2000000; + break; + case 2: + htlc->state = SENT_ADD_ACK_REVOCATION; + htlc->msatoshi = 2000000; + break; + case 3: + htlc->state = SENT_ADD_ACK_REVOCATION; + htlc->msatoshi = 3000000; + break; + case 4: + htlc->state = RCVD_ADD_ACK_REVOCATION; + htlc->msatoshi = 4000000; + break; + } + + + if (i == 0 || i == 1 || i == 4) { + /* direction: remote->local */ + + } else { + /* direction: local->remote */ + htlc->state = SENT_ADD_ACK_REVOCATION; + } + htlc->expiry.locktime = 500 + i; + htlc->r = tal(htlc, struct preimage); + memset(htlc->r, i, sizeof(*htlc->r)); + sha256(&htlc->rhash, htlc->r, sizeof(*htlc->r)); + htlcs[i] = htlc; + } + return htlcs; +} + +#if 0 +static struct pubkey pubkey_from_hex(const char *hex) +{ + struct pubkey pubkey; + + if (strstarts(hex, "0x")) + hex += 2; + if (!pubkey_from_hexstr(hex, strlen(hex), &pubkey)) + abort(); + return pubkey; +} +#endif + +static void report_htlcs(const struct bitcoin_tx *tx, + const struct htlc **htlc_map, + u16 to_self_delay, + const struct privkey *local_secretkey, + const struct pubkey *localkey, + const struct pubkey *local_delayedkey, + const struct privkey *x_remote_secretkey, + const struct pubkey *remotekey, + const struct pubkey *local_revocation_key, + u64 feerate_per_kw) +{ + tal_t *tmpctx = tal_tmpctx(NULL); + size_t i, n; + struct sha256_double txid; + struct bitcoin_tx **htlc_tx; + secp256k1_ecdsa_signature *remotesig; + u8 **wscript; + + htlc_tx = tal_arrz(tmpctx, struct bitcoin_tx *, tal_count(htlc_map)); + remotesig = tal_arr(tmpctx, secp256k1_ecdsa_signature, + tal_count(htlc_map)); + wscript = tal_arr(tmpctx, u8 *, tal_count(htlc_map)); + + bitcoin_txid(tx, &txid); + + /* First report remote signatures, in order we would receive them. */ + n = 0; + for (i = 0; i < tal_count(htlc_map); i++) + n += (htlc_map[i] != NULL); + + printf("num_htlcs: %zu\n", n); + + for (i = 0; i < tal_count(htlc_map); i++) { + const struct htlc *htlc = htlc_map[i]; + + if (!htlc) + continue; + + if (htlc_owner(htlc) == LOCAL) { + htlc_tx[i] = htlc_timeout_tx(htlc_tx, &txid, i, + htlc, to_self_delay, + local_revocation_key, + local_delayedkey, + feerate_per_kw); + wscript[i] = bitcoin_wscript_htlc_offer(tmpctx, + localkey, + remotekey, + &htlc->rhash); + } else { + htlc_tx[i] = htlc_success_tx(htlc_tx, &txid, i, + htlc, to_self_delay, + local_revocation_key, + local_delayedkey, + feerate_per_kw); + wscript[i] = bitcoin_wscript_htlc_receive(tmpctx, + &htlc->expiry, + localkey, + remotekey, + &htlc->rhash); + } + sign_tx_input(htlc_tx[i], 0, + NULL, + wscript[i], + x_remote_secretkey, remotekey, + &remotesig[i]); + printf("# signature for output %zi (htlc %zu)\n", i, htlc->id); + printf("remote_htlc_signature = %s\n", + type_to_string(tmpctx, secp256k1_ecdsa_signature, + &remotesig[i])); + } + + /* For any HTLC outputs, produce htlc_tx */ + for (i = 0; i < tal_count(htlc_map); i++) { + secp256k1_ecdsa_signature localsig; + const struct htlc *htlc = htlc_map[i]; + + if (!htlc) + continue; + + sign_tx_input(htlc_tx[i], 0, + NULL, + wscript[i], + local_secretkey, localkey, + &localsig); + printf("# local_signature = %s\n", + type_to_string(tmpctx, secp256k1_ecdsa_signature, + &localsig)); + if (htlc_owner(htlc) == LOCAL) { + htlc_timeout_tx_add_witness(htlc_tx[i], + localkey, remotekey, + &htlc->rhash, + &localsig, &remotesig[i]); + } else { + htlc_success_tx_add_witness(htlc_tx[i], + &htlc->expiry, + localkey, remotekey, + &localsig, &remotesig[i], + htlc->r); + } + printf("output htlc_%s_tx %"PRIu64": %s\n", + htlc_owner(htlc) == LOCAL ? "timeout" : "success", + htlc->id, + tal_hex(tmpctx, linearize_tx(tmpctx, htlc_tx[i]))); + } + tal_free(tmpctx); +} + +static void report(struct bitcoin_tx *tx, + const u8 *wscript, + const struct privkey *x_remote_funding_privkey, + const struct pubkey *remote_funding_pubkey, + const struct privkey *local_funding_privkey, + const struct pubkey *local_funding_pubkey, + u16 to_self_delay, + const struct privkey *local_secretkey, + const struct pubkey *localkey, + const struct pubkey *local_delayedkey, + const struct privkey *x_remote_secretkey, + const struct pubkey *remotekey, + const struct pubkey *local_revocation_key, + u64 feerate_per_kw, + const struct htlc **htlc_map) +{ + tal_t *tmpctx = tal_tmpctx(NULL); + char *txhex; + secp256k1_ecdsa_signature localsig, remotesig; + + sign_tx_input(tx, 0, + NULL, + wscript, + x_remote_funding_privkey, remote_funding_pubkey, + &remotesig); + printf("remote_signature = %s\n", + type_to_string(tmpctx, secp256k1_ecdsa_signature, &remotesig)); + sign_tx_input(tx, 0, + NULL, + wscript, + local_funding_privkey, local_funding_pubkey, + &localsig); + printf("# local_signature = %s\n", + type_to_string(tmpctx, secp256k1_ecdsa_signature, &localsig)); + tx->input[0].witness = bitcoin_witness_2of2(tx->input, + &localsig, &remotesig, + local_funding_pubkey, + remote_funding_pubkey); + txhex = tal_hex(tmpctx, linearize_tx(tx, tx)); + printf("output commit_tx: %s\n", txhex); + + report_htlcs(tx, htlc_map, to_self_delay, + local_secretkey, localkey, + local_delayedkey, + x_remote_secretkey, + remotekey, + local_revocation_key, + feerate_per_kw); + tal_free(tmpctx); +} + +#ifdef DEBUG +static u64 calc_fee(const struct bitcoin_tx *tx, u64 input_satoshi) +{ + size_t i; + u64 output_satoshi = 0; + + for (i = 0; i < tal_count(tx->output); i++) + output_satoshi += tx->output[i].amount; + + return input_satoshi - output_satoshi; +} + +/* For debugging, we do brute-force increase to find thresholds */ +static u64 increase(u64 feerate_per_kw) +{ + return feerate_per_kw + 1; +} +#else +static u64 increase(u64 feerate_per_kw) +{ + switch (feerate_per_kw) { + case 0: + return 679; + case 679: + return 2169; + case 2169: + return 2295; + case 2295: + return 3873; + case 3873: + return 5150; + case 5150: + return 9651181; + default: + abort(); + } +} +#endif + +int main(void) +{ + tal_t *tmpctx = tal_tmpctx(NULL); + struct sha256_double funding_txid; + u64 funding_amount_satoshi, dust_limit_satoshi, feerate_per_kw; + u16 to_self_delay; + /* x_ prefix means internal vars we used to derive spec */ + struct privkey local_funding_privkey, x_remote_funding_privkey; + struct privkey x_local_payment_basepoint_secret, x_remote_payment_basepoint_secret; + struct privkey x_local_per_commitment_secret, x_remote_per_commitment_secret; + struct privkey x_local_delayed_payment_basepoint_secret; + struct privkey x_local_revocation_basepoint_secret; + struct privkey local_secretkey, x_remote_secretkey; + struct privkey x_local_delayed_secretkey; + struct pubkey local_funding_pubkey, remote_funding_pubkey; + struct pubkey local_payment_basepoint, remote_payment_basepoint; + struct pubkey x_local_delayed_payment_basepoint; + struct pubkey x_local_revocation_basepoint; + struct pubkey x_local_per_commitment_point, + x_remote_per_commitment_point; + struct pubkey localkey, remotekey, tmpkey; + struct pubkey local_delayedkey; + struct pubkey local_revocation_key; + struct bitcoin_tx *tx; + u8 *wscript; + unsigned int funding_output_index; + u64 commitment_number, cn_obscurer, to_local_msat, to_remote_msat; + const struct htlc **htlcs = setup_htlcs(tmpctx), **htlc_map; + + secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY + | SECP256K1_CONTEXT_SIGN); + + /* BOLT #3: + * + * # Appendix C: Commitment and HTLC Transaction Test Vectors + * + * In the following: + * - we consider *local* transactions, which implies that all payments + * to *local* are delayed + * - we assume that *local* is the funder + * - private keys are displayed as 32 bytes plus a trailing 1 + * (bitcoin's convention for "compressed" private keys, i.e. keys + * for which the public key is compressed) + * + * - transaction signatures are all deterministic, using + * RFC6979 (using HMAC-SHA256) + * + * We start by defining common basic parameters for each test vector: + * the HTLCs are not used for the first "simple commitment tx with no + * HTLCs" test. + * + * funding_tx_id: 8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be + * funding_output_index: 0 + * funding_amount_satoshi: 10000000 + * commitment_number: 42 + * local_delay: 144 + * local_dust_limit_satoshi: 546 + */ + funding_txid = txid_from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be"); + funding_output_index = 0; + funding_amount_satoshi = 10000000; + commitment_number = 42; + to_self_delay = 144; + dust_limit_satoshi = 546; + +#ifdef DEBUG + print_superverbose = true; +#endif + + /* BOLT #3: + * + *