From 9ec670a3496d50e0f76edb173059bd37622eb8f6 Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Thu, 14 May 2020 11:12:11 -0700 Subject: [PATCH] Added NewChannel and ReadyChannel support. Added warmstart flag to Init. Changed "warmstart" to "coldstart" (inverted semantic). Modified all satoshi variable names to have "_sat" suffixes. Removed deprecated Phase 1 fields. Added push_value to hsm_ready_channel. Added sanity checking to hsm_ready_channel stub. Fixed issues w/ rebase onto upstream/master. Replaced tx->input_amounts and tx->output_witscripts with tx->psbt. Fixed redeemscript confusion. (#11) Fix remote-hsmd CI (#12) * adding g++, protobuf, grpc++ * add libgrpc++-dev to .travis.yml * wget remotesigner.proto * added libprotobuf-dev * fixed compilation warnings/errors * use Get instead of [] in protobuf seq * fixed include sort order * added protobuf generated files to skip nogen checks * fixed gensrc pattern * added libstdc++6 * fixed python spacing * added specified inclusion guards * renamed c++ header extensions to hpp to avoid c checks * guard satoshi amount calculations * libstdc++-6-dev * added `ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6 /usr/lib/x86_64-linux-gnu/libstdc++.so` Enable handle_sign_withdrawal_tx signing of PSBT. (#13) * Converted debug logging to json format. * Switched status_debug to STATUS_DEBUG macro. Skip two integration tests which mutate channel_nonce. fixed nit w/ run-one-test Added NodeConfig::NATIVE to InitReq. (#14) Converted remotesigner.PubKey from 64 byte raw to 33 byte compressed DER. (#15) Updated to channel_nonce0. (#17) Replaced option_static_remotekey w/ CommitmentType. (#18) * Replaced option_static_remotekey w/ CommitmentType. * Improved NOTES Upgraded SignFundingTxRequest KeyIndex to KeyPath. (#19) Adapted to CloseInfo moving into KeyLocator TxOut was replaced in API w/ it's only field. Adapted to remotesigner api-doc mods. Set input to 0 explicitly. SignCounterpartyHtlcToUs -> SignCounterpartyHtlcSweep SignJusticeTxToUs -> SignJusticeSweep SignDelayedPaymentToUs -> SignDelayedSweep (#20) --- .github/scripts/build.sh | 2 + contrib/pyln-testing/pyln/testing/utils.py | 1 + contrib/remote_hsmd/Makefile | 6 +- contrib/remote_hsmd/NOTES.md | 31 +- contrib/remote_hsmd/capabilities.h | 6 +- contrib/remote_hsmd/dump.cc | 292 +++++++--- contrib/remote_hsmd/{dump.h => dump.hpp} | 15 +- contrib/remote_hsmd/hsmd.c | 284 +++++---- contrib/remote_hsmd/proxy.cc | 641 ++++++++++++--------- contrib/remote_hsmd/{proxy.h => proxy.hpp} | 41 +- contrib/remote_hsmd/scripts/run-one-test | 15 +- hsmd/hsmd.c | 80 +++ hsmd/hsmd_wire.csv | 33 ++ openingd/openingd.c | 40 ++ tests/test_db.py | 2 + 15 files changed, 986 insertions(+), 503 deletions(-) rename contrib/remote_hsmd/{dump.h => dump.hpp} (74%) rename contrib/remote_hsmd/{proxy.h => proxy.hpp} (80%) diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh index 39b8d431a698..f2919cf47145 100755 --- a/.github/scripts/build.sh +++ b/.github/scripts/build.sh @@ -36,6 +36,8 @@ pip3 install --user -U \ git clone https://github.com/lightningnetwork/lightning-rfc.git ../lightning-rfc git submodule update --init --recursive +wget -q --directory-prefix=contrib/remote_hsmd https://gitlab.com/lightning-signer/rust-lightning-signer/-/raw/master/src/server/remotesigner.proto + ./configure CC="$CC" cat config.vars diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py index 141501d4b009..ad069b94bca5 100644 --- a/contrib/pyln-testing/pyln/testing/utils.py +++ b/contrib/pyln-testing/pyln/testing/utils.py @@ -81,6 +81,7 @@ def env(name, default=None): TIMEOUT = int(env("TIMEOUT", 180 if SLOW_MACHINE else 60)) SUBDAEMON = env("SUBDAEMON", "") + def wait_for(success, timeout=TIMEOUT): start_time = time.time() interval = 0.25 diff --git a/contrib/remote_hsmd/Makefile b/contrib/remote_hsmd/Makefile index 7ae6439543d4..870b69b5c1dc 100644 --- a/contrib/remote_hsmd/Makefile +++ b/contrib/remote_hsmd/Makefile @@ -37,6 +37,7 @@ RMTHSMD_COMMON_OBJS := \ common/amount.o \ common/bigsize.o \ common/bip32.o \ + common/channel_id.o \ common/daemon.o \ common/daemon_conn.o \ common/derive_basepoints.o \ @@ -48,6 +49,7 @@ RMTHSMD_COMMON_OBJS := \ common/msg_queue.o \ common/node_id.o \ common/permute_tx.o \ + common/setup.o \ common/status.o \ common/status_wire.o \ common/subdaemon.o \ @@ -58,8 +60,8 @@ RMTHSMD_COMMON_OBJS := \ common/withdraw_tx.o # For checking -LIGHTNINGD_RMTHSM_ALLSRC_NOGEN := $(filter-out contrib/remote_hsmd/gen_%, $(LIGHTNINGD_RMTHSM_SRC) $(LIGHTNINGD_RMTHSM_SRC)) -LIGHTNINGD_RMTHSM_ALLHEADERS_NOGEN := $(filter-out contrib/remote_hsmd/gen_%, $(LIGHTNINGD_RMTHSM_HEADERS)) +LIGHTNINGD_RMTHSM_ALLSRC_NOGEN := $(filter-out contrib/remote_hsmd/gen_% contrib/remote_hsmd/remotesigner.%, $(LIGHTNINGD_RMTHSM_SRC) $(LIGHTNINGD_RMTHSM_SRC)) +LIGHTNINGD_RMTHSM_ALLHEADERS_NOGEN := $(filter-out contrib/remote_hsmd/gen_% contrib/remote_hsmd/remotesigner.%, $(LIGHTNINGD_RMTHSM_HEADERS)) $(LIGHTNINGD_RMTHSM_OBJS): $(LIGHTNINGD_HEADERS) diff --git a/contrib/remote_hsmd/NOTES.md b/contrib/remote_hsmd/NOTES.md index e09c43c65707..4d8d204d4530 100644 --- a/contrib/remote_hsmd/NOTES.md +++ b/contrib/remote_hsmd/NOTES.md @@ -3,11 +3,12 @@ c-lightning Setup - cd contrib/remote_hsmd && \ - ln -s /path/to/rust-lightning-signer/src/server/remotesigner.proto + (cd contrib/remote_hsmd && \ + ln -s ../../../rust-lightning-signer/src/server/remotesigner.proto) Building + make distclean ./configure --enable-developer make @@ -19,6 +20,10 @@ https://github.com/golemfactory/golem/issues/2168 for background. pip3 install --user base58 pip3 install --user bitstring pip3 install --user secp256k1 + pip3 install --user mrkd + + # in c-lightning root: + pip3 install --user -r requirements.txt Run all of the integration tests: @@ -82,25 +87,3 @@ rust-lightning-signer ---------------------------------------------------------------- cargo run --bin server |& tee log3 - - -Signing Formats -``` -rust-lightning c-lightning rust-lightning-signer -p2pkh P2PKH -p2sh -p2wpkh p2wpkh P2WPKH -p2shwpkh p2sh-p2wpkh P2SH_P2WPKH -p2wsh -p2shwsh -``` - - -Failing tests after removing seed from hsmd: -``` - export THETEST=tests/test_misc.py::test_blockchaintrack - export THETEST=tests/test_misc.py::test_new_node_is_mainnet - export THETEST=tests/test_misc.py::test_getsharedsecret - export THETEST=tests/test_wallet.py::test_hsm_secret_encryption - export THETEST=tests/test_wallet.py::test_hsmtool_secret_decryption -``` diff --git a/contrib/remote_hsmd/capabilities.h b/contrib/remote_hsmd/capabilities.h index 3a306e778a2a..3c139c26de70 100644 --- a/contrib/remote_hsmd/capabilities.h +++ b/contrib/remote_hsmd/capabilities.h @@ -1,5 +1,5 @@ -#ifndef LIGHTNING_HSMD_CAPABILITIES_H -#define LIGHTNING_HSMD_CAPABILITIES_H +#ifndef LIGHTNING_CONTRIB_REMOTE_HSMD_CAPABILITIES_H +#define LIGHTNING_CONTRIB_REMOTE_HSMD_CAPABILITIES_H #define HSM_CAP_ECDH 1 #define HSM_CAP_SIGN_GOSSIP 2 @@ -9,4 +9,4 @@ #define HSM_CAP_SIGN_CLOSING_TX 32 #define HSM_CAP_MASTER 1024 -#endif /* LIGHTNING_HSMD_CAPABILITIES_H */ +#endif /* LIGHTNING_CONTRIB_REMOTE_HSMD_CAPABILITIES_H */ diff --git a/contrib/remote_hsmd/dump.cc b/contrib/remote_hsmd/dump.cc index 2386c0764e40..41d8db03640c 100644 --- a/contrib/remote_hsmd/dump.cc +++ b/contrib/remote_hsmd/dump.cc @@ -1,5 +1,4 @@ -#include -#include +#include "contrib/remote_hsmd/dump.hpp" extern "C" { #include @@ -11,28 +10,36 @@ extern "C" { #include #include #include -#include +} +#include +#include +extern "C" { #include } -#include "contrib/remote_hsmd/dump.h" using std::ostringstream; using std::string; +bool pubkey_is_compressed(const unsigned char pubkey[EC_PUBLIC_KEY_UNCOMPRESSED_LEN]) { + return pubkey[0] == 0x02 || pubkey[0] == 0x03; +} + /* type_to_string has issues in the C++ environment, use this to dump binary data as hex instead. */ string dump_hex(const void *vptr, size_t sz) { static const char hex[] = "0123456789abcdef"; - string retval(sz*2, '\0'); + ostringstream ostrm; + ostrm << '"'; uint8_t const * ptr = (uint8_t const *) vptr; for (size_t ii = 0; ii < sz; ++ii) { - retval[ii*2+0] = hex[(*ptr) >> 4]; - retval[ii*2+1] = hex[(*ptr) & 0xf]; - ptr++; + ostrm << hex[(*ptr) >> 4] + << hex[(*ptr) & 0xf]; + ++ptr; } - return retval; + ostrm << '"'; + return ostrm.str(); } string dump_bitcoin_txid(const struct bitcoin_txid *txid) @@ -44,8 +51,9 @@ string dump_bitcoin_signature(const struct bitcoin_signature *sp) { ostringstream ostrm; ostrm << "{ " - << "sighash_type=" << int(sp->sighash_type) - << "s=" << dump_secp256k1_ecdsa_signature(&sp->s) + << "\"sighash_type\":" << int(sp->sighash_type) + << ", \"s\":" + << '"' << dump_secp256k1_ecdsa_signature(&sp->s) << '"' << " }"; return ostrm.str(); } @@ -92,11 +100,11 @@ string dump_witnesses(const u8 ***wp) ostrm << "["; for (size_t input_ndx = 0; input_ndx < tal_count(wp); ++input_ndx) { if (input_ndx != 0) - ostrm << " "; + ostrm << ", "; ostrm << "["; u8 const *sig = wp[input_ndx][0]; ostrm << dump_hex(sig, tal_count(sig)); - ostrm << " "; + ostrm << ", "; u8 const *pubkey = wp[input_ndx][1]; ostrm << dump_hex(pubkey, tal_count(pubkey)); ostrm << "]"; @@ -109,10 +117,10 @@ string dump_basepoints(const struct basepoints *bp) { ostringstream ostrm; ostrm << "{ "; - ostrm << "revocation=" << dump_pubkey(&bp->revocation); - ostrm << ", payment=" << dump_pubkey(&bp->payment); - ostrm << ", htlc=" << dump_pubkey(&bp->htlc); - ostrm << ", delayed_payment=" << dump_pubkey(&bp->delayed_payment); + ostrm << "\"revocation\":" << dump_pubkey(&bp->revocation); + ostrm << ", \"payment\":" << dump_pubkey(&bp->payment); + ostrm << ", \"htlc\":" << dump_pubkey(&bp->htlc); + ostrm << ", \"delayed_payment\":" << dump_pubkey(&bp->delayed_payment); ostrm << " }"; return ostrm.str(); } @@ -121,11 +129,11 @@ string dump_unilateral_close_info(const struct unilateral_close_info *ip) { ostringstream ostrm; ostrm << "{ "; - ostrm << "channel_id=" << ip->channel_id; - ostrm << ", peer_id=" << dump_node_id(&ip->peer_id); - ostrm << ", commitment_point=" << + ostrm << "\"channel_id\":" << ip->channel_id; + ostrm << ", \"peer_id\":" << dump_node_id(&ip->peer_id); + ostrm << ", \"commitment_point\":" << (ip->commitment_point ? dump_pubkey(ip->commitment_point) : - ""); + "\"\""); ostrm << " }"; return ostrm.str(); } @@ -134,15 +142,15 @@ string dump_utxo(const struct utxo *in) { ostringstream ostrm; ostrm << "{ "; - ostrm << "txid=" << dump_bitcoin_txid(&in->txid); - ostrm << ", outnum=" << in->outnum; - ostrm << ", amount=" << in->amount.satoshis; - ostrm << ", keyindex=" << in->keyindex; - ostrm << ", is_p2sh=" << in->is_p2sh; - ostrm << ", close_info=" << + ostrm << "\"txid\":" << dump_bitcoin_txid(&in->txid); + ostrm << ", \"outnum\":" << in->outnum; + ostrm << ", \"amount\":" << in->amount.satoshis; + ostrm << ", \"keyindex\":" << in->keyindex; + ostrm << ", \"is_p2sh\":" << in->is_p2sh; + ostrm << ", \"close_info\":" << (in->close_info ? dump_unilateral_close_info(in->close_info) : - ""); + "\"\""); ostrm << " }"; return ostrm.str(); } @@ -164,9 +172,9 @@ string dump_bitcoin_tx_output(const struct bitcoin_tx_output *op) { ostringstream ostrm; ostrm << "{ "; - ostrm << "amount=" << op->amount.satoshis; - ostrm << ", script=" << - (op->script ? dump_hex(op->script, tal_count(op->script)) : ""); + ostrm << "\"amount\":" << op->amount.satoshis; + ostrm << ", \"script\":" << + (op->script ? dump_hex(op->script, tal_count(op->script)) : "\"\""); ostrm << " }"; return ostrm.str(); } @@ -184,30 +192,106 @@ string dump_bitcoin_tx_outputs(const struct bitcoin_tx_output **outputs) return ostrm.str(); } -string dump_input_amounts(const struct amount_sat **ias) +string dump_wally_tx_witness_stack(const struct wally_tx_witness_stack *sp) +{ + if (sp == NULL) + return "[]"; + ostringstream ostrm; + ostrm << "["; + for (size_t ii = 0; ii < sp->num_items; ii++) { + if (ii != 0) + ostrm << ","; + ostrm << dump_hex(sp->items[ii].witness, + sp->items[ii].witness_len); + } + ostrm << "]"; + return ostrm.str(); +} + +string dump_wally_keypath_item(const struct wally_keypath_item *ip) +{ + ostringstream ostrm; + ostrm << "{ "; + ostrm << "\"pubkey\":" << dump_hex( + ip->pubkey, pubkey_is_compressed(ip->pubkey) ? + EC_PUBLIC_KEY_LEN : EC_PUBLIC_KEY_UNCOMPRESSED_LEN); + ostrm << ", \"origin\":{ "; + ostrm << " \"fingerprint\":" << dump_hex(ip->origin.fingerprint, + sizeof(ip->origin.fingerprint)); + ostrm << ", \"path\":[ "; + for (size_t ii = 0; ii < ip->origin.path_len; ++ii) { + if (ii != 0) + ostrm << ","; + ostrm << ip->origin.path[ii]; + } + ostrm << " ]"; + ostrm << " }"; + ostrm << " }"; + return ostrm.str(); +} + +string dump_wally_keypath_map(const struct wally_keypath_map *mp) { ostringstream ostrm; ostrm << "["; - if (*ias) { - for (size_t ii = 0; ii < tal_count(ias); ii++) { + if (mp) { + for (size_t ii = 0; ii < mp->num_items; ii++) { if (ii != 0) ostrm << ","; - ostrm << ias[ii]->satoshis; + ostrm << dump_wally_keypath_item(&mp->items[ii]); } } ostrm << "]"; return ostrm.str(); } -string dump_wally_tx_witness_stack(const struct wally_tx_witness_stack *sp) +string dump_wally_partial_sigs_item(const struct wally_partial_sigs_item *ip) +{ + ostringstream ostrm; + ostrm << "{ "; + ostrm << "\"pubkey\":" << dump_hex( + ip->pubkey, pubkey_is_compressed(ip->pubkey) ? + EC_PUBLIC_KEY_LEN : EC_PUBLIC_KEY_UNCOMPRESSED_LEN); + ostrm << ", \"sig\":" << dump_hex(ip->sig, ip->sig_len); + ostrm << " }"; + return ostrm.str(); +} + +string dump_wally_partial_sigs_map(const struct wally_partial_sigs_map *mp) { ostringstream ostrm; ostrm << "["; - for (size_t ii = 0; ii < sp->num_items; ii++) { - if (ii != 0) - ostrm << ","; - ostrm << dump_hex(sp->items[ii].witness, - sp->items[ii].witness_len); + if (mp) { + for (size_t ii = 0; ii < mp->num_items; ii++) { + if (ii != 0) + ostrm << ","; + ostrm << dump_wally_partial_sigs_item(&mp->items[ii]); + } + } + ostrm << "]"; + return ostrm.str(); +} + +string dump_wally_unknowns_item(const struct wally_unknowns_item *ip) +{ + ostringstream ostrm; + ostrm << "{ "; + ostrm << "\"key\":" << dump_hex(ip->key, ip->key_len); + ostrm << ", \"value\":" << dump_hex(ip->value, ip->value_len); + ostrm << " }"; + return ostrm.str(); +} + +string dump_wally_unknowns_map(const struct wally_unknowns_map *mp) +{ + ostringstream ostrm; + ostrm << "["; + if (mp) { + for (size_t ii = 0; ii < mp->num_items; ii++) { + if (ii != 0) + ostrm << ","; + ostrm << dump_wally_unknowns_item(&mp->items[ii]); + } } ostrm << "]"; return ostrm.str(); @@ -217,16 +301,16 @@ string dump_wally_tx_input(const struct wally_tx_input *in) { ostringstream ostrm; ostrm << "{ "; - ostrm << "txhash=" << dump_hex(in->txhash, sizeof(in->txhash)); - ostrm << ", index=" << in->index; - ostrm << ", sequence=" << in->sequence; - ostrm << ", script=" << + ostrm << "\"txhash\":" << dump_hex(in->txhash, sizeof(in->txhash)); + ostrm << ", \"index\":" << in->index; + ostrm << ", \"sequence\":" << in->sequence; + ostrm << ", \"script\":" << (in->script_len ? dump_hex(in->script, in->script_len) : - ""); - ostrm << ", witness=" << + "\"\""); + ostrm << ", \"witness\":" << (in->witness ? dump_wally_tx_witness_stack(in->witness) : - ""); - ostrm << ", features=" << int(in->features); + "\"\""); + ostrm << ", \"features\":" << int(in->features); ostrm << " }"; return ostrm.str(); } @@ -247,13 +331,15 @@ string dump_wally_tx_inputs(const struct wally_tx_input *inputs, string dump_wally_tx_output(const struct wally_tx_output *out) { + if (out == NULL) + return "{}"; ostringstream ostrm; ostrm << "{ "; - ostrm << "satoshi=" << out->satoshi; - ostrm << " script=" << + ostrm << "\"satoshi\":" << out->satoshi; + ostrm << ", \"script\":" << (out->script_len ? dump_hex(out->script, out->script_len) : - ""); - ostrm << ", features=" << int(out->features); + "\"\""); + ostrm << ", \"features\":" << int(out->features); ostrm << " }"; return ostrm.str(); } @@ -274,46 +360,110 @@ string dump_wally_tx_outputs(const struct wally_tx_output *outputs, string dump_wally_tx(const struct wally_tx *wtx) { + if (wtx == NULL) + return "{}"; ostringstream ostrm; ostrm << "{ "; - ostrm << "version=" << wtx->version; - ostrm << ", locktime=" << wtx->locktime; - ostrm << ", inputs=" << + ostrm << "\"version\":" << wtx->version; + ostrm << ", \"locktime\":" << wtx->locktime; + ostrm << ", \"inputs\":" << dump_wally_tx_inputs(wtx->inputs, wtx->num_inputs); - ostrm << ", inputs_allocation_len=" << wtx->inputs_allocation_len; - ostrm << ", outputs=" << + ostrm << ", \"inputs_allocation_len\":" << wtx->inputs_allocation_len; + ostrm << ", \"outputs\":" << dump_wally_tx_outputs(wtx->outputs, wtx->num_outputs); - ostrm << ", outputs_allocation_len=" << wtx->outputs_allocation_len; + ostrm << ", \"outputs_allocation_len\":" << wtx->outputs_allocation_len; + ostrm << " }"; + return ostrm.str(); +} + +string dump_wally_psbt_input(const struct wally_psbt_input *in) +{ + ostringstream ostrm; + ostrm << "{ "; + ostrm << "\"non_witness_utxo\":" << dump_wally_tx(in->non_witness_utxo); + ostrm << ", \"witness_utxo\":" << dump_wally_tx_output(in->witness_utxo); + ostrm << ", \"redeem_script\":" << dump_hex(in->redeem_script, + in->redeem_script_len); + ostrm << ", \"witness_script\":" << dump_hex(in->witness_script, + in->witness_script_len); + ostrm << ", \"final_script_sig\":" << dump_hex(in->final_script_sig, + in->final_script_sig_len); + ostrm << ", \"final_witness\":" + << dump_wally_tx_witness_stack(in->final_witness); + ostrm << ", \"keypaths\":" << dump_wally_keypath_map(in->keypaths); + ostrm << ", \"partial_sigs\":" + << dump_wally_partial_sigs_map(in->partial_sigs); + ostrm << ", \"unknowns\":" << dump_wally_unknowns_map(in->unknowns); + ostrm << ", \"sighash_type\":" << in->sighash_type; + ostrm << " }"; + return ostrm.str(); +} + +string dump_wally_psbt_inputs(const struct wally_psbt_input *inputs, + size_t num_inputs) +{ + ostringstream ostrm; + ostrm << "["; + for (size_t ii = 0; ii < num_inputs; ii++) { + if (ii != 0) + ostrm << ","; + ostrm << dump_wally_psbt_input(&inputs[ii]); + } + ostrm << "]"; + return ostrm.str(); +} + +string dump_wally_psbt_output(const struct wally_psbt_output *out) +{ + ostringstream ostrm; + ostrm << "{ "; + ostrm << "\"redeem_script\":" << dump_hex(out->redeem_script, + out->redeem_script_len); + ostrm << ", \"witness_script\":" << dump_hex(out->witness_script, + out->witness_script_len); + ostrm << ", \"keypaths\":" << dump_wally_keypath_map(out->keypaths); + ostrm << ", \"unknowns\":" << dump_wally_unknowns_map(out->unknowns); ostrm << " }"; return ostrm.str(); + } -string dump_output_witscripts(const struct witscript **wp) +string dump_wally_psbt_outputs(const struct wally_psbt_output *outputs, + size_t num_outputs) { ostringstream ostrm; ostrm << "["; - for (size_t ii = 0; ii < tal_count(wp); ii++) { + for (size_t ii = 0; ii < num_outputs; ii++) { if (ii != 0) ostrm << ","; - ostrm << (wp[ii] ? - dump_hex(wp[ii]->ptr, tal_count(wp[ii]->ptr)) : - ""); + ostrm << dump_wally_psbt_output(&outputs[ii]); } ostrm << "]"; return ostrm.str(); } +string dump_wally_psbt(const struct wally_psbt *psbt) +{ + ostringstream ostrm; + ostrm << "{ "; + ostrm << "\"magic\":" << dump_hex(psbt->magic, sizeof(psbt->magic)); + ostrm << ", \"tx\":" << dump_wally_tx(psbt->tx); + ostrm << ", \"inputs\":" + << dump_wally_psbt_inputs(psbt->inputs, psbt->num_inputs); + ostrm << ", \"outputs\":" + << dump_wally_psbt_outputs(psbt->outputs, psbt->num_outputs); + ostrm << ", \"unknowns\":" << dump_wally_unknowns_map(psbt->unknowns); + ostrm << ", \"version\":" << psbt->version; + ostrm << " }"; + return ostrm.str(); +} + string dump_tx(const struct bitcoin_tx *tx) { ostringstream ostrm; ostrm << "{ "; - ostrm << "input_amounts=" << - dump_input_amounts( - (const struct amount_sat **)tx->input_amounts); - ostrm << ", wally_tx=" << dump_wally_tx(tx->wtx); - ostrm << ", output_witscripts=" << - dump_output_witscripts( - (const struct witscript **)tx->output_witscripts); + ostrm << "\"wtx\":" << dump_wally_tx(tx->wtx); + ostrm << ", \"psbt\":" << dump_wally_psbt(tx->psbt); ostrm << " }"; return ostrm.str(); } diff --git a/contrib/remote_hsmd/dump.h b/contrib/remote_hsmd/dump.hpp similarity index 74% rename from contrib/remote_hsmd/dump.h rename to contrib/remote_hsmd/dump.hpp index 030f341d1f94..3116b4353d4e 100644 --- a/contrib/remote_hsmd/dump.h +++ b/contrib/remote_hsmd/dump.hpp @@ -1,3 +1,10 @@ +#ifndef LIGHTNING_CONTRIB_REMOTE_HSMD_DUMP_H +#define LIGHTNING_CONTRIB_REMOTE_HSMD_DUMP_H + +extern "C" { +#include +#include +} #include std::string dump_hex(const void *vptr, size_t sz); @@ -16,8 +23,10 @@ std::string dump_utxo(const struct utxo *in); std::string dump_utxos(const struct utxo **utxos); std::string dump_bitcoin_tx_output(const struct bitcoin_tx_output *op); std::string dump_bitcoin_tx_outputs(const struct bitcoin_tx_output **outputs); -std::string dump_input_amounts(const struct amount_sat **ias); std::string dump_wally_tx_witness_stack(const struct wally_tx_witness_stack *sp); +std::string dump_wally_keypath_map(const struct wally_keypath_map *mp); +std::string dump_wally_partial_sigs_map(const struct wally_partial_sigs_map *mp); +std::string dump_wally_unknowns_map(const struct wally_unknowns_map *mp); std::string dump_wally_tx_input(const struct wally_tx_input *in); std::string dump_wally_tx_inputs(const struct wally_tx_input *inputs, size_t num_inputs); @@ -25,5 +34,7 @@ std::string dump_wally_tx_output(const struct wally_tx_output *out); std::string dump_wally_tx_outputs(const struct wally_tx_output *outputs, size_t num_outputs); std::string dump_wally_tx(const struct wally_tx *wtx); -std::string dump_output_witscripts(const struct witscript **wp); +std::string dump_wally_psbt(const struct wally_psbt *psbt); std::string dump_tx(const struct bitcoin_tx *tx); + +#endif /* LIGHTNING_CONTRIB_REMOTE_HSMD_DUMP_H */ diff --git a/contrib/remote_hsmd/hsmd.c b/contrib/remote_hsmd/hsmd.c index 515fa18446b5..045327c36e62 100644 --- a/contrib/remote_hsmd/hsmd.c +++ b/contrib/remote_hsmd/hsmd.c @@ -38,12 +38,12 @@ #include #include #include +/*~ All gen_ files are autogenerated; in this case by tools/generate-wire.py */ +#include +#include #include #include #include -/*~ All gen_ files are autogenerated; in this case by tools/generate-wire.py */ -#include -#include #include #include #include @@ -360,6 +360,7 @@ static struct io_plan *init_hsm(struct io_conn *conn, struct sha256 *force_channel_secrets_shaseed; struct secret *hsm_encryption_key; struct secret hsm_secret; + bool coldstart; /* This must be lightningd. */ assert(is_lightningd(c)); @@ -406,9 +407,12 @@ static struct io_plan *init_hsm(struct io_conn *conn, randombytes_buf(&hsm_secret, sizeof(hsm_secret)); } + /* Is this a warm start (restart) or a cold start (first time)? */ + coldstart = access("WARM", F_OK) == -1; + proxy_stat rv = proxy_init_hsm(&bip32_key_version, chainparams, - &hsm_secret, &node_id, - &pubstuff.bip32); + coldstart, &hsm_secret, + &node_id, &pubstuff.bip32); if (PROXY_PERMANENT(rv)) { status_failed(STATUS_FAIL_INTERNAL_ERROR, "proxy_%s failed: %s", __FUNCTION__, @@ -422,6 +426,11 @@ static struct io_plan *init_hsm(struct io_conn *conn, proxy_last_message()); } + /* Mark this node as already inited. */ + int fd = open("WARM", O_WRONLY|O_TRUNC|O_CREAT, 0666); + assert(fd != -1); + close(fd); + return req_reply(conn, c, take(towire_hsm_init_reply(NULL, &node_id, &pubstuff.bip32))); } @@ -628,15 +637,13 @@ static struct io_plan *handle_sign_commitment_tx(struct io_conn *conn, struct pubkey remote_funding_pubkey; struct node_id peer_id; u64 dbid; - struct amount_sat funding; struct bitcoin_tx *tx; struct bitcoin_signature sig; if (!fromwire_hsm_sign_commitment_tx(tmpctx, msg_in, &peer_id, &dbid, &tx, - &remote_funding_pubkey, - &funding)) + &remote_funding_pubkey)) return bad_req(conn, c, msg_in); tx->chainparams = c->chainparams; @@ -647,14 +654,6 @@ static struct io_plan *handle_sign_commitment_tx(struct io_conn *conn, if (tx->wtx->num_outputs == 0) return bad_req_fmt(conn, c, msg_in, "tx must have > 0 outputs"); - /*~ Segregated Witness also added the input amount to the signing - * algorithm; it's only part of the input implicitly (it's part of the - * output it's spending), so in our 'bitcoin_tx' structure it's a - * pointer, as we don't always know it (and zero is a valid amount, so - * NULL is better to mean 'unknown' and has the nice property that - * you'll crash if you assume it's there and you're wrong.) */ - tx->input_amounts[0] = tal_dup(tx, struct amount_sat, &funding); - proxy_stat rv = proxy_handle_sign_commitment_tx( tx, &remote_funding_pubkey, &peer_id, dbid, &sig); if (PROXY_PERMANENT(rv)) @@ -683,18 +682,14 @@ static struct io_plan *handle_sign_remote_commitment_tx(struct io_conn *conn, const u8 *msg_in) { struct pubkey remote_funding_pubkey; - struct amount_sat funding; struct bitcoin_tx *tx; struct bitcoin_signature sig; - struct witscript **output_witscripts; struct pubkey remote_per_commit; bool option_static_remotekey; if (!fromwire_hsm_sign_remote_commitment_tx(tmpctx, msg_in, &tx, &remote_funding_pubkey, - &funding, - &output_witscripts, &remote_per_commit, &option_static_remotekey)) bad_req(conn, c, msg_in); @@ -705,16 +700,10 @@ static struct io_plan *handle_sign_remote_commitment_tx(struct io_conn *conn, return bad_req_fmt(conn, c, msg_in, "tx must have 1 input"); if (tx->wtx->num_outputs == 0) return bad_req_fmt(conn, c, msg_in, "tx must have > 0 outputs"); - if (tal_count(output_witscripts) != tx->wtx->num_outputs) - return bad_req_fmt(conn, c, msg_in, "tx must have matching witscripts"); - - /* Need input amount for signing */ - tx->input_amounts[0] = tal_dup(tx, struct amount_sat, &funding); proxy_stat rv = proxy_handle_sign_remote_commitment_tx( - tx, &remote_funding_pubkey, &funding, + tx, &remote_funding_pubkey, &c->id, c->dbid, - (const struct witscript **) output_witscripts, &remote_per_commit, option_static_remotekey, &sig); @@ -727,7 +716,7 @@ static struct io_plan *handle_sign_remote_commitment_tx(struct io_conn *conn, "proxy_%s error: %s", __FUNCTION__, proxy_last_message()); - status_debug("%s:%d %s: signature: %s", + STATUS_DEBUG("%s:%d %s: signature: %s", __FILE__, __LINE__, __FUNCTION__, type_to_string(tmpctx, struct bitcoin_signature, &sig)); @@ -743,20 +732,14 @@ static struct io_plan *handle_sign_remote_htlc_tx(struct io_conn *conn, struct bitcoin_tx *tx; struct bitcoin_signature sig; struct pubkey remote_per_commit_point; - struct amount_sat amount; u8 *wscript; if (!fromwire_hsm_sign_remote_htlc_tx(tmpctx, msg_in, - &tx, &wscript, &amount, + &tx, &wscript, &remote_per_commit_point)) return bad_req(conn, c, msg_in); tx->chainparams = c->chainparams; - /* Need input amount for signing */ - if (tx->wtx->num_inputs != 1) - return bad_req_fmt(conn, c, msg_in, "bad txinput count"); - tx->input_amounts[0] = tal_dup(tx, struct amount_sat, &amount); - proxy_stat rv = proxy_handle_sign_remote_htlc_tx( tx, wscript, @@ -785,22 +768,16 @@ static struct io_plan *handle_sign_delayed_payment_to_us(struct io_conn *conn, const u8 *msg_in) { u64 commit_num; - struct amount_sat input_sat; struct bitcoin_tx *tx; u8 *wscript; /*~ We don't derive the wscript ourselves, but perhaps we should? */ if (!fromwire_hsm_sign_delayed_payment_to_us(tmpctx, msg_in, &commit_num, - &tx, &wscript, - &input_sat)) + &tx, &wscript)) return bad_req(conn, c, msg_in); tx->chainparams = c->chainparams; - if (tx->wtx->num_inputs != 1) - return bad_req_fmt(conn, c, msg_in, "bad txinput count"); - tx->input_amounts[0] = tal_dup(tx, struct amount_sat, &input_sat); - struct bitcoin_signature sig; proxy_stat rv = proxy_handle_sign_delayed_payment_to_us( tx, commit_num, wscript, &c->id, c->dbid, &sig); @@ -823,24 +800,17 @@ static struct io_plan *handle_sign_remote_htlc_to_us(struct io_conn *conn, struct client *c, const u8 *msg_in) { - struct amount_sat input_sat; struct bitcoin_tx *tx; struct pubkey remote_per_commitment_point; u8 *wscript; if (!fromwire_hsm_sign_remote_htlc_to_us(tmpctx, msg_in, &remote_per_commitment_point, - &tx, &wscript, - &input_sat)) + &tx, &wscript)) return bad_req(conn, c, msg_in); tx->chainparams = c->chainparams; - /* Need input amount for signing */ - if (tx->wtx->num_inputs != 1) - return bad_req_fmt(conn, c, msg_in, "bad txinput count"); - tx->input_amounts[0] = tal_dup(tx, struct amount_sat, &input_sat); - struct bitcoin_signature sig; proxy_stat rv = proxy_handle_sign_remote_htlc_to_us( tx, @@ -868,23 +838,16 @@ static struct io_plan *handle_sign_penalty_to_us(struct io_conn *conn, struct client *c, const u8 *msg_in) { - struct amount_sat input_sat; struct secret revocation_secret; struct bitcoin_tx *tx; u8 *wscript; if (!fromwire_hsm_sign_penalty_to_us(tmpctx, msg_in, &revocation_secret, - &tx, &wscript, - &input_sat)) + &tx, &wscript)) return bad_req(conn, c, msg_in); tx->chainparams = c->chainparams; - /* Need input amount for signing */ - if (tx->wtx->num_inputs != 1) - return bad_req_fmt(conn, c, msg_in, "bad txinput count"); - tx->input_amounts[0] = tal_dup(tx, struct amount_sat, &input_sat); - struct bitcoin_signature sig; proxy_stat rv = proxy_handle_sign_penalty_to_us( tx, &revocation_secret, wscript, &c->id, c->dbid, &sig); @@ -908,22 +871,16 @@ static struct io_plan *handle_sign_local_htlc_tx(struct io_conn *conn, const u8 *msg_in) { u64 commit_num; - struct amount_sat input_sat; struct bitcoin_tx *tx; u8 *wscript; struct bitcoin_signature sig; if (!fromwire_hsm_sign_local_htlc_tx(tmpctx, msg_in, - &commit_num, &tx, &wscript, - &input_sat)) + &commit_num, &tx, &wscript)) return bad_req(conn, c, msg_in); tx->chainparams = c->chainparams; - if (tx->wtx->num_inputs != 1) - return bad_req_fmt(conn, c, msg_in, "bad txinput count"); - tx->input_amounts[0] = tal_dup(tx, struct amount_sat, &input_sat); - proxy_stat rv = proxy_handle_sign_local_htlc_tx( tx, commit_num, wscript, &c->id, c->dbid, &sig); if (PROXY_PERMANENT(rv)) @@ -1014,19 +971,14 @@ static struct io_plan *handle_sign_mutual_close_tx(struct io_conn *conn, struct bitcoin_tx *tx; struct pubkey remote_funding_pubkey; struct bitcoin_signature sig; - struct amount_sat funding; if (!fromwire_hsm_sign_mutual_close_tx(tmpctx, msg_in, &tx, - &remote_funding_pubkey, - &funding)) + &remote_funding_pubkey)) return bad_req(conn, c, msg_in); tx->chainparams = c->chainparams; - /* Need input amount for signing */ - tx->input_amounts[0] = tal_dup(tx, struct amount_sat, &funding); - proxy_stat rv = proxy_handle_sign_mutual_close_tx( tx, &remote_funding_pubkey, &c->id, c->dbid, &sig); if (PROXY_PERMANENT(rv)) @@ -1092,7 +1044,7 @@ static struct io_plan *pass_client_hsmfd(struct io_conn *conn, status_failed(STATUS_FAIL_INTERNAL_ERROR, "creating fds: %s", strerror(errno)); - status_debug("new_client: %"PRIu64, dbid); + STATUS_DEBUG("new_client: %"PRIu64, dbid); new_client(c, c->chainparams, &id, dbid, capabilities, fds[0]); // Skip zero dbid (master, gossipd, connectd). @@ -1116,38 +1068,113 @@ static struct io_plan *pass_client_hsmfd(struct io_conn *conn, send_pending_client_fd, c); } +/*~ This is used to declare a new channel. */ +static struct io_plan *handle_new_channel(struct io_conn *conn, + struct client *c, + const u8 *msg_in) +{ + struct node_id peer_id; + u64 dbid; + + if (!fromwire_hsm_new_channel(msg_in, &peer_id, &dbid)) + return bad_req(conn, c, msg_in); + + proxy_stat rv = proxy_handle_new_channel(&peer_id, dbid); + if (PROXY_PERMANENT(rv)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "proxy_%s failed: %s", __FUNCTION__, + proxy_last_message()); + else if (!PROXY_SUCCESS(rv)) + return bad_req_fmt(conn, c, msg_in, + "proxy_%s error: %s", __FUNCTION__, + proxy_last_message()); + + return req_reply(conn, c, + take(towire_hsm_new_channel_reply(NULL))); +} + +/*~ This is used to provide all unchanging public channel parameters. */ +static struct io_plan *handle_ready_channel(struct io_conn *conn, + struct client *c, + const u8 *msg_in) +{ + bool is_outbound; + struct amount_sat channel_value; + struct amount_msat push_value; + struct bitcoin_txid funding_txid; + u16 funding_txout; + u16 local_to_self_delay; + u8 *local_shutdown_script; + struct basepoints remote_basepoints; + struct pubkey remote_funding_pubkey; + u16 remote_to_self_delay; + u8 *remote_shutdown_script; + bool option_static_remotekey; + + if (!fromwire_hsm_ready_channel(tmpctx, msg_in, &is_outbound, + &channel_value, &push_value, &funding_txid, + &funding_txout, &local_to_self_delay, + &local_shutdown_script, + &remote_basepoints, + &remote_funding_pubkey, + &remote_to_self_delay, + &remote_shutdown_script, + &option_static_remotekey)) + return bad_req(conn, c, msg_in); + + proxy_stat rv = proxy_handle_ready_channel( + &c->id, c->dbid, + is_outbound, + &channel_value, + &push_value, + &funding_txid, + funding_txout, + local_to_self_delay, + local_shutdown_script, + &remote_basepoints, + &remote_funding_pubkey, + remote_to_self_delay, + remote_shutdown_script, + option_static_remotekey); + if (PROXY_PERMANENT(rv)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "proxy_%s failed: %s", __FUNCTION__, + proxy_last_message()); + else if (!PROXY_SUCCESS(rv)) + return bad_req_fmt(conn, c, msg_in, + "proxy_%s error: %s", __FUNCTION__, + proxy_last_message()); + return req_reply(conn, c, + take(towire_hsm_ready_channel_reply(NULL))); +} + /*~ lightningd asks us to sign a withdrawal; same as above but in theory * we can do more to check the previous case is valid. */ static struct io_plan *handle_sign_withdrawal_tx(struct io_conn *conn, struct client *c, const u8 *msg_in) { - struct amount_sat satoshi_out, change_out; - u32 change_keyindex; struct utxo **utxos; - struct bitcoin_tx *tx; - struct pubkey changekey; - struct bitcoin_tx_output **outputs; - u32 nlocktime; + struct wally_psbt *psbt; - if (!fromwire_hsm_sign_withdrawal(tmpctx, msg_in, &satoshi_out, - &change_out, &change_keyindex, - &outputs, &utxos, &nlocktime)) + if (!fromwire_hsm_sign_withdrawal(tmpctx, msg_in, + &utxos, &psbt)) return bad_req(conn, c, msg_in); - if (!bip32_pubkey(&pubstuff.bip32, &changekey, change_keyindex)) - return bad_req_fmt(conn, c, msg_in, - "Failed to get key %u", change_keyindex); - - tx = withdraw_tx(tmpctx, c->chainparams, - cast_const2(const struct utxo **, utxos), outputs, - &changekey, change_out, NULL, NULL, nlocktime); + struct bitcoin_tx_output **outputs; + outputs = tal_arr(tmpctx, struct bitcoin_tx_output *, psbt->num_outputs); + for (size_t ii = 0; ii < psbt->num_outputs; ++ii) { + outputs[ii] = tal(outputs, struct bitcoin_tx_output); + outputs[ii]->amount.satoshis = psbt->tx->outputs[ii].satoshi; /* Raw: from wally_tx_output */ + outputs[ii]->script = + tal_dup_arr(outputs[ii], u8, + psbt->tx->outputs[ii].script, + psbt->tx->outputs[ii].script_len, 0); + } u8 *** wits; proxy_stat rv = proxy_handle_sign_withdrawal_tx( - &c->id, c->dbid, &satoshi_out, - &change_out, change_keyindex, - outputs, utxos, tx, &wits); + &c->id, c->dbid, outputs, utxos, psbt, &wits); if (PROXY_PERMANENT(rv)) status_failed(STATUS_FAIL_INTERNAL_ERROR, "proxy_%s failed: %s", __FUNCTION__, @@ -1157,35 +1184,40 @@ static struct io_plan *handle_sign_withdrawal_tx(struct io_conn *conn, "proxy_%s error: %s", __FUNCTION__, proxy_last_message()); - /* Sign w/ the remote lightning-signer. */ - assert(tal_count(wits) == tal_count(utxos)); - for (size_t ii = 0; ii < tal_count(wits); ++ii) { - struct pubkey inkey; - bool ok = pubkey_from_der( - wits[ii][1], tal_count(wits[ii][1]), &inkey); - assert(ok); - - if (utxos[ii]->is_p2sh) { - u8 *script = bitcoin_scriptsig_p2sh_p2wpkh( - tx, &inkey); - bitcoin_tx_input_set_script(tx, ii, script); - - } else { - bitcoin_tx_input_set_script(tx, ii, NULL); + /* We must have one witness element for each input. */ + assert(tal_count(wits) == psbt->num_inputs); + + /* Witnesses and inputs are in the same order. */ + for (size_t kk = 0; kk < tal_count(wits); ++kk) { + struct wally_psbt_input *input = &psbt->inputs[kk]; + u8 *sig = wits[kk][0]; + u8 *pubkey = wits[kk][1]; + int ret; + + /* If this is a PSBT, we should skip any inputs that + * have an empty signature. */ + if (tal_count(sig) == 0) + continue; + + struct pubkey spubkey; + pubkey_from_der(pubkey, EC_PUBLIC_KEY_LEN, &spubkey); + psbt_input_add_pubkey(psbt, kk, &spubkey); + + if (!input->partial_sigs) { + ret = wally_partial_sigs_map_init_alloc( + 1, &input->partial_sigs); + assert(ret == WALLY_OK); } - u8 **witness = tal_arr(tx, u8 *, 2); - witness[0] = tal_dup_arr(witness, u8, - wits[ii][0], - tal_count(wits[ii][0]), 0); - witness[1] = tal_dup_arr(witness, u8, - wits[ii][1], - tal_count(wits[ii][1]), 0); - bitcoin_tx_input_set_witness(tx, ii, take(witness)); + ret = wally_add_new_partial_sig( + input->partial_sigs, + pubkey, EC_PUBLIC_KEY_LEN, + sig, tal_count(sig)); + assert(ret == WALLY_OK); } return req_reply(conn, c, - take(towire_hsm_sign_withdrawal_reply(NULL, tx))); + take(towire_hsm_sign_withdrawal_reply(NULL, psbt))); } /*~ Lightning invoices, defined by BOLT 11, are signed. This has been @@ -1361,6 +1393,7 @@ static bool check_client_capabilities(struct client *client, case WIRE_HSM_GET_PER_COMMITMENT_POINT: case WIRE_HSM_CHECK_FUTURE_SECRET: + case WIRE_HSM_READY_CHANNEL: return (client->capabilities & HSM_CAP_COMMITMENT_POINT) != 0; case WIRE_HSM_SIGN_REMOTE_COMMITMENT_TX: @@ -1371,8 +1404,8 @@ static bool check_client_capabilities(struct client *client, return (client->capabilities & HSM_CAP_SIGN_CLOSING_TX) != 0; case WIRE_HSM_INIT: + case WIRE_HSM_NEW_CHANNEL: case WIRE_HSM_CLIENT_HSMFD: - case WIRE_HSM_SIGN_FUNDING: case WIRE_HSM_SIGN_WITHDRAWAL: case WIRE_HSM_SIGN_INVOICE: case WIRE_HSM_SIGN_COMMITMENT_TX: @@ -1388,7 +1421,8 @@ static bool check_client_capabilities(struct client *client, case WIRE_HSM_CANNOUNCEMENT_SIG_REPLY: case WIRE_HSM_CUPDATE_SIG_REPLY: case WIRE_HSM_CLIENT_HSMFD_REPLY: - case WIRE_HSM_SIGN_FUNDING_REPLY: + case WIRE_HSM_NEW_CHANNEL_REPLY: + case WIRE_HSM_READY_CHANNEL_REPLY: case WIRE_HSM_NODE_ANNOUNCEMENT_SIG_REPLY: case WIRE_HSM_SIGN_WITHDRAWAL_REPLY: case WIRE_HSM_SIGN_INVOICE_REPLY: @@ -1411,7 +1445,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) { enum hsm_wire_type t = fromwire_peektype(c->msg_in); - status_debug("Client: Received message %d from client", t); + STATUS_DEBUG("Client: Received message %d from client", t); /* Before we do anything else, is this client allowed to do * what he asks for? */ @@ -1428,6 +1462,12 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSM_CLIENT_HSMFD: return pass_client_hsmfd(conn, c, c->msg_in); + case WIRE_HSM_NEW_CHANNEL: + return handle_new_channel(conn, c, c->msg_in); + + case WIRE_HSM_READY_CHANNEL: + return handle_ready_channel(conn, c, c->msg_in); + case WIRE_HSM_GET_CHANNEL_BASEPOINTS: return handle_get_channel_basepoints(conn, c, c->msg_in); @@ -1440,11 +1480,6 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSM_CUPDATE_SIG_REQ: return handle_channel_update_sig(conn, c, c->msg_in); - case WIRE_HSM_SIGN_FUNDING: - /* FIXME: Never called by integration tests. */ - /* return handle_sign_funding_tx(conn, c, c->msg_in); */ - assert(false); - case WIRE_HSM_NODE_ANNOUNCEMENT_SIG_REQ: return handle_sign_node_announcement(conn, c, c->msg_in); @@ -1496,7 +1531,8 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSM_CANNOUNCEMENT_SIG_REPLY: case WIRE_HSM_CUPDATE_SIG_REPLY: case WIRE_HSM_CLIENT_HSMFD_REPLY: - case WIRE_HSM_SIGN_FUNDING_REPLY: + case WIRE_HSM_NEW_CHANNEL_REPLY: + case WIRE_HSM_READY_CHANNEL_REPLY: case WIRE_HSM_NODE_ANNOUNCEMENT_SIG_REPLY: case WIRE_HSM_SIGN_WITHDRAWAL_REPLY: case WIRE_HSM_SIGN_INVOICE_REPLY: diff --git a/contrib/remote_hsmd/proxy.cc b/contrib/remote_hsmd/proxy.cc index e9515f1163c5..509b0a61ce09 100644 --- a/contrib/remote_hsmd/proxy.cc +++ b/contrib/remote_hsmd/proxy.cc @@ -1,18 +1,14 @@ /* This needs to be first */ #define __STDC_FORMAT_MACROS -#include - -#include /* These two only needed for sleep() and getpid() */ -#include - -#include -#include - -#include +#include "contrib/remote_hsmd/dump.hpp" +#include "contrib/remote_hsmd/proxy.hpp" +#include "contrib/remote_hsmd/remotesigner.grpc.pb.h" +#include "contrib/remote_hsmd/remotesigner.pb.h" extern "C" { #include #include +#include #include #include #include @@ -21,15 +17,20 @@ extern "C" { #include #include #include +} +#include +#include +#include +extern "C" { #include +} +#include +#include /* These two only needed for sleep() and getpid() */ +#include +extern "C" { #include } -#include "contrib/remote_hsmd/remotesigner.pb.h" -#include "contrib/remote_hsmd/remotesigner.grpc.pb.h" - -#include "contrib/remote_hsmd/dump.h" -#include "contrib/remote_hsmd/proxy.h" using std::cerr; using std::endl; @@ -79,32 +80,32 @@ proxy_stat map_status(Status const & status) /* BIP144: * If the witness is empty, the old serialization format should be used. */ -bool uses_witness(const struct bitcoin_tx *tx) +bool uses_witness(const struct wally_tx *wtx) { size_t i; - for (i = 0; i < tx->wtx->num_inputs; i++) { - if (tx->wtx->inputs[i].witness) + for (i = 0; i < wtx->num_inputs; i++) { + if (wtx->inputs[i].witness) return true; } return false; } -string serialized_tx(struct bitcoin_tx const *tx, bool bip144) +string serialized_wtx(struct wally_tx const *wtx, bool bip144) { int res; size_t len, written; u8 *serialized;; u8 flag = 0; - if (bip144 && uses_witness(tx)) + if (bip144 && uses_witness(wtx)) flag |= WALLY_TX_FLAG_USE_WITNESS; - res = wally_tx_get_length(tx->wtx, flag, &len); + res = wally_tx_get_length(wtx, flag, &len); assert(res == WALLY_OK); string retval(len, '\0'); - res = wally_tx_to_bytes(tx->wtx, flag, (unsigned char *)&retval[0], + res = wally_tx_to_bytes(wtx, flag, (unsigned char *)&retval[0], retval.size(), &written); assert(res == WALLY_OK); assert(len == written); @@ -123,6 +124,11 @@ void marshal_secret(struct secret const *ss, Secret *o_sp) o_sp->set_data(ss->data, sizeof(ss->data)); } +void marshal_bip32seed(struct secret const *ss, BIP32Seed *o_sp) +{ + o_sp->set_data(ss->data, sizeof(ss->data)); +} + void marshal_node_id(struct node_id const *np, NodeId *o_np) { o_np->set_data(np->k, sizeof(np->k)); @@ -130,19 +136,22 @@ void marshal_node_id(struct node_id const *np, NodeId *o_np) void marshal_pubkey(struct pubkey const *pp, PubKey *o_pp) { - o_pp->set_data(pp->pubkey.data, sizeof(pp->pubkey.data)); + u8 pubkey_der[PUBKEY_CMPR_LEN]; + pubkey_to_der(pubkey_der, pp); + + o_pp->set_data(pubkey_der, sizeof(pubkey_der)); } void marshal_utxo(struct utxo const *up, InputDescriptor *idesc) { - idesc->mutable_key_loc()->set_key_index(up->keyindex); - idesc->mutable_prev_output()->set_value(up->amount.satoshis); - /* FIXME - where does pk_script come from? */ + idesc->mutable_key_loc()->add_key_path(up->keyindex); + idesc->set_value_sat(up->amount.satoshis); idesc->set_spend_type(up->is_p2sh ? SpendType::P2SH_P2WPKH : SpendType::P2WPKH); if (up->close_info) { - UnilateralCloseInfo *cinfo = idesc->mutable_close_info(); + UnilateralCloseInfo *cinfo = + idesc->mutable_key_loc()->mutable_close_info(); marshal_channel_nonce(&up->close_info->peer_id, up->close_info->channel_id, cinfo->mutable_channel_nonce()); @@ -152,46 +161,52 @@ void marshal_utxo(struct utxo const *up, InputDescriptor *idesc) } } +void marshal_outpoint(struct bitcoin_txid const *txid, u16 txout, Outpoint *o_op) +{ + o_op->set_txid(txid->shad.sha.u.u8, sizeof(txid->shad.sha.u.u8)); + o_op->set_index(txout); +} + +void marshal_script(u8 const *script, string *o_script) +{ + if (script) + o_script->assign((char const *)script, tal_count(script)); +} + +void marshal_basepoints(struct basepoints const *bps, + struct pubkey *funding_pubkey, + Basepoints * o_bps) +{ + marshal_pubkey(&bps->revocation, o_bps->mutable_revocation()); + marshal_pubkey(&bps->payment, o_bps->mutable_payment()); + marshal_pubkey(&bps->htlc, o_bps->mutable_htlc()); + marshal_pubkey(&bps->delayed_payment, o_bps->mutable_delayed_payment()); + marshal_pubkey(funding_pubkey, o_bps->mutable_funding_pubkey()); +} + void marshal_single_input_tx(struct bitcoin_tx const *tx, - u8 const *output_witscript, - struct witscript const **output_witscripts, + u8 const *redeem_script, Transaction *o_tp) { - if (output_witscript) { - /* Called with a single witscript. */ - assert(tx->wtx->num_outputs == 1); - } else if (output_witscripts) { - /* Called with an array of witscripts. */ - assert(tal_count(output_witscripts) == tx->wtx->num_outputs); - } + assert(tx->psbt->num_outputs == tx->wtx->num_outputs); - o_tp->set_raw_tx_bytes(serialized_tx(tx, true)); + o_tp->set_raw_tx_bytes(serialized_wtx(tx->wtx, true)); assert(tx->wtx->num_inputs == 1); + assert(tx->psbt->num_inputs == 1); InputDescriptor *idesc = o_tp->add_input_descs(); - idesc->mutable_prev_output()->set_value(tx->input_amounts[0]->satoshis); - /* FIXME - What else needs to be set? */ + idesc->set_value_sat(psbt_input_get_amount(tx->psbt, 0).satoshis); + if (redeem_script) + idesc->set_redeem_script((const char *) redeem_script, + tal_count(redeem_script)); for (size_t ii = 0; ii < tx->wtx->num_outputs; ii++) { OutputDescriptor *odesc = o_tp->add_output_descs(); - if (output_witscript) { - /* We have a single witscript. */ - odesc->set_witscript((const char *) output_witscript, - tal_count(output_witscript)); - } else if (output_witscripts) { - /* We have an array of witscripts. */ - if (output_witscripts[ii]) - odesc->set_witscript( - (const char *) - output_witscripts[ii]->ptr, - tal_count(output_witscripts[ii]->ptr)); - else - odesc->set_witscript(""); - } else { - /* Called w/ no witscripts. */ - odesc->set_witscript(""); - } - + if (tx->psbt->outputs[ii].witness_script_len) + odesc->set_witscript( + (const char *) + tx->psbt->outputs[ii].witness_script, + tx->psbt->outputs[ii].witness_script_len); } } @@ -263,7 +278,7 @@ void unmarshal_witnesses(RepeatedPtrField const &wits, u8 ****o_wits) owits = tal_arrz(tmpctx, u8**, nwits); for (size_t ii = 0; ii < nwits; ++ii) { owits[ii] = tal_arrz(owits, u8*, 2); - Witness const &wit = wits[ii]; + Witness const &wit = wits.Get(ii); const string &sig = wit.signature().data(); const string &pubkey = wit.pubkey().data(); owits[ii][0] = tal_arr(owits[ii], u8, sig.size()); @@ -291,7 +306,7 @@ const char *proxy_last_message(void) void proxy_setup() { - status_debug("%s:%d %s", __FILE__, __LINE__, __FUNCTION__); + STATUS_DEBUG("%s:%d %s", __FILE__, __LINE__, __FUNCTION__); auto channel = grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()); stub = Signer::NewStub(channel); @@ -300,14 +315,16 @@ void proxy_setup() proxy_stat proxy_init_hsm(struct bip32_key_version *bip32_key_version, struct chainparams const *chainparams, + bool coldstart, struct secret *hsm_secret, struct node_id *o_node_id, struct ext_key *o_ext_pubkey) { - status_debug( - "%s:%d %s hsm_secret=%s", + STATUS_DEBUG( + "%s:%d %s { \"hsm_secret\":%s, \"coldstart\":%s }", __FILE__, __LINE__, __FUNCTION__, - dump_secret(hsm_secret).c_str() + dump_secret(hsm_secret).c_str(), + coldstart ? "true" : "false" ); /* First we make the Init call to create the Node. */ @@ -315,12 +332,17 @@ proxy_stat proxy_init_hsm(struct bip32_key_version *bip32_key_version, last_message = ""; InitRequest req; + auto nc = req.mutable_node_config(); + nc->set_key_derivation_style(NodeConfig::NATIVE); + auto cp = req.mutable_chainparams(); cp->set_network_name(chainparams->network_name); + req.set_coldstart(coldstart); + /* FIXME - Sending the secret instead of generating on * the remote. */ - marshal_secret(hsm_secret, req.mutable_hsm_secret()); + marshal_bip32seed(hsm_secret, req.mutable_hsm_secret()); ClientContext context; InitReply rsp; @@ -328,7 +350,7 @@ proxy_stat proxy_init_hsm(struct bip32_key_version *bip32_key_version, if (status.ok()) { unmarshal_node_id(rsp.node_id(), o_node_id); unmarshal_node_id(rsp.node_id(), &self_id); - status_debug("%s:%d %s node_id=%s", + STATUS_DEBUG("%s:%d %s { \"node_id\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(o_node_id).c_str()); last_message = "success"; @@ -354,7 +376,8 @@ proxy_stat proxy_init_hsm(struct bip32_key_version *bip32_key_version, Status status = stub->GetExtPubKey(&context, req, &rsp); if (status.ok()) { unmarshal_ext_pubkey(rsp.xpub(), o_ext_pubkey); - status_debug("%s:%d %s node_id=%s ext_pubkey=%s", + STATUS_DEBUG("%s:%d %s " + "{ \"node_id\":%s, \"ext_pubkey\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_ext_pubkey(o_ext_pubkey).c_str()); @@ -373,8 +396,8 @@ proxy_stat proxy_init_hsm(struct bip32_key_version *bip32_key_version, proxy_stat proxy_handle_ecdh(const struct pubkey *point, struct secret *o_ss) { - status_debug( - "%s:%d %s self_id=%s point=%s", + STATUS_DEBUG( + "%s:%d %s { \"self_id\":%s, \"point\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_pubkey(point).c_str() @@ -390,7 +413,7 @@ proxy_stat proxy_handle_ecdh(const struct pubkey *point, Status status = stub->ECDH(&context, req, &rsp); if (status.ok()) { unmarshal_secret(rsp.shared_secret(), o_ss); - status_debug("%s:%d %s self_id=%s ss=%s", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s, \"ss\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_secret(o_ss).c_str()); @@ -411,9 +434,10 @@ proxy_stat proxy_handle_pass_client_hsmfd( u64 dbid, u64 capabilities) { - status_debug( - "%s:%d %s self_id=%s peer_id=%s dbid=%" PRIu64 " " - "capabilities=%" PRIu64 "", + STATUS_DEBUG( + "%s:%d %s " + "{ \"self_id\":%s, \"peer_id\":%s, \"dbid\":%" PRIu64 ", " + "\"capabilities\":%" PRIu64 " }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_node_id(peer_id).c_str(), @@ -421,6 +445,9 @@ proxy_stat proxy_handle_pass_client_hsmfd( capabilities ); +/* We used to synthesize NewChannel here, but now have an explicit + * interface. This whole method can go away. */ +#if 0 last_message = ""; NewChannelRequest req; marshal_node_id(&self_id, req.mutable_node_id()); @@ -430,7 +457,7 @@ proxy_stat proxy_handle_pass_client_hsmfd( NewChannelReply rsp; Status status = stub->NewChannel(&context, req, &rsp); if (status.ok()) { - status_debug("%s:%d %s self_id=%s", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str()); last_message = "success"; @@ -443,51 +470,157 @@ proxy_stat proxy_handle_pass_client_hsmfd( last_message = status.error_message(); return map_status(status); } +#else + last_message = "success"; + return PROXY_OK; +#endif } -proxy_stat proxy_handle_sign_withdrawal_tx( +proxy_stat proxy_handle_new_channel( + struct node_id *peer_id, + u64 dbid) +{ + STATUS_DEBUG( + "%s:%d %s " + "{ \"self_id\":%s, \"peer_id\":%s, \"dbid\":%" PRIu64 " }", + __FILE__, __LINE__, __FUNCTION__, + dump_node_id(&self_id).c_str(), + dump_node_id(peer_id).c_str(), + dbid); + + last_message = ""; + NewChannelRequest req; + marshal_node_id(&self_id, req.mutable_node_id()); + marshal_channel_nonce(peer_id, dbid, req.mutable_channel_nonce0()); + + ClientContext context; + NewChannelReply rsp; + Status status = stub->NewChannel(&context, req, &rsp); + if (status.ok()) { + STATUS_DEBUG("%s:%d %s { \"self_id\":%s }", + __FILE__, __LINE__, __FUNCTION__, + dump_node_id(&self_id).c_str()); + last_message = "success"; + return PROXY_OK; + } else { + status_unusual("%s:%d %s: self_id=%s %s", + __FILE__, __LINE__, __FUNCTION__, + dump_node_id(&self_id).c_str(), + status.error_message().c_str()); + last_message = status.error_message(); + return map_status(status); + } +} + +proxy_stat proxy_handle_ready_channel( struct node_id *peer_id, u64 dbid, - struct amount_sat *satoshi_out, - struct amount_sat *change_out, - u32 change_keyindex, - struct bitcoin_tx_output **outputs, - struct utxo **utxos, - struct bitcoin_tx *tx, - u8 ****o_wits) + bool is_outbound, + struct amount_sat *channel_value, + struct amount_msat *push_value, + struct bitcoin_txid *funding_txid, + u16 funding_txout, + u16 holder_to_self_delay, + u8 *holder_shutdown_script, + struct basepoints *counterparty_basepoints, + struct pubkey *counterparty_funding_pubkey, + u16 counterparty_to_self_delay, + u8 *counterparty_shutdown_script, + bool option_static_remotekey) { - fprintf(stderr, - "%s:%d %s self_id=%s peer_id=%s dbid=%" PRIu64 " " - "satoshi_out=%" PRIu64 " change_out=%" PRIu64 " " - "change_keyindex=%u utxos=%s outputs=%s tx=%s\n", + STATUS_DEBUG( + "%s:%d %s { " + "\"self_id\":%s, \"peer_id\":%s, \"dbid\":%" PRIu64 ", " + "\"is_outbound\":%s, \"channel_value\":%" PRIu64 ", " + "\"push_value\":%" PRIu64 ", " + "\"funding_txid\":%s, \"funding_txout\":%d, " + "\"holder_to_self_delay\":%d, \"holder_shutdown_script\":%s, " + "\"counterparty_basepoints\":%s, " + "\"counterparty_funding_pubkey\":%s, " + "\"counterparty_to_self_delay\":%d, " + "\"counterparty_shutdown_script\":%s, " + "\"option_static_remotekey\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_node_id(peer_id).c_str(), dbid, - satoshi_out->satoshis, - change_out->satoshis, - change_keyindex, - dump_utxos((const struct utxo **)utxos).c_str(), - dump_bitcoin_tx_outputs( - (const struct bitcoin_tx_output **)outputs).c_str(), - dump_tx(tx).c_str() + (is_outbound ? "true" : "false"), + channel_value->satoshis, + push_value->millisatoshis, + dump_bitcoin_txid(funding_txid).c_str(), + funding_txout, + holder_to_self_delay, + dump_hex(holder_shutdown_script, + tal_count(holder_shutdown_script)).c_str(), + dump_basepoints(counterparty_basepoints).c_str(), + dump_pubkey(counterparty_funding_pubkey).c_str(), + counterparty_to_self_delay, + dump_hex(counterparty_shutdown_script, + tal_count(counterparty_shutdown_script)).c_str(), + (option_static_remotekey ? "true" : "false") ); - status_debug( - "%s:%d %s self_id=%s peer_id=%s dbid=%" PRIu64 " " - "satoshi_out=%" PRIu64 " change_out=%" PRIu64 " " - "change_keyindex=%u utxos=%s outputs=%s tx=%s", + last_message = ""; + ReadyChannelRequest req; + marshal_node_id(&self_id, req.mutable_node_id()); + marshal_channel_nonce(peer_id, dbid, req.mutable_channel_nonce0()); + req.set_is_outbound(is_outbound); + req.set_channel_value_sat(channel_value->satoshis); + req.set_push_value_msat(push_value->millisatoshis); + marshal_outpoint(funding_txid, + funding_txout, req.mutable_funding_outpoint()); + req.set_holder_to_self_delay(holder_to_self_delay); + marshal_script(holder_shutdown_script, + req.mutable_holder_shutdown_script()); + marshal_basepoints(counterparty_basepoints, counterparty_funding_pubkey, + req.mutable_counterparty_basepoints()); + req.set_counterparty_to_self_delay(counterparty_to_self_delay); + marshal_script(counterparty_shutdown_script, + req.mutable_counterparty_shutdown_script()); + req.set_commitment_type( + option_static_remotekey ? + ReadyChannelRequest_CommitmentType_STATIC_REMOTEKEY : + ReadyChannelRequest_CommitmentType_LEGACY); + + ClientContext context; + ReadyChannelReply rsp; + Status status = stub->ReadyChannel(&context, req, &rsp); + if (status.ok()) { + STATUS_DEBUG("%s:%d %s { \"self_id\":%s }", + __FILE__, __LINE__, __FUNCTION__, + dump_node_id(&self_id).c_str()); + last_message = "success"; + return PROXY_OK; + } else { + status_unusual("%s:%d %s: self_id=%s %s", + __FILE__, __LINE__, __FUNCTION__, + dump_node_id(&self_id).c_str(), + status.error_message().c_str()); + last_message = status.error_message(); + return map_status(status); + } +} + +proxy_stat proxy_handle_sign_withdrawal_tx( + struct node_id *peer_id, + u64 dbid, + struct bitcoin_tx_output **outputs, + struct utxo **utxos, + struct wally_psbt *psbt, + u8 ****o_wits) +{ + STATUS_DEBUG( + "%s:%d %s { " + "\"self_id\":%s, \"peer_id\":%s, \"dbid\":%" PRIu64 ", " + "\"utxos\":%s, \"outputs\":%s, \"psbt\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_node_id(peer_id).c_str(), dbid, - satoshi_out->satoshis, - change_out->satoshis, - change_keyindex, dump_utxos((const struct utxo **)utxos).c_str(), dump_bitcoin_tx_outputs( (const struct bitcoin_tx_output **)outputs).c_str(), - dump_tx(tx).c_str() + dump_wally_psbt(psbt).c_str() ); last_message = ""; @@ -495,53 +628,33 @@ proxy_stat proxy_handle_sign_withdrawal_tx( marshal_node_id(&self_id, req.mutable_node_id()); marshal_channel_nonce(peer_id, dbid, req.mutable_channel_nonce()); - req.mutable_tx()->set_raw_tx_bytes(serialized_tx(tx, true)); - assert(tx->wtx->num_inputs == tal_count(utxos)); - for (size_t ii = 0; ii < tx->wtx->num_inputs; ii++) - marshal_utxo(utxos[ii], req.mutable_tx()->add_input_descs()); - - /* We expect exactly two total ouputs, with one non-change. */ - /* FIXME - next assert fails in - tests/test_closing.py::test_onchain_unwatch with num_outputs == 1 - assert(tx->wtx->num_outputs == 2); - */ - assert(tal_count(outputs) == 1); - for (size_t ii = 0; ii < tx->wtx->num_outputs; ii++) { - const struct wally_tx_output *out = &tx->wtx->outputs[ii]; - OutputDescriptor *odesc = req.mutable_tx()->add_output_descs(); - /* Does this output match the funding output? */ - if (memeq(out->script, out->script_len, - outputs[0]->script, tal_count(outputs[0]->script))) { - /* Yes, this is the funding output. */ - /* FIXME - we don't set anything? */ - } else { - /* Nope, this must be the change output. */ - assert(out->satoshi == change_out->satoshis); - odesc->mutable_key_loc()-> - set_key_index(change_keyindex); + req.mutable_tx()->set_raw_tx_bytes(serialized_wtx(psbt->tx, true)); + assert(psbt->tx->num_inputs >= tal_count(utxos)); + size_t uu = 0; + for (size_t ii = 0; ii < psbt->tx->num_inputs; ++ii) { + InputDescriptor *idesc = req.mutable_tx()->add_input_descs(); + if (uu < tal_count(utxos) && + wally_tx_input_spends(&psbt->tx->inputs[ii], + &utxos[uu]->txid, + utxos[uu]->outnum)) { + marshal_utxo(utxos[uu], idesc); + ++uu; } } + assert(uu == tal_count(utxos)); ClientContext context; SignFundingTxReply rsp; Status status = stub->SignFundingTx(&context, req, &rsp); if (status.ok()) { unmarshal_witnesses(rsp.witnesses(), o_wits); - fprintf(stderr, "%s:%d %s self_id=%s witnesses=%s\n", - __FILE__, __LINE__, __FUNCTION__, - dump_node_id(&self_id).c_str(), - dump_witnesses((u8 const ***) *o_wits).c_str()); - status_debug("%s:%d %s self_id=%s witnesses=%s", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s, \"witnesses\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_witnesses((u8 const ***) *o_wits).c_str()); last_message = "success"; return PROXY_OK; } else { - fprintf(stderr, "%s:%d %s: self_id=%s %s\n", - __FILE__, __LINE__, __FUNCTION__, - dump_node_id(&self_id).c_str(), - status.error_message().c_str()); status_unusual("%s:%d %s: self_id=%s %s", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), @@ -553,49 +666,43 @@ proxy_stat proxy_handle_sign_withdrawal_tx( proxy_stat proxy_handle_sign_remote_commitment_tx( struct bitcoin_tx *tx, - const struct pubkey *remote_funding_pubkey, - struct amount_sat *funding, + const struct pubkey *counterparty_funding_pubkey, struct node_id *peer_id, u64 dbid, - struct witscript const **output_witscripts, const struct pubkey *remote_per_commit, bool option_static_remotekey, struct bitcoin_signature *o_sig) { - status_debug( - "%s:%d %s self_id=%s peer_id=%s dbid=%" PRIu64 " " - "funding=%" PRIu64 " remote_funding_pubkey=%s " - "output_witscripts=%s remote_per_commit=%s " - "option_static_remotekey=%s tx=%s", + STATUS_DEBUG( + "%s:%d %s { " + "\"self_id\":%s, \"peer_id\":%s, \"dbid\":%" PRIu64 ", " + "\"counterparty_funding_pubkey\":%s, " + "\"remote_per_commit\":%s, " + "\"option_static_remotekey\":%s, \"tx\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_node_id(peer_id).c_str(), dbid, - funding->satoshis, - dump_pubkey(remote_funding_pubkey).c_str(), - dump_output_witscripts(output_witscripts).c_str(), + dump_pubkey(counterparty_funding_pubkey).c_str(), dump_pubkey(remote_per_commit).c_str(), (option_static_remotekey ? "true" : "false"), dump_tx(tx).c_str() ); last_message = ""; - SignRemoteCommitmentTxRequest req; + SignCounterpartyCommitmentTxRequest req; marshal_node_id(&self_id, req.mutable_node_id()); marshal_channel_nonce(peer_id, dbid, req.mutable_channel_nonce()); - marshal_pubkey(remote_funding_pubkey, - req.mutable_remote_funding_pubkey()); marshal_pubkey(remote_per_commit, req.mutable_remote_per_commit_point()); - req.set_option_static_remotekey(option_static_remotekey); - marshal_single_input_tx(tx, NULL, output_witscripts, req.mutable_tx()); + marshal_single_input_tx(tx, NULL, req.mutable_tx()); ClientContext context; SignatureReply rsp; - Status status = stub->SignRemoteCommitmentTx(&context, req, &rsp); + Status status = stub->SignCounterpartyCommitmentTx(&context, req, &rsp); if (status.ok()) { unmarshal_bitcoin_signature(rsp.signature(), o_sig); - status_debug("%s:%d %s self_id=%s sig=%s", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s, \"sig\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_bitcoin_signature(o_sig).c_str()); @@ -618,14 +725,14 @@ proxy_stat proxy_handle_get_per_commitment_point( struct pubkey *o_per_commitment_point, struct secret **o_old_secret) { - status_debug( - "%s:%d %s self_id=%s peer_id=%s dbid=%" PRIu64 " " - "n=%" PRIu64 "", - __FILE__, __LINE__, __FUNCTION__, - dump_node_id(&self_id).c_str(), - dump_node_id(peer_id).c_str(), - dbid, - n + STATUS_DEBUG("%s:%d %s { " + "\"self_id\":%s, \"peer_id\":%s, \"dbid\":%" PRIu64 ", " + "\"n\":%" PRIu64 " }", + __FILE__, __LINE__, __FUNCTION__, + dump_node_id(&self_id).c_str(), + dump_node_id(peer_id).c_str(), + dbid, + n ); last_message = ""; @@ -646,8 +753,9 @@ proxy_stat proxy_handle_get_per_commitment_point( *o_old_secret = tal_arr(tmpctx, struct secret, 1); unmarshal_secret(rsp.old_secret(), *o_old_secret); } - status_debug("%s:%d %s self_id=%s " - "per_commitment_point=%s old_secret=%s", + STATUS_DEBUG("%s:%d %s { " + "\"self_id\":%s, \"per_commitment_point\":%s, " + "\"old_secret\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_pubkey(o_per_commitment_point).c_str(), @@ -670,12 +778,12 @@ proxy_stat proxy_handle_sign_invoice( u8 *hrpu8, secp256k1_ecdsa_recoverable_signature *o_sig) { - status_debug( - "%s:%d %s self_id=%s u5bytes=%s hrpu8=%s", - __FILE__, __LINE__, __FUNCTION__, - dump_node_id(&self_id).c_str(), - dump_hex(u5bytes, tal_count(u5bytes)).c_str(), - string((const char *)hrpu8, tal_count(hrpu8)).c_str() + STATUS_DEBUG("%s:%d %s { " + "\"self_id\":%s, \"u5bytes\":%s \"hrpu8\":%s }", + __FILE__, __LINE__, __FUNCTION__, + dump_node_id(&self_id).c_str(), + dump_hex(u5bytes, tal_count(u5bytes)).c_str(), + string((const char *)hrpu8, tal_count(hrpu8)).c_str() ); last_message = ""; @@ -689,7 +797,7 @@ proxy_stat proxy_handle_sign_invoice( Status status = stub->SignInvoice(&context, req, &rsp); if (status.ok()) { unmarshal_ecdsa_recoverable_signature(rsp.signature(), o_sig); - status_debug("%s:%d %s self_id=%s sig=%s", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s, \"sig\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_secp256k1_ecdsa_recoverable_signature( @@ -710,8 +818,8 @@ proxy_stat proxy_handle_sign_message( u8 *msg, secp256k1_ecdsa_recoverable_signature *o_sig) { - status_debug( - "%s:%d %s self_id=%s msg=%s", + STATUS_DEBUG( + "%s:%d %s { \"self_id\":%s, \"msg\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_hex(msg, tal_count(msg)).c_str() @@ -727,7 +835,7 @@ proxy_stat proxy_handle_sign_message( Status status = stub->SignMessage(&context, req, &rsp); if (status.ok()) { unmarshal_ecdsa_recoverable_signature(rsp.signature(), o_sig); - status_debug("%s:%d %s self_id=%s sig=%s", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s, \"sig\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_secp256k1_ecdsa_recoverable_signature( @@ -748,9 +856,8 @@ proxy_stat proxy_handle_channel_update_sig( u8 *channel_update, secp256k1_ecdsa_signature *o_sig) { - status_debug( - "%s:%d %s self_id=%s " - "channel_update=%s", + STATUS_DEBUG("%s:%d %s { " + "\"self_id\":%s, \"channel_update\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_hex(channel_update, tal_count(channel_update)).c_str()); @@ -769,7 +876,7 @@ proxy_stat proxy_handle_channel_update_sig( Status status = stub->SignChannelUpdate(&context, req, &rsp); if (status.ok()) { unmarshal_ecdsa_signature(rsp.signature(), o_sig); - status_debug("%s:%d %s self_id=%s sig=%s", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s, \"sig\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_secp256k1_ecdsa_signature(o_sig).c_str()); @@ -791,12 +898,12 @@ proxy_stat proxy_handle_get_channel_basepoints( struct basepoints *o_basepoints, struct pubkey *o_funding_pubkey) { - status_debug( - "%s:%d %s self_id=%s peer_id=%s dbid=%" PRIu64 "", - __FILE__, __LINE__, __FUNCTION__, - dump_node_id(&self_id).c_str(), - dump_node_id(peer_id).c_str(), - dbid + STATUS_DEBUG("%s:%d %s { " + "\"self_id\":%s, \"peer_id\":%s \"dbid\":%" PRIu64 " }", + __FILE__, __LINE__, __FUNCTION__, + dump_node_id(&self_id).c_str(), + dump_node_id(peer_id).c_str(), + dbid ); last_message = ""; @@ -815,7 +922,9 @@ proxy_stat proxy_handle_get_channel_basepoints( unmarshal_pubkey(bps.delayed_payment(), &o_basepoints->delayed_payment); unmarshal_pubkey(bps.funding_pubkey(), o_funding_pubkey); - status_debug("%s:%d %s self_id=%s", + STATUS_DEBUG("%s:%d %s { " + "\"self_id\":%s, \"basepoints\":%s, " + "\"pubkey\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_basepoints(o_basepoints).c_str(), @@ -835,19 +944,20 @@ proxy_stat proxy_handle_get_channel_basepoints( proxy_stat proxy_handle_sign_mutual_close_tx( struct bitcoin_tx *tx, - const struct pubkey *remote_funding_pubkey, + const struct pubkey *counterparty_funding_pubkey, struct node_id *peer_id, u64 dbid, struct bitcoin_signature *o_sig) { - status_debug( - "%s:%d %s self_id=%s peer_id=%s dbid=%" PRIu64 " " - "remote_funding_pubkey=%s tx=%s", + STATUS_DEBUG( + "%s:%d %s { " + "\"self_id\":%s, \"peer_id\":%s, \"dbid\":%" PRIu64 ", " + "\"counterparty_funding_pubkey\":%s, \"tx\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_node_id(peer_id).c_str(), dbid, - dump_pubkey(remote_funding_pubkey).c_str(), + dump_pubkey(counterparty_funding_pubkey).c_str(), dump_tx(tx).c_str() ); @@ -855,16 +965,14 @@ proxy_stat proxy_handle_sign_mutual_close_tx( SignMutualCloseTxRequest req; marshal_node_id(&self_id, req.mutable_node_id()); marshal_channel_nonce(peer_id, dbid, req.mutable_channel_nonce()); - marshal_pubkey(remote_funding_pubkey, - req.mutable_remote_funding_pubkey()); - marshal_single_input_tx(tx, NULL, NULL, req.mutable_tx()); + marshal_single_input_tx(tx, NULL, req.mutable_tx()); ClientContext context; SignatureReply rsp; Status status = stub->SignMutualCloseTx(&context, req, &rsp); if (status.ok()) { unmarshal_bitcoin_signature(rsp.signature(), o_sig); - status_debug("%s:%d %s self_id=%s sig=%s", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s, \"sig\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_bitcoin_signature(o_sig).c_str()); @@ -882,36 +990,35 @@ proxy_stat proxy_handle_sign_mutual_close_tx( proxy_stat proxy_handle_sign_commitment_tx( struct bitcoin_tx *tx, - const struct pubkey *remote_funding_pubkey, + const struct pubkey *counterparty_funding_pubkey, struct node_id *peer_id, u64 dbid, struct bitcoin_signature *o_sig) { - status_debug( - "%s:%d %s self_id=%s peer_id=%s dbid=%" PRIu64 " " - "remote_funding_pubkey=%s tx=%s", + STATUS_DEBUG( + "%s:%d %s { " + "\"self_id\":%s, \"peer_id\":%s, \"dbid\":%" PRIu64 ", " + "\"counterparty_funding_pubkey\":%s, \"tx\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_node_id(peer_id).c_str(), dbid, - dump_pubkey(remote_funding_pubkey).c_str(), + dump_pubkey(counterparty_funding_pubkey).c_str(), dump_tx(tx).c_str() ); last_message = ""; - SignCommitmentTxRequest req; + SignHolderCommitmentTxRequest req; marshal_node_id(&self_id, req.mutable_node_id()); marshal_channel_nonce(peer_id, dbid, req.mutable_channel_nonce()); - marshal_pubkey(remote_funding_pubkey, - req.mutable_remote_funding_pubkey()); - marshal_single_input_tx(tx, NULL, NULL, req.mutable_tx()); + marshal_single_input_tx(tx, NULL, req.mutable_tx()); ClientContext context; SignatureReply rsp; - Status status = stub->SignCommitmentTx(&context, req, &rsp); + Status status = stub->SignHolderCommitmentTx(&context, req, &rsp); if (status.ok()) { unmarshal_bitcoin_signature(rsp.signature(), o_sig); - status_debug("%s:%d %s self_id=%s sig=%s", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s, \"sig\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_bitcoin_signature(o_sig).c_str()); @@ -934,8 +1041,10 @@ proxy_stat proxy_handle_cannouncement_sig( secp256k1_ecdsa_signature *o_node_sig, secp256k1_ecdsa_signature *o_bitcoin_sig) { - status_debug( - "%s:%d %s self_id=%s peer_id=%s dbid=%" PRIu64 " ca=%s", + STATUS_DEBUG( + "%s:%d %s { " + "\"self_id\":%s, \"peer_id\":%s, \"dbid\":%" PRIu64 ", " + "\"ca\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_node_id(peer_id).c_str(), @@ -961,7 +1070,9 @@ proxy_stat proxy_handle_cannouncement_sig( if (status.ok()) { unmarshal_ecdsa_signature(rsp.node_signature(), o_node_sig); unmarshal_ecdsa_signature(rsp.bitcoin_signature(), o_bitcoin_sig); - status_debug("%s:%d %s self_id=%s node_sig=%s bitcoin_sig=%s", + STATUS_DEBUG("%s:%d %s { " + "\"self_id\":%s, \"node_sig\":%s, " + "\"bitcoin_sig\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_secp256k1_ecdsa_signature(o_node_sig).c_str(), @@ -986,11 +1097,10 @@ proxy_stat proxy_handle_sign_local_htlc_tx( u64 dbid, struct bitcoin_signature *o_sig) { - status_debug( - "%s:%d %s self_id=%s peer_id=%s dbid=%" PRIu64 " " - "commit_num==%" PRIu64 " " - "wscript=%s " - "tx=%s", + STATUS_DEBUG( + "%s:%d %s { " + "\"self_id\":%s, \"peer_id\":%s, \"dbid\":%" PRIu64 ", " + "\"commit_num\":%" PRIu64 ", \"wscript\":%s, \"tx\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_node_id(peer_id).c_str(), @@ -1001,18 +1111,18 @@ proxy_stat proxy_handle_sign_local_htlc_tx( ); last_message = ""; - SignLocalHTLCTxRequest req; + SignHolderHTLCTxRequest req; marshal_node_id(&self_id, req.mutable_node_id()); marshal_channel_nonce(peer_id, dbid, req.mutable_channel_nonce()); req.set_n(commit_num); - marshal_single_input_tx(tx, wscript, NULL, req.mutable_tx()); + marshal_single_input_tx(tx, wscript, req.mutable_tx()); ClientContext context; SignatureReply rsp; - Status status = stub->SignLocalHTLCTx(&context, req, &rsp); + Status status = stub->SignHolderHTLCTx(&context, req, &rsp); if (status.ok()) { unmarshal_bitcoin_signature(rsp.signature(), o_sig); - status_debug("%s:%d %s self_id=%s sig=%s", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s, \"sig\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_bitcoin_signature(o_sig).c_str() @@ -1037,31 +1147,31 @@ proxy_stat proxy_handle_sign_remote_htlc_tx( u64 dbid, struct bitcoin_signature *o_sig) { - status_debug( - "%s:%d %s self_id=%s peer_id=%s dbid=%" PRIu64 " " - "wscript=%s tx=%s", - __FILE__, __LINE__, __FUNCTION__, - dump_node_id(&self_id).c_str(), - dump_node_id(peer_id).c_str(), - dbid, - dump_hex(wscript, tal_count(wscript)).c_str(), - dump_tx(tx).c_str() + STATUS_DEBUG("%s:%d %s { " + "\"self_id\":%s, \"peer_id\":%s, \"dbid\":%" PRIu64 ", " + "\"wscript\":%s, \"tx\":%s }", + __FILE__, __LINE__, __FUNCTION__, + dump_node_id(&self_id).c_str(), + dump_node_id(peer_id).c_str(), + dbid, + dump_hex(wscript, tal_count(wscript)).c_str(), + dump_tx(tx).c_str() ); last_message = ""; - SignRemoteHTLCTxRequest req; + SignCounterpartyHTLCTxRequest req; marshal_node_id(&self_id, req.mutable_node_id()); marshal_channel_nonce(peer_id, dbid, req.mutable_channel_nonce()); marshal_pubkey(remote_per_commit_point, req.mutable_remote_per_commit_point()); - marshal_single_input_tx(tx, wscript, NULL, req.mutable_tx()); + marshal_single_input_tx(tx, wscript, req.mutable_tx()); ClientContext context; SignatureReply rsp; - Status status = stub->SignRemoteHTLCTx(&context, req, &rsp); + Status status = stub->SignCounterpartyHTLCTx(&context, req, &rsp); if (status.ok()) { unmarshal_bitcoin_signature(rsp.signature(), o_sig); - status_debug("%s:%d %s self_id=%s sig=%s", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s. \"sig\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_bitcoin_signature(o_sig).c_str()); @@ -1085,11 +1195,10 @@ proxy_stat proxy_handle_sign_delayed_payment_to_us( u64 dbid, struct bitcoin_signature *o_sig) { - status_debug( - "%s:%d %s self_id=%s peer_id=%s dbid=%" PRIu64 " " - "commit_num==%" PRIu64 " " - "wscript=%s " - "tx=%s", + STATUS_DEBUG("%s:%d %s { " + "\"self_id\":%s, \"peer_id\":%s, dbid=%" PRIu64 ", " + "\"commit_num\":=%" PRIu64 ", " + "\"wscript\":%s, \"tx\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_node_id(peer_id).c_str(), @@ -1100,18 +1209,19 @@ proxy_stat proxy_handle_sign_delayed_payment_to_us( ); last_message = ""; - SignDelayedPaymentToUsRequest req; + SignDelayedSweepRequest req; marshal_node_id(&self_id, req.mutable_node_id()); marshal_channel_nonce(peer_id, dbid, req.mutable_channel_nonce()); - req.set_n(commit_num); - marshal_single_input_tx(tx, wscript, NULL, req.mutable_tx()); + req.set_input(0); + req.set_commitment_number(commit_num); + marshal_single_input_tx(tx, wscript, req.mutable_tx()); ClientContext context; SignatureReply rsp; - Status status = stub->SignDelayedPaymentToUs(&context, req, &rsp); + Status status = stub->SignDelayedSweep(&context, req, &rsp); if (status.ok()) { unmarshal_bitcoin_signature(rsp.signature(), o_sig); - status_debug("%s:%d %s self_id=%s sig=%s", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s, \"sig\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_bitcoin_signature(o_sig).c_str()); @@ -1135,9 +1245,9 @@ proxy_stat proxy_handle_sign_remote_htlc_to_us( u64 dbid, struct bitcoin_signature *o_sig) { - status_debug( - "%s:%d %s self_id=%s peer_id=%s dbid=%" PRIu64 " " - "wscript=%s tx=%s", + STATUS_DEBUG("%s:%d %s { " + "\"self_id\":%s, \"peer_id\":%s, \"dbid\":%" PRIu64 ", " + "\"wscript\":%s, \"tx\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_node_id(peer_id).c_str(), @@ -1147,19 +1257,20 @@ proxy_stat proxy_handle_sign_remote_htlc_to_us( ); last_message = ""; - SignRemoteHTLCToUsRequest req; + SignCounterpartyHTLCSweepRequest req; marshal_node_id(&self_id, req.mutable_node_id()); marshal_channel_nonce(peer_id, dbid, req.mutable_channel_nonce()); + req.set_input(0); marshal_pubkey(remote_per_commit_point, req.mutable_remote_per_commit_point()); - marshal_single_input_tx(tx, wscript, NULL, req.mutable_tx()); + marshal_single_input_tx(tx, wscript, req.mutable_tx()); ClientContext context; SignatureReply rsp; - Status status = stub->SignRemoteHTLCToUs(&context, req, &rsp); + Status status = stub->SignCounterpartyHTLCSweep(&context, req, &rsp); if (status.ok()) { unmarshal_bitcoin_signature(rsp.signature(), o_sig); - status_debug("%s:%d %s self_id=%s sig=%s", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s, \"sig\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_bitcoin_signature(o_sig).c_str()); @@ -1183,11 +1294,10 @@ proxy_stat proxy_handle_sign_penalty_to_us( u64 dbid, struct bitcoin_signature *o_sig) { - status_debug( - "%s:%d %s self_id=%s peer_id=%s dbid=%" PRIu64 " " - "revocation_secret=%s " - "wscript=%s " - "tx=%s", + STATUS_DEBUG( + "%s:%d %s { " + "\"self_id\":%s, \"peer_id\":%s, \"dbid\":%" PRIu64 ", " + "\"revocation_secret\":%s, \"wscript\":%s, \"tx\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_node_id(peer_id).c_str(), @@ -1199,18 +1309,19 @@ proxy_stat proxy_handle_sign_penalty_to_us( ); last_message = ""; - SignPenaltyToUsRequest req; + SignJusticeSweepRequest req; marshal_node_id(&self_id, req.mutable_node_id()); marshal_channel_nonce(peer_id, dbid, req.mutable_channel_nonce()); marshal_secret(revocation_secret, req.mutable_revocation_secret()); - marshal_single_input_tx(tx, wscript, NULL, req.mutable_tx()); + req.set_input(0); + marshal_single_input_tx(tx, wscript, req.mutable_tx()); ClientContext context; SignatureReply rsp; - Status status = stub->SignPenaltyToUs(&context, req, &rsp); + Status status = stub->SignJusticeSweep(&context, req, &rsp); if (status.ok()) { unmarshal_bitcoin_signature(rsp.signature(), o_sig); - status_debug("%s:%d %s self_id=%s sig=%s", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s, \"sig\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_bitcoin_signature(o_sig).c_str()); @@ -1233,9 +1344,10 @@ proxy_stat proxy_handle_check_future_secret( struct secret *suggested, bool *o_correct) { - status_debug( - "%s:%d %s self_id=%s peer_id=%s dbid=%" PRIu64 " " - "n=%" PRIu64 " suggested=%s", + STATUS_DEBUG( + "%s:%d %s { \"self_id\":%s, \"peer_id\":%s, " + "\"dbid\":%" PRIu64 ", " + "\"n\":%" PRIu64 ", \"suggested\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_node_id(peer_id).c_str(), @@ -1256,7 +1368,7 @@ proxy_stat proxy_handle_check_future_secret( Status status = stub->CheckFutureSecret(&context, req, &rsp); if (status.ok()) { *o_correct = rsp.correct(); - status_debug("%s:%d %s self_id=%s correct=%d", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s, \"correct\":%d }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), int(*o_correct)); last_message = "success"; @@ -1275,8 +1387,8 @@ proxy_stat proxy_handle_sign_node_announcement( u8 *node_announcement, secp256k1_ecdsa_signature *o_sig) { - status_debug( - "%s:%d %s self_id=%s ann=%s", + STATUS_DEBUG( + "%s:%d %s { \"self_id\":%s, \"ann\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_hex(node_announcement, @@ -1297,7 +1409,7 @@ proxy_stat proxy_handle_sign_node_announcement( Status status = stub->SignNodeAnnouncement(&context, req, &rsp); if (status.ok()) { unmarshal_ecdsa_signature(rsp.signature(), o_sig); - status_debug("%s:%d %s self_id=%s sig=%s", + STATUS_DEBUG("%s:%d %s { \"self_id\":%s, \"sig\":%s }", __FILE__, __LINE__, __FUNCTION__, dump_node_id(&self_id).c_str(), dump_secp256k1_ecdsa_signature(o_sig).c_str()); @@ -1313,11 +1425,18 @@ proxy_stat proxy_handle_sign_node_announcement( } } -// FIXME - This routine allows us to pretty print the tx to stderr -// from C code. Probably should remove it in production ... +// FIXME - These routines allows us to pretty print to stderr from C +// code. Probably should remove it in production ... + void print_tx(char const *tag, struct bitcoin_tx const *tx) { - fprintf(stderr, "%s: tx=%s\n", tag, dump_tx(tx).c_str()); + fprintf(stderr, "%s: bitcoin_tx=%s\n", tag, dump_tx(tx).c_str()); +} + +void print_psbt(char const *tag, const struct wally_psbt *psbt) +{ + fprintf(stderr, "%s: wally_psbt=%s\n", + tag, dump_wally_psbt(psbt).c_str()); } } /* extern "C" */ diff --git a/contrib/remote_hsmd/proxy.h b/contrib/remote_hsmd/proxy.hpp similarity index 80% rename from contrib/remote_hsmd/proxy.h rename to contrib/remote_hsmd/proxy.hpp index 58b066b94769..d034e7d68bcf 100644 --- a/contrib/remote_hsmd/proxy.h +++ b/contrib/remote_hsmd/proxy.hpp @@ -1,8 +1,18 @@ +#ifndef LIGHTNING_CONTRIB_REMOTE_HSMD_PROXY_H +#define LIGHTNING_CONTRIB_REMOTE_HSMD_PROXY_H + #ifdef __cplusplus extern "C" { #endif #include +#include + +#define STATUS_DEBUG(args...) \ + do { \ + fprintf(stderr, args); \ + fprintf(stderr, "\n"); \ + } while (false) enum proxy_status { /* SUCCESS */ @@ -30,6 +40,7 @@ void proxy_setup(void); proxy_stat proxy_init_hsm( struct bip32_key_version *bip32_key_version, struct chainparams const *chainparams, + bool coldstart, struct secret *hsm_secret, struct node_id *o_node_id, struct ext_key *o_ext_pub_key); @@ -43,23 +54,38 @@ proxy_stat proxy_handle_pass_client_hsmfd( u64 dbid, u64 capabilities); +proxy_stat proxy_handle_new_channel( + struct node_id *peer_id, + u64 dbid); + +proxy_stat proxy_handle_ready_channel( + struct node_id *peer_id, + u64 dbid, + bool is_outbound, + struct amount_sat *channel_value, + struct amount_msat *push_value, + struct bitcoin_txid *funding_txid, + u16 funding_txout, + u16 local_to_self_delay, + u8 *local_shutdown_script, + struct basepoints *remote_basepoints, + struct pubkey *remote_funding_pubkey, + u16 remote_to_self_delay, + u8 *remote_shutdown_script, + bool option_static_remotekey); + proxy_stat proxy_handle_sign_withdrawal_tx( struct node_id *peer_id, u64 dbid, - struct amount_sat *satoshi_out, - struct amount_sat *change_out, - u32 change_keyindex, struct bitcoin_tx_output **outputs, struct utxo **utxos, - struct bitcoin_tx *tx, + struct wally_psbt *psbt, u8 ****o_wits); proxy_stat proxy_handle_sign_remote_commitment_tx( struct bitcoin_tx *tx, const struct pubkey *remote_funding_pubkey, - struct amount_sat *funding, struct node_id *peer_id, u64 dbid, - struct witscript const **output_witscripts, const struct pubkey *remote_per_commit, bool option_static_remotekey, struct bitcoin_signature *o_sig); @@ -164,7 +190,10 @@ proxy_stat proxy_handle_sign_node_announcement( // FIXME - For debugging, remove for production. void print_tx(char const *tag, struct bitcoin_tx const *tx); +void print_psbt(char const *tag, const struct wally_psbt *psbt); #ifdef __cplusplus } /* extern C */ #endif + +#endif /* LIGHTNING_CONTRIB_REMOTE_HSMD_PROXY_H */ diff --git a/contrib/remote_hsmd/scripts/run-one-test b/contrib/remote_hsmd/scripts/run-one-test index 744a805b410d..cd1573dcd781 100755 --- a/contrib/remote_hsmd/scripts/run-one-test +++ b/contrib/remote_hsmd/scripts/run-one-test @@ -2,14 +2,10 @@ THETEST=$1 -export PYTHONPATH=\ -`pwd`/hsmd:\ -`pwd`/contrib/pylightning:\ -`pwd`/contrib/pyln-proto:\ -`pwd`/contrib/pyln-testing:\ -`pwd`/contrib/pyln-client:\ -$PYTHONPATH - +PYTHONPATH=\ +$PWD/contrib/pyln-client:\ +$PWD/contrib/pyln-testing:\ +$PWD/contrib/pyln-proto \ TEST_DEBUG=1 \ DEVELOPER=1 \ VALGRIND=0 \ @@ -17,5 +13,4 @@ SLOW_MACHINE=1 \ SUBDAEMON='hsmd:remote_hsmd' \ pytest \ $THETEST \ --v --timeout=550 --timeout_method=thread -x -s - +-v --timeout=550 --timeout_method=thread -x diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 9ea8079f1581..6fad535fa3e0 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -1545,6 +1545,74 @@ static struct io_plan *pass_client_hsmfd(struct io_conn *conn, send_pending_client_fd, c); } +/*~ This is used to declare a new channel. */ +static struct io_plan *handle_new_channel(struct io_conn *conn, + struct client *c, + const u8 *msg_in) +{ + struct node_id peer_id; + u64 dbid; + + if (!fromwire_hsm_new_channel(msg_in, &peer_id, &dbid)) + return bad_req(conn, c, msg_in); + + return req_reply(conn, c, + take(towire_hsm_new_channel_reply(NULL))); +} + +static bool mem_is_zero(const void *mem, size_t len) +{ + size_t i; + for (i = 0; i < len; ++i) + if (((const unsigned char *)mem)[i]) + return false; + return true; +} + +/*~ This is used to provide all unchanging public channel parameters. */ +static struct io_plan *handle_ready_channel(struct io_conn *conn, + struct client *c, + const u8 *msg_in) +{ + bool is_outbound; + struct amount_sat channel_value; + struct amount_msat push_value; + struct bitcoin_txid funding_txid; + u16 funding_txout; + u16 local_to_self_delay; + u8 *local_shutdown_script; + struct basepoints remote_basepoints; + struct pubkey remote_funding_pubkey; + u16 remote_to_self_delay; + u8 *remote_shutdown_script; + bool option_static_remotekey; + struct amount_msat value_msat; + + if (!fromwire_hsm_ready_channel(tmpctx, msg_in, &is_outbound, + &channel_value, &push_value, &funding_txid, + &funding_txout, &local_to_self_delay, + &local_shutdown_script, + &remote_basepoints, + &remote_funding_pubkey, + &remote_to_self_delay, + &remote_shutdown_script, + &option_static_remotekey)) + return bad_req(conn, c, msg_in); + + /* Fail fast if any values are obviously uninitialized. */ + assert(amount_sat_greater(channel_value, AMOUNT_SAT(0))); + assert(amount_sat_to_msat(&value_msat, channel_value)); + assert(amount_msat_less_eq(push_value, value_msat)); + assert(!mem_is_zero(&funding_txid, sizeof(funding_txid))); + assert(local_to_self_delay > 0); + assert(!mem_is_zero(&remote_basepoints, sizeof(remote_basepoints))); + assert(!mem_is_zero(&remote_funding_pubkey, sizeof(remote_funding_pubkey))); + assert(remote_to_self_delay > 0); + + return req_reply(conn, c, + take(towire_hsm_ready_channel_reply(NULL))); +} + /*~ For almost every wallet tx we use the BIP32 seed, but not for onchain * unilateral closes from a peer: they (may) have an output to us using a * public key based on the channel basepoints. It's a bit spammy to spend @@ -1962,6 +2030,7 @@ static bool check_client_capabilities(struct client *client, case WIRE_HSMD_GET_PER_COMMITMENT_POINT: case WIRE_HSMD_CHECK_FUTURE_SECRET: + case WIRE_HSMD_READY_CHANNEL: return (client->capabilities & HSM_CAP_COMMITMENT_POINT) != 0; case WIRE_HSMD_SIGN_REMOTE_COMMITMENT_TX: @@ -1972,6 +2041,7 @@ static bool check_client_capabilities(struct client *client, return (client->capabilities & HSM_CAP_SIGN_CLOSING_TX) != 0; case WIRE_HSMD_INIT: + case WIRE_HSMD_NEW_CHANNEL: case WIRE_HSMD_CLIENT_HSMFD: case WIRE_HSMD_SIGN_WITHDRAWAL: case WIRE_HSMD_SIGN_INVOICE: @@ -1990,6 +2060,8 @@ static bool check_client_capabilities(struct client *client, case WIRE_HSMD_CANNOUNCEMENT_SIG_REPLY: case WIRE_HSMD_CUPDATE_SIG_REPLY: case WIRE_HSMD_CLIENT_HSMFD_REPLY: + case WIRE_HSMD_NEW_CHANNEL_REPLY: + case WIRE_HSMD_READY_CHANNEL_REPLY: case WIRE_HSMD_NODE_ANNOUNCEMENT_SIG_REPLY: case WIRE_HSMD_SIGN_WITHDRAWAL_REPLY: case WIRE_HSMD_SIGN_INVOICE_REPLY: @@ -2039,6 +2111,12 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_CLIENT_HSMFD: return pass_client_hsmfd(conn, c, c->msg_in); + case WIRE_HSMD_NEW_CHANNEL: + return handle_new_channel(conn, c, c->msg_in); + + case WIRE_HSMD_READY_CHANNEL: + return handle_ready_channel(conn, c, c->msg_in); + case WIRE_HSMD_GET_CHANNEL_BASEPOINTS: return handle_get_channel_basepoints(conn, c, c->msg_in); @@ -2108,6 +2186,8 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_CANNOUNCEMENT_SIG_REPLY: case WIRE_HSMD_CUPDATE_SIG_REPLY: case WIRE_HSMD_CLIENT_HSMFD_REPLY: + case WIRE_HSMD_NEW_CHANNEL_REPLY: + case WIRE_HSMD_READY_CHANNEL_REPLY: case WIRE_HSMD_NODE_ANNOUNCEMENT_SIG_REPLY: case WIRE_HSMD_SIGN_WITHDRAWAL_REPLY: case WIRE_HSMD_SIGN_INVOICE_REPLY: diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index 86be49bb13d9..bc07b6b88d11 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -22,6 +22,16 @@ msgdata,hsmd_init_reply,node_id,node_id, msgdata,hsmd_init_reply,bip32,ext_key, msgdata,hsmd_init_reply,bolt12,pubkey32, +# Declare a new channel. +msgtype,hsmd_new_channel,30 +# Which identity to use for requests +msgdata,hsmd_new_channel,id,node_id, +# Database id for this client. +msgdata,hsmd_new_channel,dbid,u64, + +# No value returned. +msgtype,hsmd_new_channel_reply,130 + # Get a new HSM FD, with the specified capabilities msgtype,hsmd_client_hsmfd,9 # Which identity to use for requests @@ -43,6 +53,26 @@ msgtype,hsmd_get_channel_basepoints_reply,110 msgdata,hsmd_get_channel_basepoints_reply,basepoints,basepoints, msgdata,hsmd_get_channel_basepoints_reply,funding_pubkey,pubkey, +# Provide channel parameters. +msgtype,hsmd_ready_channel,31 +msgdata,hsmd_ready_channel,is_outbound,bool, +msgdata,hsmd_ready_channel,channel_value,amount_sat, +msgdata,hsmd_ready_channel,push_value,amount_msat, +msgdata,hsmd_ready_channel,funding_txid,bitcoin_txid, +msgdata,hsmd_ready_channel,funding_txout,u16, +msgdata,hsmd_ready_channel,local_to_self_delay,u16, +msgdata,hsmd_ready_channel,local_shutdown_script_len,u16, +msgdata,hsmd_ready_channel,local_shutdown_script,u8,local_shutdown_script_len +msgdata,hsmd_ready_channel,remote_basepoints,basepoints, +msgdata,hsmd_ready_channel,remote_funding_pubkey,pubkey, +msgdata,hsmd_ready_channel,remote_to_self_delay,u16, +msgdata,hsmd_ready_channel,remote_shutdown_script_len,u16, +msgdata,hsmd_ready_channel,remote_shutdown_script,u8,remote_shutdown_script_len +msgdata,hsmd_ready_channel,option_static_remotekey,bool, + +# No value returned. +msgtype,hsmd_ready_channel_reply,131 + # Return signature for a funding tx. #include @@ -142,6 +172,9 @@ msgdata,hsmd_sign_remote_commitment_tx,tx,bitcoin_tx, msgdata,hsmd_sign_remote_commitment_tx,remote_funding_key,pubkey, msgdata,hsmd_sign_remote_commitment_tx,remote_per_commit,pubkey, msgdata,hsmd_sign_remote_commitment_tx,option_static_remotekey,bool, +msgdata,hsmd_sign_remote_commitment_tx,num_htlc_rhash,u16, +msgdata,hsmd_sign_remote_commitment_tx,htlc_rhash,sha256,num_htlc_rhash +msgdata,hsmd_sign_remote_commitment_tx,commit_num,u64, # channeld asks HSM to sign remote HTLC tx. msgtype,hsmd_sign_remote_htlc_tx,20 diff --git a/openingd/openingd.c b/openingd/openingd.c index 1e55e834ea12..8c762480e318 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -494,6 +494,26 @@ static bool funder_finalize_channel_setup(struct state *state, char *err_reason; struct wally_tx_output *direct_outputs[NUM_SIDES]; + /*~ Channel is ready; Report the channel parameters to the signer. */ + msg = towire_hsm_ready_channel(NULL, + true, /* is_outbound */ + state->funding, + state->push_msat, + &state->funding_txid, + state->funding_txout, + state->localconf.to_self_delay, + state->upfront_shutdown_script[LOCAL], + &state->their_points, + &state->their_funding_pubkey, + state->remoteconf.to_self_delay, + state->upfront_shutdown_script[REMOTE], + state->option_static_remotekey); + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsm_ready_channel_reply(msg)) + status_failed(STATUS_FAIL_HSM_IO, "Bad ready_channel_reply %s", + tal_hex(tmpctx, msg)); + /*~ Now we can initialize the `struct channel`. This represents * the current channel state and is how we can generate the current * commitment transaction. @@ -994,6 +1014,26 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) &state->channel_id), type_to_string(msg, struct channel_id, &id_in)); + /*~ Channel is ready; Report the channel parameters to the signer. */ + msg = towire_hsm_ready_channel(NULL, + false, /* is_outbound */ + state->funding, + state->push_msat, + &state->funding_txid, + state->funding_txout, + state->localconf.to_self_delay, + state->upfront_shutdown_script[LOCAL], + &theirs, + &their_funding_pubkey, + state->remoteconf.to_self_delay, + state->upfront_shutdown_script[REMOTE], + state->option_static_remotekey); + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsm_ready_channel_reply(msg)) + status_failed(STATUS_FAIL_HSM_IO, "Bad ready_channel_reply %s", + tal_hex(tmpctx, msg)); + /* Now we can create the channel structure. */ state->channel = new_initial_channel(state, &state->channel_id, diff --git a/tests/test_db.py b/tests/test_db.py index 9cd625a46e4a..c99599707baa 100644 --- a/tests/test_db.py +++ b/tests/test_db.py @@ -133,6 +133,7 @@ def test_max_channel_id(node_factory, bitcoind): @unittest.skipIf(not COMPAT, "needs COMPAT to convert obsolete db") @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "This test is based on a sqlite3 snapshot") @unittest.skipIf(TEST_NETWORK != 'regtest', "The network must match the DB snapshot") +@unittest.skipIf(os.getenv('SUBDAEMON', 'xxx') == 'hsmd:remote_hsmd', "remote_hsmd doesn't like channel_nonce changing") def test_scid_upgrade(node_factory, bitcoind): bitcoind.generate_block(1) @@ -146,6 +147,7 @@ def test_scid_upgrade(node_factory, bitcoind): @unittest.skipIf(not COMPAT, "needs COMPAT to convert obsolete db") @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "This test is based on a sqlite3 snapshot") @unittest.skipIf(TEST_NETWORK != 'regtest', "The network must match the DB snapshot") +@unittest.skipIf(os.getenv('SUBDAEMON', 'xxx') == 'hsmd:remote_hsmd', "remote_hsmd doesn't like channel_nonce changing") def test_last_tx_psbt_upgrade(node_factory, bitcoind): bitcoind.generate_block(12)