From 3705b5f60592f59dead5c24495ebd09def8d3095 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Tue, 19 Nov 2019 17:05:16 -0600 Subject: [PATCH] devtools: add privkey+hash printing to mkcommit/mkgossip We updated the protocol spec tests to verify a sig from a hash and a private key; this updates mkcommit + mkgossip utilities to print out the procotol compatible SIG() notation for all signatures. --verbose will print a computed signature and more data as well. Also adds --verbose flag to mkgossip. Changelog-None --- bitcoin/signature.c | 9 +++--- bitcoin/signature.h | 14 +++++++++ devtools/mkcommit.c | 74 +++++++++++++++++++++++++++++++++------------ devtools/mkgossip.c | 47 +++++++++++++++++++++++----- 4 files changed, 114 insertions(+), 30 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index e40afb4f8..3a308bb46 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -107,13 +107,14 @@ void sign_hash(const struct privkey *privkey, privkey->secret.data, NULL, extra_entropy); ((u32 *)extra_entropy)[0]++; } while (!sig_has_low_r(s)); + assert(ok); } -static void bitcoin_tx_hash_for_sig(const struct bitcoin_tx *tx, unsigned int in, - const u8 *script, - enum sighash_type sighash_type, - struct sha256_double *dest) +void bitcoin_tx_hash_for_sig(const struct bitcoin_tx *tx, unsigned int in, + const u8 *script, + enum sighash_type sighash_type, + struct sha256_double *dest) { int ret; u8 value[9]; diff --git a/bitcoin/signature.h b/bitcoin/signature.h index de0d3342d..28df2bd2c 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -46,6 +46,20 @@ struct bitcoin_signature { enum sighash_type sighash_type; }; +/** + * bitcoin_tx_hash_for_sig - produce hash for a transaction + * + * @tx - tx to hash + * @in - index that this 'hash' is for + * @script - script for the index that's being 'hashed for' + * @sighash_type - sighash_type to hash for + * @dest - hash result + */ +void bitcoin_tx_hash_for_sig(const struct bitcoin_tx *tx, unsigned int in, + const u8 *script, + enum sighash_type sighash_type, + struct sha256_double *dest); + /** * sign_hash - produce a raw secp256k1 signature (with low R value). * @p: secret key diff --git a/devtools/mkcommit.c b/devtools/mkcommit.c index bc138c728..743009e31 100644 --- a/devtools/mkcommit.c +++ b/devtools/mkcommit.c @@ -162,16 +162,6 @@ static int parse_config(char *argv[], return argnum; } -static char *sig_as_hex(const struct bitcoin_signature *sig) -{ - u8 compact_sig[64]; - - secp256k1_ecdsa_signature_serialize_compact(secp256k1_ctx, - compact_sig, - &sig->s); - return tal_hexstr(NULL, compact_sig, sizeof(compact_sig)); -} - static int parse_htlc(char *argv[], struct added_htlc **htlcs, enum htlc_state **htlc_states, @@ -224,6 +214,33 @@ static const struct preimage *preimage_of(const struct sha256 *hash, abort(); } +static char *sig_as_hex(const struct bitcoin_signature *sig) +{ + u8 compact_sig[64]; + + secp256k1_ecdsa_signature_serialize_compact(secp256k1_ctx, + compact_sig, + &sig->s); + return tal_hexstr(NULL, compact_sig, sizeof(compact_sig)); +} + + +static char *sig_notation(const struct sha256_double *hash, + const struct privkey *privkey, + const struct bitcoin_signature *sig) +{ + const char *pstr = tal_hexstr(NULL, privkey->secret.data, sizeof(privkey->secret.data)); + const char *hstr = type_to_string(NULL, struct sha256_double, hash); + + if (verbose) + return tal_fmt(NULL, + "SIG(%s:%s)\n privkey: %s\n tx_hash: %s\n" + " sig: %s", + pstr, hstr, pstr, hstr, sig_as_hex(sig)); + + return tal_fmt(NULL, "SIG(%s:%s)", pstr, hstr); +} + int main(int argc, char *argv[]) { struct secrets local, remote; @@ -252,6 +269,7 @@ int main(int argc, char *argv[]) struct privkey local_htlc_privkey, remote_htlc_privkey; struct pubkey local_htlc_pubkey, remote_htlc_pubkey; bool option_static_remotekey = false; + struct sha256_double hash; setup_locale(); chainparams = chainparams_for_network("bitcoin"); @@ -386,26 +404,33 @@ int main(int argc, char *argv[]) &local_per_commit_point, commitnum, LOCAL); printf("## local_commitment\n" - "# input amount %s, funding_wscript %s, key %s\n", + "# input amount %s, funding_wscript %s, pubkey %s\n", type_to_string(NULL, struct amount_sat, &funding_amount), tal_hex(NULL, funding_wscript), type_to_string(NULL, struct pubkey, &funding_localkey)); printf("# unsigned local commitment tx: %s\n", tal_hex(NULL, linearize_tx(NULL, local_txs[0]))); + /* Get the hash out, for printing */ + bitcoin_tx_hash_for_sig(local_txs[0], 0, funding_wscript, + SIGHASH_ALL, &hash); sign_tx_input(local_txs[0], 0, NULL, funding_wscript, &local.funding_privkey, &funding_localkey, SIGHASH_ALL, &local_sig); - printf("localsig_on_local: %s\n", sig_as_hex(&local_sig)); + printf("localsig_on_local: %s\n", sig_notation(&hash, + &local.funding_privkey, + &local_sig)); sign_tx_input(local_txs[0], 0, NULL, funding_wscript, &remote.funding_privkey, &funding_remotekey, SIGHASH_ALL, &remote_sig); - printf("remotesig_on_local: %s\n", sig_as_hex(&remote_sig)); + printf("remotesig_on_local: %s\n", sig_notation(&hash, + &remote.funding_privkey, + &remote_sig)); witness = bitcoin_witness_2of2(NULL, &local_sig, &remote_sig, @@ -452,6 +477,9 @@ int main(int argc, char *argv[]) = tal_dup(local_txs[1+i], struct amount_sat, &amt); printf("# wscript: %s\n", tal_hex(NULL, wscripts[1+i])); + + bitcoin_tx_hash_for_sig(local_txs[1+i], 0, wscripts[1+i], + SIGHASH_ALL, &hash); sign_tx_input(local_txs[1+i], 0, NULL, wscripts[1+i], &local_htlc_privkey, &local_htlc_pubkey, SIGHASH_ALL, &local_htlc_sig); @@ -459,9 +487,9 @@ int main(int argc, char *argv[]) &remote_htlc_privkey, &remote_htlc_pubkey, SIGHASH_ALL, &remote_htlc_sig); printf("localsig_on_local output %zu: %s\n", - i, sig_as_hex(&local_htlc_sig)); + i, sig_notation(&hash, &local_htlc_privkey, &local_htlc_sig)); printf("remotesig_on_local output %zu: %s\n", - i, sig_as_hex(&remote_htlc_sig)); + i, sig_notation(&hash, &remote_htlc_privkey, &remote_htlc_sig)); if (htlc_owner(htlcmap[i]) == LOCAL) witness = bitcoin_witness_htlc_timeout_tx(NULL, @@ -496,19 +524,25 @@ int main(int argc, char *argv[]) printf("# unsigned remote commitment tx: %s\n", tal_hex(NULL, linearize_tx(NULL, remote_txs[0]))); + bitcoin_tx_hash_for_sig(remote_txs[0], 0, funding_wscript, + SIGHASH_ALL, &hash); sign_tx_input(remote_txs[0], 0, NULL, funding_wscript, &local.funding_privkey, &funding_localkey, SIGHASH_ALL, &local_sig); - printf("localsig_on_remote: %s\n", sig_as_hex(&local_sig)); + printf("localsig_on_remote: %s\n", sig_notation(&hash, + &local.funding_privkey, + &local_sig)); sign_tx_input(remote_txs[0], 0, NULL, funding_wscript, &remote.funding_privkey, &funding_remotekey, SIGHASH_ALL, &remote_sig); - printf("remotesig_on_remote: %s\n", sig_as_hex(&remote_sig)); + printf("remotesig_on_remote: %s\n", sig_notation(&hash, + &remote.funding_privkey, + &remote_sig)); witness = bitcoin_witness_2of2(NULL, &local_sig, &remote_sig, @@ -555,6 +589,8 @@ int main(int argc, char *argv[]) = tal_dup(remote_txs[1+i], struct amount_sat, &amt); printf("# wscript: %s\n", tal_hex(NULL, wscripts[1+i])); + bitcoin_tx_hash_for_sig(remote_txs[1+i], 0, wscripts[1+i], + SIGHASH_ALL, &hash); sign_tx_input(remote_txs[1+i], 0, NULL, wscripts[1+i], &local_htlc_privkey, &local_htlc_pubkey, SIGHASH_ALL, &local_htlc_sig); @@ -562,9 +598,9 @@ int main(int argc, char *argv[]) &remote_htlc_privkey, &remote_htlc_pubkey, SIGHASH_ALL, &remote_htlc_sig); printf("localsig_on_remote output %zu: %s\n", - i, sig_as_hex(&local_htlc_sig)); + i, sig_notation(&hash, &local_htlc_privkey, &local_htlc_sig)); printf("remotesig_on_remote output %zu: %s\n", - i, sig_as_hex(&remote_htlc_sig)); + i, sig_notation(&hash, &remote_htlc_privkey, &remote_htlc_sig)); if (htlc_owner(htlcmap[i]) == REMOTE) witness = bitcoin_witness_htlc_timeout_tx(NULL, diff --git a/devtools/mkgossip.c b/devtools/mkgossip.c index b6cf9db7b..d605cdbd2 100644 --- a/devtools/mkgossip.c +++ b/devtools/mkgossip.c @@ -14,13 +14,17 @@ #include #include #include +#include #include #include +#include #include #include #include #include +static bool verbose = false; + struct update_opts { u32 timestamp; u32 cltv_expiry_delta; @@ -79,6 +83,26 @@ static char *sig_as_hex(const secp256k1_ecdsa_signature *sig) return tal_hexstr(NULL, compact_sig, sizeof(compact_sig)); } +static char *sig_notation(const struct privkey *privkey, + struct sha256_double *hash, + const secp256k1_ecdsa_signature *sig) +{ + const char *pstr = tal_hexstr(NULL, privkey->secret.data, + sizeof(privkey->secret.data)); + const char *hstr = + type_to_string(NULL, struct sha256_double, hash); + + if (verbose) + return tal_fmt(NULL, + "SIG(%s:%s)\n" + " -- privkey= %s\n" + " -- tx_hash= %s\n" + " -- computed_sig= %s", + pstr, hstr, pstr, hstr, sig_as_hex(sig)); + + return tal_fmt(NULL, "SIG(%s:%s)", pstr, hstr); +} + /* BOLT #7: * * The checksum of a `channel_update` is the CRC32C checksum as specified in @@ -145,7 +169,7 @@ static void print_update(const struct bitcoin_blkid *chainhash, sign_hash(privkey, &hash, &sig); printf("type=channel_update\n"); - printf(" signature=%s\n", sig_as_hex(&sig)); + printf(" signature=%s\n", sig_notation(privkey, &hash, &sig)); printf(" chain_hash=%s\n", tal_hexstr(NULL, chainhash, sizeof(*chainhash))); printf(" short_channel_id=%s\n", short_channel_id_to_str(NULL, scid)); printf(" timestamp=%u\n", opts->timestamp); @@ -189,7 +213,7 @@ static void print_nannounce(const struct node_id *nodeid, sign_hash(privkey, &hash, &sig); printf("type=node_announcement\n"); - printf(" signature=%s\n", sig_as_hex(&sig)); + printf(" signature=%s\n", sig_notation(privkey, &hash, &sig)); printf(" features=%s\n", tal_hex(NULL, NULL)); printf(" timestamp=%u\n", opts->timestamp); printf(" node_id=%s\n", node_id_to_hexstr(NULL, nodeid)); @@ -220,7 +244,7 @@ int main(int argc, char *argv[]) secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); - if (argc != 8 + 7 * 2) + if (argc < 8 + 7 * 2) errx(1, "Usage: mkgossip update-opts-1 update-opts-2\n" "Where is:\n" " \n" @@ -231,6 +255,11 @@ int main(int argc, char *argv[]) " \n" " "); + opt_register_noarg("-v|--verbose", opt_set_bool, &verbose, + "Increase verbosity"); + + opt_parse(&argc, argv, opt_log_stderr_exit); + argnum = 1; if (!short_channel_id_from_str(argv[argnum], strlen(argv[argnum]), &scid)) errx(1, "Bad scid"); @@ -297,10 +326,14 @@ int main(int argc, char *argv[]) sign_hash(&funding_privkey[1], &hash, &bitcoinsig[1]); printf("type=channel_announcement\n"); - printf(" node_signature_1=%s\n", sig_as_hex(&nodesig[lesser_key])); - printf(" node_signature_2=%s\n", sig_as_hex(&nodesig[!lesser_key])); - printf(" bitcoin_signature_1=%s\n", sig_as_hex(&bitcoinsig[lesser_key])); - printf(" bitcoin_signature_2=%s\n", sig_as_hex(&bitcoinsig[!lesser_key])); + printf(" node_signature_1=%s\n", + sig_notation(&node_privkey[lesser_key], &hash, &nodesig[lesser_key])); + printf(" node_signature_2=%s\n", + sig_notation(&node_privkey[!lesser_key], &hash, &nodesig[!lesser_key])); + printf(" bitcoin_signature_1=%s\n", + sig_notation(&funding_privkey[lesser_key], &hash, &bitcoinsig[lesser_key])); + printf(" bitcoin_signature_2=%s\n", + sig_notation(&funding_privkey[!lesser_key], &hash, &bitcoinsig[!lesser_key])); printf(" features=%s\n", tal_hex(NULL, features)); printf(" chain_hash=%s\n", tal_hexstr(NULL, &chainhash, sizeof(chainhash))); printf(" short_channel_id=%s\n", short_channel_id_to_str(NULL, &scid));