diff --git a/bitcoin/Makefile b/bitcoin/Makefile index a0536df0b611..7d7767dd832a 100644 --- a/bitcoin/Makefile +++ b/bitcoin/Makefile @@ -4,6 +4,7 @@ BITCOIN_SRC := \ bitcoin/base58.c \ bitcoin/block.c \ bitcoin/chainparams.c \ + bitcoin/feerate.c \ bitcoin/locktime.c \ bitcoin/preimage.c \ bitcoin/privkey.c \ diff --git a/bitcoin/feerate.c b/bitcoin/feerate.c new file mode 100644 index 000000000000..696ec4b39b29 --- /dev/null +++ b/bitcoin/feerate.c @@ -0,0 +1,40 @@ +#include +#include +#include + +u32 feerate_from_style(u32 feerate, enum feerate_style style) +{ + switch (style) { + case FEERATE_PER_KSIPA: + return feerate; + case FEERATE_PER_KBYTE: + /* Everyone uses satoshi per kbyte, but we use satoshi per ksipa + * (don't round down to zero though)! */ + return (feerate + 3) / 4; + } + abort(); +} + +u32 feerate_to_style(u32 feerate_perkw, enum feerate_style style) +{ + switch (style) { + case FEERATE_PER_KSIPA: + return feerate_perkw; + case FEERATE_PER_KBYTE: + if ((u64)feerate_perkw * 4 > UINT_MAX) + return UINT_MAX; + return feerate_perkw * 4; + } + abort(); +} + +const char *feerate_style_name(enum feerate_style style) +{ + switch (style) { + case FEERATE_PER_KBYTE: + return "perkb"; + case FEERATE_PER_KSIPA: + return "perkw"; + } + abort(); +} diff --git a/bitcoin/feerate.h b/bitcoin/feerate.h index a0379a43295e..43bec21181d5 100644 --- a/bitcoin/feerate.h +++ b/bitcoin/feerate.h @@ -3,6 +3,7 @@ #include "config.h" #include #include +#include /* bitcoind considers 250 satoshi per kw to be the minimum acceptable fee: * less than this won't even relay. @@ -33,6 +34,11 @@ */ #define FEERATE_FLOOR 253 +enum feerate_style { + FEERATE_PER_KSIPA, + FEERATE_PER_KBYTE +}; + static inline u32 feerate_floor(void) { /* Assert that bitcoind will see this as above minRelayTxFee */ @@ -47,4 +53,9 @@ static inline u32 feerate_floor(void) return FEERATE_FLOOR; } + +u32 feerate_from_style(u32 feerate, enum feerate_style style); +u32 feerate_to_style(u32 feerate_perkw, enum feerate_style style); +const char *feerate_style_name(enum feerate_style style); + #endif /* LIGHTNING_BITCOIN_FEERATE_H */ diff --git a/bitcoin/test/run-bitcoin_block_from_hex.c b/bitcoin/test/run-bitcoin_block_from_hex.c index 6bbcc127490f..e9a0216608d6 100644 --- a/bitcoin/test/run-bitcoin_block_from_hex.c +++ b/bitcoin/test/run-bitcoin_block_from_hex.c @@ -21,14 +21,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire */ const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) { fprintf(stderr, "fromwire called!\n"); abort(); } diff --git a/bitcoin/test/run-tx-encode.c b/bitcoin/test/run-tx-encode.c index 03de237ef6d4..3437f9b5228f 100644 --- a/bitcoin/test/run-tx-encode.c +++ b/bitcoin/test/run-tx-encode.c @@ -22,14 +22,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire */ const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) { fprintf(stderr, "fromwire called!\n"); abort(); } diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 6469fa2850c9..b2ea98c54fe6 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -803,3 +803,20 @@ size_t bitcoin_tx_simple_input_weight(bool p2sh) return weight; } + +struct amount_sat change_amount(struct amount_sat excess, u32 feerate_perkw) +{ + size_t outweight; + + /* Must be able to pay for its own additional weight */ + outweight = bitcoin_tx_output_weight(BITCOIN_SCRIPTPUBKEY_P2WPKH_LEN); + if (!amount_sat_sub(&excess, + excess, amount_tx_fee(feerate_perkw, outweight))) + return AMOUNT_SAT(0); + + /* Must be non-dust */ + if (!amount_sat_greater_eq(excess, chainparams->dust_limit)) + return AMOUNT_SAT(0); + + return excess; +} diff --git a/bitcoin/tx.h b/bitcoin/tx.h index e4f7264695d8..f62c5c0f761d 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -241,4 +241,15 @@ size_t bitcoin_tx_input_sig_weight(void); /* We only do segwit inputs, and we assume witness is sig + key */ size_t bitcoin_tx_simple_input_weight(bool p2sh); +/** + * change_amount - Is it worth making a P2WPKH change output at this feerate? + * @excess: input amount we have above the tx fee and other outputs. + * @feerate_perkw: feerate. + * + * If it's not worth (or possible) to make change, returns AMOUNT_SAT(0). + * Otherwise returns the amount of the change output to add (@excess minus + * the additional fee for the change output itself). + */ +struct amount_sat change_amount(struct amount_sat excess, u32 feerate_perkw); + #endif /* LIGHTNING_BITCOIN_TX_H */ diff --git a/cli/test/run-large-input.c b/cli/test/run-large-input.c index 2d4d01cf8689..8add9a51cf0d 100644 --- a/cli/test/run-large-input.c +++ b/cli/test/run-large-input.c @@ -47,14 +47,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire_amount_msat */ struct amount_msat fromwire_amount_msat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_amount_msat called!\n"); abort(); } diff --git a/cli/test/run-remove-hint.c b/cli/test/run-remove-hint.c index 0207dc5f2f44..02ab66cbffd5 100644 --- a/cli/test/run-remove-hint.c +++ b/cli/test/run-remove-hint.c @@ -50,14 +50,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire_amount_msat */ struct amount_msat fromwire_amount_msat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_amount_msat called!\n"); abort(); } diff --git a/common/json_tok.c b/common/json_tok.c index b7d8c9bb8577..a50b0d3d559f 100644 --- a/common/json_tok.c +++ b/common/json_tok.c @@ -1,8 +1,14 @@ +#include +#include +#include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -330,3 +336,172 @@ struct command_result *param_secrets_array(struct command *cmd, } return NULL; } + +struct command_result *param_feerate_val(struct command *cmd, + const char *name, const char *buffer, + const jsmntok_t *tok, + u32 **feerate_per_kw) +{ + jsmntok_t base = *tok, suffix = *tok; + enum feerate_style style; + unsigned int num; + + /* We have to split the number and suffix. */ + suffix.start = suffix.end; + while (suffix.start > base.start && !isdigit(buffer[suffix.start-1])) { + suffix.start--; + base.end--; + } + + if (!json_to_number(buffer, &base, &num)) { + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "'%s' prefix should be an integer, not '%.*s'", + name, base.end - base.start, + buffer + base.start); + } + + if (suffix.end == suffix.start + || json_tok_streq(buffer, &suffix, + feerate_style_name(FEERATE_PER_KBYTE))) { + style = FEERATE_PER_KBYTE; + } else if (json_tok_streq(buffer, &suffix, + feerate_style_name(FEERATE_PER_KSIPA))) { + style = FEERATE_PER_KSIPA; + } else { + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "'%s' suffix should be '%s' or '%s', not '%.*s'", + name, + feerate_style_name(FEERATE_PER_KSIPA), + feerate_style_name(FEERATE_PER_KBYTE), + suffix.end - suffix.start, + buffer + suffix.start); + } + + *feerate_per_kw = tal(cmd, u32); + **feerate_per_kw = feerate_from_style(num, style); + if (**feerate_per_kw < FEERATE_FLOOR) + **feerate_per_kw = FEERATE_FLOOR; + return NULL; +} + +/** + * segwit_addr_net_decode - Try to decode a Bech32 address and detect + * testnet/mainnet/regtest/signet + * + * This processes the address and returns a string if it is a Bech32 + * address specified by BIP173. The string is set whether it is + * testnet ("tb"), mainnet ("bc"), regtest ("bcrt"), or signet ("sb") + * It does not check, witness version and program size restrictions. + * + * Out: witness_version: Pointer to an int that will be updated to contain + * the witness program version (between 0 and 16 inclusive). + * witness_program: Pointer to a buffer of size 40 that will be updated + * to contain the witness program bytes. + * witness_program_len: Pointer to a size_t that will be updated to + * contain the length of bytes in witness_program. + * In: addrz: Pointer to the null-terminated address. + * Returns string containing the human readable segment of bech32 address + */ +static const char *segwit_addr_net_decode(int *witness_version, + uint8_t *witness_program, + size_t *witness_program_len, + const char *addrz, + const struct chainparams *chainparams) +{ + if (segwit_addr_decode(witness_version, witness_program, + witness_program_len, chainparams->bip173_name, + addrz)) + return chainparams->bip173_name; + else + return NULL; +} + +enum address_parse_result +json_to_address_scriptpubkey(const tal_t *ctx, + const struct chainparams *chainparams, + const char *buffer, + const jsmntok_t *tok, const u8 **scriptpubkey) +{ + struct bitcoin_address destination; + int witness_version; + /* segwit_addr_net_decode requires a buffer of size 40, and will + * not write to the buffer if the address is too long, so a buffer + * of fixed size 40 will not overflow. */ + uint8_t witness_program[40]; + size_t witness_program_len; + + char *addrz; + const char *bip173; + + bool parsed; + bool right_network; + u8 addr_version; + + parsed = + ripemd160_from_base58(&addr_version, &destination.addr, + buffer + tok->start, tok->end - tok->start); + + if (parsed) { + if (addr_version == chainparams->p2pkh_version) { + *scriptpubkey = scriptpubkey_p2pkh(ctx, &destination); + return ADDRESS_PARSE_SUCCESS; + } else if (addr_version == chainparams->p2sh_version) { + *scriptpubkey = + scriptpubkey_p2sh_hash(ctx, &destination.addr); + return ADDRESS_PARSE_SUCCESS; + } else { + return ADDRESS_PARSE_WRONG_NETWORK; + } + /* Insert other parsers that accept pointer+len here. */ + } + + /* Generate null-terminated address. */ + addrz = tal_dup_arr(ctx, char, buffer + tok->start, tok->end - tok->start, 1); + addrz[tok->end - tok->start] = '\0'; + + bip173 = segwit_addr_net_decode(&witness_version, witness_program, + &witness_program_len, addrz, chainparams); + + if (bip173) { + bool witness_ok = false; + if (witness_version == 0 && (witness_program_len == 20 || + witness_program_len == 32)) { + witness_ok = true; + } + /* Insert other witness versions here. */ + + if (witness_ok) { + *scriptpubkey = scriptpubkey_witness_raw(ctx, witness_version, + witness_program, witness_program_len); + parsed = true; + right_network = streq(bip173, chainparams->bip173_name); + } + } + /* Insert other parsers that accept null-terminated string here. */ + + tal_free(addrz); + + if (parsed) { + if (right_network) + return ADDRESS_PARSE_SUCCESS; + else + return ADDRESS_PARSE_WRONG_NETWORK; + } + + return ADDRESS_PARSE_UNRECOGNIZED; +} + +struct command_result *param_txid(struct command *cmd, + const char *name, + const char *buffer, + const jsmntok_t *tok, + struct bitcoin_txid **txid) +{ + *txid = tal(cmd, struct bitcoin_txid); + if (json_to_txid(buffer, tok, *txid)) + return NULL; + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "'%s' should be txid, not '%.*s'", + name, json_tok_full_len(tok), + json_tok_full(buffer, tok)); +} diff --git a/common/json_tok.h b/common/json_tok.h index 3a428bc2e4f4..4e8a7ceac27b 100644 --- a/common/json_tok.h +++ b/common/json_tok.h @@ -10,6 +10,7 @@ struct amount_msat; struct amount_sat; +struct bitcoin_txid; struct channel_id; struct command; struct command_result; @@ -131,4 +132,30 @@ struct command_result *param_secrets_array(struct command *cmd, const jsmntok_t *tok, struct secret **secrets); +struct command_result *param_feerate_val(struct command *cmd, + const char *name, const char *buffer, + const jsmntok_t *tok, + u32 **feerate_per_kw); + +struct command_result *param_txid(struct command *cmd, + const char *name, + const char *buffer, + const jsmntok_t *tok, + struct bitcoin_txid **txid); + +enum address_parse_result { + /* Not recognized as an onchain address */ + ADDRESS_PARSE_UNRECOGNIZED, + /* Recognized as an onchain address, but targets wrong network */ + ADDRESS_PARSE_WRONG_NETWORK, + /* Recognized and succeeds */ + ADDRESS_PARSE_SUCCESS, +}; +/* Return result of address parsing and fills in *scriptpubkey + * allocated off ctx if ADDRESS_PARSE_SUCCESS + */ +enum address_parse_result json_to_address_scriptpubkey(const tal_t *ctx, + const struct chainparams *chainparams, + const char *buffer, + const jsmntok_t *tok, const u8 **scriptpubkey); #endif /* LIGHTNING_COMMON_JSON_TOK_H */ diff --git a/common/test/run-bigsize.c b/common/test/run-bigsize.c index 33b3640d2650..64c0f1eaeef7 100644 --- a/common/test/run-bigsize.c +++ b/common/test/run-bigsize.c @@ -27,14 +27,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire */ const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) { fprintf(stderr, "fromwire called!\n"); abort(); } diff --git a/common/test/run-cryptomsg.c b/common/test/run-cryptomsg.c index 9278076e56a5..0694d7b48fb7 100644 --- a/common/test/run-cryptomsg.c +++ b/common/test/run-cryptomsg.c @@ -22,14 +22,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire */ const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) { fprintf(stderr, "fromwire called!\n"); abort(); } diff --git a/common/test/run-derive_basepoints.c b/common/test/run-derive_basepoints.c index 733c284142e5..8279c832c2f7 100644 --- a/common/test/run-derive_basepoints.c +++ b/common/test/run-derive_basepoints.c @@ -23,14 +23,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire */ const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) { fprintf(stderr, "fromwire called!\n"); abort(); } diff --git a/common/test/run-features.c b/common/test/run-features.c index ef0f3f28cb5a..42fb4d72c48a 100644 --- a/common/test/run-features.c +++ b/common/test/run-features.c @@ -22,14 +22,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire */ const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) { fprintf(stderr, "fromwire called!\n"); abort(); } diff --git a/common/test/run-gossip_rcvd_filter.c b/common/test/run-gossip_rcvd_filter.c index 531ea29a0f27..c0fc19a5cc35 100644 --- a/common/test/run-gossip_rcvd_filter.c +++ b/common/test/run-gossip_rcvd_filter.c @@ -19,14 +19,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire_amount_sat */ struct amount_sat fromwire_amount_sat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_amount_sat called!\n"); abort(); } diff --git a/common/test/run-ip_port_parsing.c b/common/test/run-ip_port_parsing.c index 5439ddca1beb..e04b18705946 100644 --- a/common/test/run-ip_port_parsing.c +++ b/common/test/run-ip_port_parsing.c @@ -21,14 +21,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire */ const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) { fprintf(stderr, "fromwire called!\n"); abort(); } diff --git a/common/test/run-json_remove.c b/common/test/run-json_remove.c index 4c318216aa2f..1f2fd1a06c7e 100644 --- a/common/test/run-json_remove.c +++ b/common/test/run-json_remove.c @@ -19,14 +19,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire */ const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) { fprintf(stderr, "fromwire called!\n"); abort(); } diff --git a/common/test/run-key_derive.c b/common/test/run-key_derive.c index 76a7e3068181..039e320d08aa 100644 --- a/common/test/run-key_derive.c +++ b/common/test/run-key_derive.c @@ -24,14 +24,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire */ const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) { fprintf(stderr, "fromwire called!\n"); abort(); } diff --git a/common/test/run-lock.c b/common/test/run-lock.c index d29f323e36b3..268130d19031 100644 --- a/common/test/run-lock.c +++ b/common/test/run-lock.c @@ -23,14 +23,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire */ const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) { fprintf(stderr, "fromwire called!\n"); abort(); } diff --git a/common/test/run-param.c b/common/test/run-param.c index 03fe21cfb79d..b59ea83a374c 100644 --- a/common/test/run-param.c +++ b/common/test/run-param.c @@ -50,6 +50,19 @@ bool json_to_node_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, bool json_to_pubkey(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, struct pubkey *pubkey UNNEEDED) { fprintf(stderr, "json_to_pubkey called!\n"); abort(); } +/* Generated stub for json_to_txid */ +bool json_to_txid(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, + struct bitcoin_txid *txid UNNEEDED) +{ fprintf(stderr, "json_to_txid called!\n"); abort(); } +/* Generated stub for segwit_addr_decode */ +int segwit_addr_decode( + int* ver UNNEEDED, + uint8_t* prog UNNEEDED, + size_t* prog_len UNNEEDED, + const char* hrp UNNEEDED, + const char* addr +) +{ fprintf(stderr, "segwit_addr_decode called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ /* We do this lightningd-style: */ diff --git a/common/test/run-softref.c b/common/test/run-softref.c index d9f7c381ee71..caa2a85140fa 100644 --- a/common/test/run-softref.c +++ b/common/test/run-softref.c @@ -20,14 +20,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire */ const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) { fprintf(stderr, "fromwire called!\n"); abort(); } diff --git a/common/test/run-sphinx.c b/common/test/run-sphinx.c index a31e55a31f12..84a355603eaa 100644 --- a/common/test/run-sphinx.c +++ b/common/test/run-sphinx.c @@ -36,14 +36,17 @@ void amount_msat_from_u64(struct amount_msat *msat UNNEEDED, u64 millisatoshis U /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for bigsize_put */ size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN] UNNEEDED, bigsize_t v UNNEEDED) { fprintf(stderr, "bigsize_put called!\n"); abort(); } diff --git a/connectd/test/run-initiator-success.c b/connectd/test/run-initiator-success.c index 953a65b193a7..904846c8c0e9 100644 --- a/connectd/test/run-initiator-success.c +++ b/connectd/test/run-initiator-success.c @@ -26,14 +26,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire */ const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) { fprintf(stderr, "fromwire called!\n"); abort(); } diff --git a/connectd/test/run-responder-success.c b/connectd/test/run-responder-success.c index 29fdab58aa17..34cf0c69230c 100644 --- a/connectd/test/run-responder-success.c +++ b/connectd/test/run-responder-success.c @@ -26,14 +26,17 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) /* Generated stub for amount_sat_eq */ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_eq called!\n"); abort(); } -/* Generated stub for amount_sat_less */ -bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) -{ fprintf(stderr, "amount_sat_less called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } /* Generated stub for amount_sat_sub */ bool amount_sat_sub(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } /* Generated stub for fromwire */ const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) { fprintf(stderr, "fromwire called!\n"); abort(); } diff --git a/doc/lightning-listfunds.7 b/doc/lightning-listfunds.7 index 6a1629a65647..21d8d0bc8603 100644 --- a/doc/lightning-listfunds.7 +++ b/doc/lightning-listfunds.7 @@ -33,6 +33,8 @@ appended) .IP \[bu] \fIaddress\fR .IP \[bu] +\fIscriptpubkey\fR (the ScriptPubkey of the output, in hex) +.IP \[bu] \fIstatus\fR (whether \fIunconfirmed\fR, \fIconfirmed\fR, or \fIspent\fR) .IP \[bu] \fIreserved\fR (whether this is UTXO is currently reserved for an in-flight tx) diff --git a/doc/lightning-listfunds.7.md b/doc/lightning-listfunds.7.md index c475d1b42363..f17985e0df09 100644 --- a/doc/lightning-listfunds.7.md +++ b/doc/lightning-listfunds.7.md @@ -27,6 +27,7 @@ Each entry in *outputs* will include: - *amount\_msat* (the same as *value*, but in millisatoshi with *msat* appended) - *address* +- *scriptpubkey* (the ScriptPubkey of the output, in hex) - *status* (whether *unconfirmed*, *confirmed*, or *spent*) - *reserved* (whether this is UTXO is currently reserved for an in-flight tx) diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index fa32bc410ec7..4cc46486e318 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -466,32 +466,6 @@ u32 penalty_feerate(struct chain_topology *topo) return try_get_feerate(topo, FEERATE_PENALTY); } -u32 feerate_from_style(u32 feerate, enum feerate_style style) -{ - switch (style) { - case FEERATE_PER_KSIPA: - return feerate; - case FEERATE_PER_KBYTE: - /* Everyone uses satoshi per kbyte, but we use satoshi per ksipa - * (don't round down to zero though)! */ - return (feerate + 3) / 4; - } - abort(); -} - -u32 feerate_to_style(u32 feerate_perkw, enum feerate_style style) -{ - switch (style) { - case FEERATE_PER_KSIPA: - return feerate_perkw; - case FEERATE_PER_KBYTE: - if ((u64)feerate_perkw * 4 > UINT_MAX) - return UINT_MAX; - return feerate_perkw * 4; - } - abort(); -} - static struct command_result *json_feerates(struct command *cmd, const char *buffer, const jsmntok_t *obj UNNEEDED, @@ -516,7 +490,7 @@ static struct command_result *json_feerates(struct command *cmd, } response = json_stream_success(cmd); - json_object_start(response, json_feerate_style_name(*style)); + json_object_start(response, feerate_style_name(*style)); for (size_t i = 0; i < ARRAY_SIZE(feerates); i++) { if (!feerates[i] || i == FEERATE_MIN || i == FEERATE_MAX) continue; diff --git a/lightningd/chaintopology.h b/lightningd/chaintopology.h index 456296a09500..4f948b15fd36 100644 --- a/lightningd/chaintopology.h +++ b/lightningd/chaintopology.h @@ -159,10 +159,6 @@ u32 delayed_to_us_feerate(struct chain_topology *topo); u32 htlc_resolution_feerate(struct chain_topology *topo); u32 penalty_feerate(struct chain_topology *topo); -/* We always use feerate-per-ksipa, ie. perkw */ -u32 feerate_from_style(u32 feerate, enum feerate_style style); -u32 feerate_to_style(u32 feerate_perkw, enum feerate_style style); - const char *feerate_name(enum feerate feerate); /* Set feerate_per_kw to this estimate & return NULL, or fail cmd */ diff --git a/lightningd/json.c b/lightningd/json.c index d074c0294f15..fbbb18041d7d 100644 --- a/lightningd/json.c +++ b/lightningd/json.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -38,21 +37,6 @@ struct command_result *param_pubkey(struct command *cmd, const char *name, json_tok_full(buffer, tok)); } -struct command_result *param_txid(struct command *cmd, - const char *name, - const char *buffer, - const jsmntok_t *tok, - struct bitcoin_txid **txid) -{ - *txid = tal(cmd, struct bitcoin_txid); - if (json_to_txid(buffer, tok, *txid)) - return NULL; - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "'%s' should be txid, not '%.*s'", - name, json_tok_full_len(tok), - json_tok_full(buffer, tok)); -} - struct command_result *param_short_channel_id(struct command *cmd, const char *name, const char *buffer, @@ -69,17 +53,6 @@ struct command_result *param_short_channel_id(struct command *cmd, json_tok_full(buffer, tok)); } -const char *json_feerate_style_name(enum feerate_style style) -{ - switch (style) { - case FEERATE_PER_KBYTE: - return "perkb"; - case FEERATE_PER_KSIPA: - return "perkw"; - } - abort(); -} - struct command_result *param_feerate_style(struct command *cmd, const char *name, const char *buffer, @@ -88,11 +61,11 @@ struct command_result *param_feerate_style(struct command *cmd, { *style = tal(cmd, enum feerate_style); if (json_tok_streq(buffer, tok, - json_feerate_style_name(FEERATE_PER_KSIPA))) { + feerate_style_name(FEERATE_PER_KSIPA))) { **style = FEERATE_PER_KSIPA; return NULL; } else if (json_tok_streq(buffer, tok, - json_feerate_style_name(FEERATE_PER_KBYTE))) { + feerate_style_name(FEERATE_PER_KBYTE))) { **style = FEERATE_PER_KBYTE; return NULL; } @@ -100,8 +73,8 @@ struct command_result *param_feerate_style(struct command *cmd, return command_fail(cmd, JSONRPC2_INVALID_PARAMS, "'%s' should be '%s' or '%s', not '%.*s'", name, - json_feerate_style_name(FEERATE_PER_KSIPA), - json_feerate_style_name(FEERATE_PER_KBYTE), + feerate_style_name(FEERATE_PER_KSIPA), + feerate_style_name(FEERATE_PER_KBYTE), json_tok_full_len(tok), json_tok_full(buffer, tok)); } @@ -109,10 +82,6 @@ struct command_result *param_feerate(struct command *cmd, const char *name, const char *buffer, const jsmntok_t *tok, u32 **feerate) { - jsmntok_t base = *tok, suffix = *tok; - enum feerate_style style; - unsigned int num; - for (size_t i = 0; i < NUM_FEERATES; i++) { if (json_tok_streq(buffer, tok, feerate_name(i))) return param_feerate_estimate(cmd, feerate, i); @@ -127,42 +96,8 @@ struct command_result *param_feerate(struct command *cmd, const char *name, else if (json_tok_streq(buffer, tok, "urgent")) return param_feerate_estimate(cmd, feerate, FEERATE_UNILATERAL_CLOSE); - /* We have to split the number and suffix. */ - suffix.start = suffix.end; - while (suffix.start > base.start && !isdigit(buffer[suffix.start-1])) { - suffix.start--; - base.end--; - } - - if (!json_to_number(buffer, &base, &num)) { - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "'%s' prefix should be an integer, not '%.*s'", - name, base.end - base.start, - buffer + base.start); - } - - if (json_tok_streq(buffer, &suffix, "") - || json_tok_streq(buffer, &suffix, - json_feerate_style_name(FEERATE_PER_KBYTE))) { - style = FEERATE_PER_KBYTE; - } else if (json_tok_streq(buffer, &suffix, - json_feerate_style_name(FEERATE_PER_KSIPA))) { - style = FEERATE_PER_KSIPA; - } else { - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "'%s' suffix should be '%s' or '%s', not '%.*s'", - name, - json_feerate_style_name(FEERATE_PER_KSIPA), - json_feerate_style_name(FEERATE_PER_KBYTE), - suffix.end - suffix.start, - buffer + suffix.start); - } - - *feerate = tal(cmd, u32); - **feerate = feerate_from_style(num, style); - if (**feerate < FEERATE_FLOOR) - **feerate = FEERATE_FLOOR; - return NULL; + /* It's a number... */ + return param_feerate_val(cmd, name, buffer, tok, feerate); } bool @@ -173,113 +108,6 @@ json_tok_channel_id(const char *buffer, const jsmntok_t *tok, cid, sizeof(*cid)); } -/** - * segwit_addr_net_decode - Try to decode a Bech32 address and detect - * testnet/mainnet/regtest/signet - * - * This processes the address and returns a string if it is a Bech32 - * address specified by BIP173. The string is set whether it is - * testnet ("tb"), mainnet ("bc"), regtest ("bcrt"), or signet ("sb") - * It does not check, witness version and program size restrictions. - * - * Out: witness_version: Pointer to an int that will be updated to contain - * the witness program version (between 0 and 16 inclusive). - * witness_program: Pointer to a buffer of size 40 that will be updated - * to contain the witness program bytes. - * witness_program_len: Pointer to a size_t that will be updated to - * contain the length of bytes in witness_program. - * In: addrz: Pointer to the null-terminated address. - * Returns string containing the human readable segment of bech32 address - */ -static const char *segwit_addr_net_decode(int *witness_version, - uint8_t *witness_program, - size_t *witness_program_len, - const char *addrz, - const struct chainparams *chainparams) -{ - if (segwit_addr_decode(witness_version, witness_program, - witness_program_len, chainparams->bip173_name, - addrz)) - return chainparams->bip173_name; - else - return NULL; -} - -enum address_parse_result -json_to_address_scriptpubkey(const tal_t *ctx, - const struct chainparams *chainparams, - const char *buffer, - const jsmntok_t *tok, const u8 **scriptpubkey) -{ - struct bitcoin_address destination; - int witness_version; - /* segwit_addr_net_decode requires a buffer of size 40, and will - * not write to the buffer if the address is too long, so a buffer - * of fixed size 40 will not overflow. */ - uint8_t witness_program[40]; - size_t witness_program_len; - - char *addrz; - const char *bip173; - - bool parsed; - bool right_network; - u8 addr_version; - - parsed = - ripemd160_from_base58(&addr_version, &destination.addr, - buffer + tok->start, tok->end - tok->start); - - if (parsed) { - if (addr_version == chainparams->p2pkh_version) { - *scriptpubkey = scriptpubkey_p2pkh(ctx, &destination); - return ADDRESS_PARSE_SUCCESS; - } else if (addr_version == chainparams->p2sh_version) { - *scriptpubkey = - scriptpubkey_p2sh_hash(ctx, &destination.addr); - return ADDRESS_PARSE_SUCCESS; - } else { - return ADDRESS_PARSE_WRONG_NETWORK; - } - /* Insert other parsers that accept pointer+len here. */ - } - - /* Generate null-terminated address. */ - addrz = tal_dup_arr(ctx, char, buffer + tok->start, tok->end - tok->start, 1); - addrz[tok->end - tok->start] = '\0'; - - bip173 = segwit_addr_net_decode(&witness_version, witness_program, - &witness_program_len, addrz, chainparams); - - if (bip173) { - bool witness_ok = false; - if (witness_version == 0 && (witness_program_len == 20 || - witness_program_len == 32)) { - witness_ok = true; - } - /* Insert other witness versions here. */ - - if (witness_ok) { - *scriptpubkey = scriptpubkey_witness_raw(ctx, witness_version, - witness_program, witness_program_len); - parsed = true; - right_network = streq(bip173, chainparams->bip173_name); - } - } - /* Insert other parsers that accept null-terminated string here. */ - - tal_free(addrz); - - if (parsed) { - if (right_network) - return ADDRESS_PARSE_SUCCESS; - else - return ADDRESS_PARSE_WRONG_NETWORK; - } - - return ADDRESS_PARSE_UNRECOGNIZED; -} - struct command_result *param_bitcoin_address(struct command *cmd, const char *name, const char *buffer, diff --git a/lightningd/json.h b/lightningd/json.h index 5055c3c06e40..28a797ee3f52 100644 --- a/lightningd/json.h +++ b/lightningd/json.h @@ -5,6 +5,7 @@ #ifndef LIGHTNING_LIGHTNINGD_JSON_H #define LIGHTNING_LIGHTNINGD_JSON_H #include "config.h" +#include #include #include #include @@ -28,21 +29,12 @@ struct command_result *param_pubkey(struct command *cmd, const char *name, const char *buffer, const jsmntok_t *tok, struct pubkey **pubkey); -struct command_result *param_txid(struct command *cmd, const char *name, - const char *buffer, const jsmntok_t *tok, - struct bitcoin_txid **txid); - struct command_result *param_short_channel_id(struct command *cmd, const char *name, const char *buffer, const jsmntok_t *tok, struct short_channel_id **scid); -enum feerate_style { - FEERATE_PER_KSIPA, - FEERATE_PER_KBYTE -}; - /* Extract a feerate style. */ struct command_result *param_feerate_style(struct command *cmd, const char *name, @@ -60,22 +52,6 @@ struct command_result *param_feerate(struct command *cmd, const char *name, bool json_tok_channel_id(const char *buffer, const jsmntok_t *tok, struct channel_id *cid); -enum address_parse_result { - /* Not recognized as an onchain address */ - ADDRESS_PARSE_UNRECOGNIZED, - /* Recognized as an onchain address, but targets wrong network */ - ADDRESS_PARSE_WRONG_NETWORK, - /* Recognized and succeeds */ - ADDRESS_PARSE_SUCCESS, -}; -/* Return result of address parsing and fills in *scriptpubkey - * allocated off ctx if ADDRESS_PARSE_SUCCESS - */ -enum address_parse_result json_to_address_scriptpubkey(const tal_t *ctx, - const struct chainparams *chainparams, - const char *buffer, - const jsmntok_t *tok, const u8 **scriptpubkey); - struct command_result *param_bitcoin_address(struct command *cmd, const char *name, const char *buffer, diff --git a/lightningd/test/run-jsonrpc.c b/lightningd/test/run-jsonrpc.c index 243f606de4ae..cdfea9955aa5 100644 --- a/lightningd/test/run-jsonrpc.c +++ b/lightningd/test/run-jsonrpc.c @@ -12,9 +12,6 @@ void db_commit_transaction(struct db *db UNNEEDED) /* Generated stub for fatal */ void fatal(const char *fmt UNNEEDED, ...) { fprintf(stderr, "fatal called!\n"); abort(); } -/* Generated stub for feerate_from_style */ -u32 feerate_from_style(u32 feerate UNNEEDED, enum feerate_style style UNNEEDED) -{ fprintf(stderr, "feerate_from_style called!\n"); abort(); } /* Generated stub for feerate_name */ const char *feerate_name(enum feerate feerate UNNEEDED) { fprintf(stderr, "feerate_name called!\n"); abort(); } @@ -32,6 +29,12 @@ void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct n void json_add_sha256(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED, const struct sha256 *hash UNNEEDED) { fprintf(stderr, "json_add_sha256 called!\n"); abort(); } +/* Generated stub for json_to_address_scriptpubkey */ +enum address_parse_result json_to_address_scriptpubkey(const tal_t *ctx UNNEEDED, + const struct chainparams *chainparams UNNEEDED, + const char *buffer UNNEEDED, + const jsmntok_t *tok UNNEEDED, const u8 **scriptpubkey UNNEEDED) +{ fprintf(stderr, "json_to_address_scriptpubkey called!\n"); abort(); } /* Generated stub for json_to_pubkey */ bool json_to_pubkey(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, struct pubkey *pubkey UNNEEDED) @@ -40,10 +43,6 @@ bool json_to_pubkey(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, bool json_to_short_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, struct short_channel_id *scid UNNEEDED) { fprintf(stderr, "json_to_short_channel_id called!\n"); abort(); } -/* Generated stub for json_to_txid */ -bool json_to_txid(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, - struct bitcoin_txid *txid UNNEEDED) -{ fprintf(stderr, "json_to_txid called!\n"); abort(); } /* Generated stub for log_ */ void log_(struct log *log UNNEEDED, enum log_level level UNNEEDED, const struct node_id *node_id UNNEEDED, @@ -80,6 +79,12 @@ struct command_result *param_feerate_estimate(struct command *cmd UNNEEDED, u32 **feerate_per_kw UNNEEDED, enum feerate feerate UNNEEDED) { fprintf(stderr, "param_feerate_estimate called!\n"); abort(); } +/* Generated stub for param_feerate_val */ +struct command_result *param_feerate_val(struct command *cmd UNNEEDED, + const char *name UNNEEDED, const char *buffer UNNEEDED, + const jsmntok_t *tok UNNEEDED, + u32 **feerate_per_kw UNNEEDED) +{ fprintf(stderr, "param_feerate_val called!\n"); abort(); } /* Generated stub for param_ignore */ struct command_result *param_ignore(struct command *cmd UNNEEDED, const char *name UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, diff --git a/plugins/Makefile b/plugins/Makefile index fc9cfa032b0b..971f589e9d4a 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -37,6 +37,7 @@ PLUGINS := \ PLUGIN_COMMON_OBJS := \ bitcoin/base58.o \ + bitcoin/feerate.o \ bitcoin/privkey.o \ bitcoin/psbt.o \ bitcoin/pubkey.o \ diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 469de169ea36..c3ab72806905 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -702,7 +702,7 @@ u8 *towire_incorrect_cltv_expiry(const tal_t *ctx UNNEEDED, u32 cltv_expiry UNNE u8 *towire_incorrect_or_unknown_payment_details(const tal_t *ctx UNNEEDED, struct amount_msat htlc_msat UNNEEDED, u32 height UNNEEDED) { fprintf(stderr, "towire_incorrect_or_unknown_payment_details called!\n"); abort(); } /* Generated stub for towire_invalid_onion_payload */ -u8 *towire_invalid_onion_payload(const tal_t *ctx UNNEEDED, varint type UNNEEDED, u16 offset UNNEEDED) +u8 *towire_invalid_onion_payload(const tal_t *ctx UNNEEDED, bigsize type UNNEEDED, u16 offset UNNEEDED) { fprintf(stderr, "towire_invalid_onion_payload called!\n"); abort(); } /* Generated stub for towire_invalid_realm */ u8 *towire_invalid_realm(const tal_t *ctx UNNEEDED) diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index bf0ecc88074e..afbad92a9510 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -856,6 +856,7 @@ static void json_add_utxo(struct json_stream *response, "value", "amount_msat"); if (utxo->scriptPubkey != NULL) { + json_add_hex_talarr(response, "scriptpubkey", utxo->scriptPubkey); out = encode_scriptpubkey_to_addr( tmpctx, chainparams, utxo->scriptPubkey);