|
4 | 4 | #include <ccan/array_size/array_size.h>
|
5 | 5 | #include <ccan/cast/cast.h>
|
6 | 6 | #include <common/addr.h>
|
| 7 | +#include <common/base64.h> |
7 | 8 | #include <common/bech32.h>
|
8 | 9 | #include <common/configdir.h>
|
9 | 10 | #include <common/json_command.h>
|
@@ -1066,3 +1067,113 @@ static const struct json_command sendpsbt_command = {
|
1066 | 1067 | };
|
1067 | 1068 |
|
1068 | 1069 | AUTODATA(json_command, &sendpsbt_command);
|
| 1070 | + |
| 1071 | +static struct command_result * |
| 1072 | +json_signmessagewithkey(struct command *cmd, const char *buffer, |
| 1073 | + const jsmntok_t *obj UNNEEDED, const jsmntok_t *params) |
| 1074 | +{ |
| 1075 | + /* decoding the address */ |
| 1076 | + const u8 *scriptpubkey; |
| 1077 | + const char *message; |
| 1078 | + |
| 1079 | + /* from wallet BIP32 */ |
| 1080 | + struct pubkey pubkey; |
| 1081 | + |
| 1082 | + if (!param( |
| 1083 | + cmd, buffer, params, |
| 1084 | + p_req("message", param_string, &message), |
| 1085 | + p_req("address", param_bitcoin_address, &scriptpubkey), |
| 1086 | + NULL)) |
| 1087 | + return command_param_failed(); |
| 1088 | + |
| 1089 | + const size_t script_len = tal_bytelen(scriptpubkey); |
| 1090 | + |
| 1091 | + /* FIXME: we already had the address from the input */ |
| 1092 | + char *addr; |
| 1093 | + addr = encode_scriptpubkey_to_addr(tmpctx, chainparams, scriptpubkey); |
| 1094 | + |
| 1095 | + if (!is_p2wpkh(scriptpubkey, script_len, NULL)) { |
| 1096 | + /* FIXME add support for BIP 322 */ |
| 1097 | + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, |
| 1098 | + "Address is not p2wpkh and " |
| 1099 | + "it is not supported for signing"); |
| 1100 | + } |
| 1101 | + |
| 1102 | + u32 keyidx = UINT32_MAX; |
| 1103 | + |
| 1104 | + /* loop over all generated keys, find a matching key */ |
| 1105 | + /* FIXME: alternatively, can we use the our_addresses hash table? |
| 1106 | + *struct script_with_len *key; |
| 1107 | + *struct wallet_address *addr = |
| 1108 | + * wallet_address_htable_get(cmd->ld->wallet->our_addresses, key); |
| 1109 | + */ |
| 1110 | + struct issued_address_type *listaddrtypes = |
| 1111 | + wallet_list_addresses(tmpctx, cmd->ld->wallet, 1, NULL); |
| 1112 | + for (size_t i = 0; i < tal_count(listaddrtypes); i++) { |
| 1113 | + bip32_pubkey(cmd->ld, &pubkey, listaddrtypes[i].keyidx); |
| 1114 | + char *out_p2wpkh = ""; |
| 1115 | + if (listaddrtypes[i].addrtype == ADDR_BECH32 || |
| 1116 | + listaddrtypes[i].addrtype == ADDR_ALL) { |
| 1117 | + u8 *redeemscript_p2wpkh; |
| 1118 | + out_p2wpkh = encode_pubkey_to_addr( |
| 1119 | + cmd, &pubkey, ADDR_BECH32, &redeemscript_p2wpkh); |
| 1120 | + if (!out_p2wpkh) { |
| 1121 | + abort(); |
| 1122 | + } |
| 1123 | + } |
| 1124 | + if (streq(addr, out_p2wpkh)) { |
| 1125 | + keyidx = listaddrtypes[i].keyidx; |
| 1126 | + break; |
| 1127 | + } |
| 1128 | + } |
| 1129 | + |
| 1130 | + if (keyidx == UINT32_MAX) { |
| 1131 | + return command_fail( |
| 1132 | + cmd, JSONRPC2_INVALID_PARAMS, |
| 1133 | + "Address is not found in the wallet's database"); |
| 1134 | + } |
| 1135 | + |
| 1136 | + /* wire to hsmd a sign request */ |
| 1137 | + u8 *msg = towire_hsmd_sign_message_with_key( |
| 1138 | + cmd, tal_dup_arr(tmpctx, u8, (u8 *)message, strlen(message), 0), |
| 1139 | + keyidx); |
| 1140 | + if (!wire_sync_write(cmd->ld->hsm_fd, take(msg))) { |
| 1141 | + fatal("Could not write sign_with_key to HSM: %s", |
| 1142 | + strerror(errno)); |
| 1143 | + } |
| 1144 | + |
| 1145 | + /* read form hsmd a sign reply */ |
| 1146 | + msg = wire_sync_read(cmd, cmd->ld->hsm_fd); |
| 1147 | + |
| 1148 | + int recid; |
| 1149 | + u8 sig[65]; |
| 1150 | + secp256k1_ecdsa_recoverable_signature rsig; |
| 1151 | + |
| 1152 | + if (!fromwire_hsmd_sign_message_with_key_reply(msg, &rsig)) { |
| 1153 | + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, |
| 1154 | + "HSM gave bad sign_with_key_reply %s", |
| 1155 | + tal_hex(tmpctx, msg)); |
| 1156 | + } |
| 1157 | + |
| 1158 | + secp256k1_ecdsa_recoverable_signature_serialize_compact( |
| 1159 | + secp256k1_ctx, sig + 1, &recid, &rsig); |
| 1160 | + /* this is the header value for P2WPKH specified in BIP137 */ |
| 1161 | + sig[0] = recid + 39; |
| 1162 | + |
| 1163 | + /* FIXME: Given the fact that we plan to extend support for BIP322 |
| 1164 | + * signature in the future making a pubkey output here makes less sense. */ |
| 1165 | + struct json_stream *response; |
| 1166 | + response = json_stream_success(cmd); |
| 1167 | + json_add_string(response, "address", addr); |
| 1168 | + json_add_pubkey(response, "pubkey", &pubkey); |
| 1169 | + json_add_hex(response, "signature", sig, sizeof(sig)); |
| 1170 | + json_add_string(response, "base64", |
| 1171 | + b64_encode(tmpctx, sig, sizeof(sig))); |
| 1172 | + return command_success(cmd, response); |
| 1173 | +} |
| 1174 | + |
| 1175 | +static const struct json_command signmessagewithkey_command = { |
| 1176 | + "signmessagewithkey", |
| 1177 | + json_signmessagewithkey |
| 1178 | +}; |
| 1179 | +AUTODATA(json_command, &signmessagewithkey_command); |
0 commit comments