diff --git a/bitcoin/psbt.c b/bitcoin/psbt.c index 81c973977..21766e91f 100644 --- a/bitcoin/psbt.c +++ b/bitcoin/psbt.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -420,6 +421,105 @@ struct amount_sat psbt_output_get_amount(struct wally_psbt *psbt, assert(amount_asset_is_main(&asset)); return amount_asset_to_sat(&asset); } + +static void add(u8 **key, const void *mem, size_t len) +{ + size_t oldlen = tal_count(*key); + tal_resize(key, oldlen + len); + memcpy(*key + oldlen, memcheck(mem, len), len); +} + +static void add_type(u8 **key, const u8 num) +{ + add(key, &num, 1); +} + +static void add_varint(u8 **key, size_t val) +{ + u8 vt[VARINT_MAX_LEN]; + size_t vtlen; + vtlen = varint_put(vt, val); + add(key, vt, vtlen); +} + +#define LIGHTNING_PROPRIETARY_PREFIX "lightning" + +u8 *psbt_make_key(const tal_t *ctx, u8 key_subtype, const u8 *key_data) +{ + /** + * BIP174: + * Type: Proprietary Use Type PSBT_GLOBAL_PROPRIETARY = 0xFC + ** Key: Variable length identifier prefix, followed + * by a subtype, followed by the key data itself. + *** {0xFC}||{subtype}|{key data} + ** Value: Any value data as defined by the proprietary type user. + *** + */ + u8 *key = tal_arr(ctx, u8, 0); + add_type(&key, PSBT_PROPRIETARY_TYPE); + add_varint(&key, strlen(LIGHTNING_PROPRIETARY_PREFIX)); + add(&key, LIGHTNING_PROPRIETARY_PREFIX, + strlen(LIGHTNING_PROPRIETARY_PREFIX)); + add_type(&key, key_subtype); + if (key_data) + add(&key, key_data, tal_bytelen(key_data)); + return key; +} + +void psbt_input_add_unknown(struct wally_psbt_input *in, + const u8 *key, + const void *value, + size_t value_len) +{ + if (wally_map_add(&in->unknowns, + cast_const(unsigned char *, key), tal_bytelen(key), + (unsigned char *) memcheck(value, value_len), value_len) + != WALLY_OK) + abort(); +} + +void *psbt_get_unknown(const struct wally_map *map, + const u8 *key, + size_t *val_len) +{ + size_t index; + + if (wally_map_find(map, key, tal_bytelen(key), &index) != WALLY_OK) + return NULL; + + /* Zero: item not found. */ + if (index == 0) + return NULL; + + /* ++: item is at this index minus 1 */ + *val_len = map->items[index - 1].value_len; + return map->items[index - 1].value; +} + +void *psbt_get_lightning(const struct wally_map *map, + const u8 proprietary_type, + size_t *val_len) +{ + void *res; + u8 *key = psbt_make_key(NULL, proprietary_type, NULL); + res = psbt_get_unknown(map, key, val_len); + tal_free(key); + return res; +} + + +void psbt_output_add_unknown(struct wally_psbt_output *out, + const u8 *key, + const void *value, + size_t value_len) +{ + if (wally_map_add(&out->unknowns, + cast_const(unsigned char *, key), tal_bytelen(key), + (unsigned char *) memcheck(value, value_len), value_len) + != WALLY_OK) + abort(); +} + struct wally_tx *psbt_finalize(struct wally_psbt *psbt, bool finalize_in_place) { struct wally_psbt *tmppsbt; @@ -518,6 +618,8 @@ char *psbt_to_b64(const tal_t *ctx, const struct wally_psbt *psbt) wally_free_string(serialized_psbt); return ret_val; } + +/* Do not remove this line, it is magic */ REGISTER_TYPE_TO_STRING(wally_psbt, psbt_to_b64); const u8 *psbt_get_bytes(const tal_t *ctx, const struct wally_psbt *psbt, diff --git a/bitcoin/psbt.h b/bitcoin/psbt.h index 40e572296..26a3b29eb 100644 --- a/bitcoin/psbt.h +++ b/bitcoin/psbt.h @@ -10,6 +10,7 @@ struct wally_psbt_input; struct wally_tx; struct wally_tx_input; struct wally_tx_output; +struct wally_map; struct amount_asset; struct amount_sat; struct bitcoin_signature; @@ -59,6 +60,16 @@ void psbt_txid(const struct wally_psbt *psbt, struct bitcoin_txid *txid, struct wally_tx *psbt_finalize(struct wally_psbt *psbt, bool finalize_in_place); +/* psbt_make_key - Create a new, proprietary c-lightning key + * + * @ctx - allocation context + * @key_subtype - type for this key + * @key_data - any extra data to append to the key + * + * Returns a proprietary-prefixed key. + */ +u8 *psbt_make_key(const tal_t *ctx, u8 key_subtype, const u8 *key_data); + struct wally_psbt_input *psbt_add_input(struct wally_psbt *psbt, struct wally_tx_input *input, size_t insert_at); @@ -112,6 +123,49 @@ void psbt_elements_input_init_witness(struct wally_psbt *psbt, size_t in, const u8 *nonce); bool psbt_input_set_redeemscript(struct wally_psbt *psbt, size_t in, const u8 *redeemscript); +/* psbt_input_add_unknown - Add the given Key-Value to the psbt's input keymap + * @in - psbt input to add key-value to + * @key - key for key-value pair + * @value - value to add + * @value_len - length of {@value} + */ +void psbt_input_add_unknown(struct wally_psbt_input *in, + const u8 *key, + const void *value, + size_t value_len); +/* psbt_get_unknown - Fetch the value from the given map at key + * + * @map - map of unknowns to search for key + * @key - key of key-value pair to return value for + * @value_len - (out) length of value (if found) + * + * Returns: value at @key, or NULL if not found */ +void *psbt_get_unknown(const struct wally_map *map, + const u8 *key, + size_t *val_len); + +/* psbt_get_lightning - Fetch a proprietary lightning value from the given map + * + * @map - map of unknowns to search for key + * @proprietary_type - type no. to look for + * @val_len - (out) length of value (if found) + * + * Returns: value of type {proprietary_type}, or NULL if not found */ +void *psbt_get_lightning(const struct wally_map *map, + const u8 proprietary_type, + size_t *val_len); + +/* psbt_output_add_unknown - Add the given Key-Value to the psbt's output keymap + * + * @out - psbt output to add key-value to + * @key - key for key-value pair + * @value - value to add + * @value_len - length of {@value} + */ +void psbt_output_add_unknown(struct wally_psbt_output *out, + const u8 *key, const void *value, + size_t value_len); + /* psbt_input_get_amount - Returns the value of this input * * @psbt - psbt