Skip to content

Commit e5e26b1

Browse files
committed
Port sign_message_by_id
1 parent 04a4a2a commit e5e26b1

File tree

7 files changed

+103
-75
lines changed

7 files changed

+103
-75
lines changed

chia/_tests/cmds/cmd_test_utils.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
SendTransactionMultiResponse,
4949
SignMessageByAddress,
5050
SignMessageByAddressResponse,
51+
SignMessageByID,
52+
SignMessageByIDResponse,
5153
WalletInfoResponse,
5254
)
5355
from chia.wallet.wallet_rpc_client import WalletRpcClient
@@ -167,12 +169,21 @@ async def sign_message_by_address(self, request: SignMessageByAddress) -> SignMe
167169
signing_mode = SigningMode.CHIP_0002.value
168170
return SignMessageByAddressResponse(pubkey, signature, signing_mode)
169171

170-
async def sign_message_by_id(self, id: str, message: str) -> tuple[str, str, str]:
171-
self.add_to_log("sign_message_by_id", (id, message))
172-
pubkey = bytes([4] * 48).hex()
173-
signature = bytes([7] * 576).hex()
172+
async def sign_message_by_id(self, request: SignMessageByID) -> SignMessageByIDResponse:
173+
self.add_to_log("sign_message_by_id", (request.id, request.message))
174+
pubkey = G1Element.from_bytes(
175+
bytes.fromhex(
176+
"a9e652cb551d5978a9ee4b7aa52a4e826078a54b08a3d903c38611cb8a804a9a29c926e4f8549314a079e04ecde10cc1"
177+
)
178+
)
179+
signature = G2Element.from_bytes(
180+
bytes.fromhex(
181+
"c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
182+
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
183+
)
184+
)
174185
signing_mode = SigningMode.CHIP_0002.value
175-
return pubkey, signature, signing_mode
186+
return SignMessageByIDResponse(pubkey, signature, bytes32.zeros, signing_mode)
176187

177188
async def cat_asset_id_to_name(self, asset_id: bytes32) -> Optional[tuple[Optional[uint32], str]]:
178189
"""

chia/_tests/cmds/wallet/test_did.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,9 @@ def test_did_sign_message(capsys: object, get_test_cli_clients: tuple[TestRpcCli
116116
# these are various things that should be in the output
117117
assert_list = [
118118
f"Message: {message.hex()}",
119-
f"Public Key: {bytes([4] * 48).hex()}",
120-
f"Signature: {bytes([7] * 576).hex()}",
119+
"Public Key: a9e652cb551d5978a9ee4b7aa52a4e826078a54b08a3d903c38611cb8a804a9a29c926e4f8549314a079e04ecde10cc1",
120+
"Signature: c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
121+
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
121122
f"Signing Mode: {SigningMode.CHIP_0002.value}",
122123
]
123124
run_cli_command_and_assert(capsys, root_dir, [*command_args, f"-i{did_id}"], assert_list)

chia/_tests/wallet/nft_wallet/test_nft_wallet.py

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from typing import Any, Callable
66

77
import pytest
8-
from chia_rs import AugSchemeMPL, G1Element, G2Element
8+
from chia_rs import AugSchemeMPL
99
from chia_rs.sized_bytes import bytes32
1010
from chia_rs.sized_ints import uint16, uint32, uint64
1111
from clvm_tools.binutils import disassemble
@@ -41,6 +41,7 @@
4141
NFTTransferBulk,
4242
NFTTransferNFT,
4343
NFTWalletWithDID,
44+
SignMessageByID,
4445
)
4546
from chia.wallet.wallet_rpc_api import MAX_NFT_CHUNK_SIZE
4647
from chia.wallet.wallet_state_manager import WalletStateManager
@@ -2757,51 +2758,55 @@ async def test_nft_sign_message(wallet_environments: WalletTestFramework) -> Non
27572758
assert not coin.pending_transaction
27582759
# Test general string
27592760
message = "Hello World"
2760-
pubkey, sig, _ = await env.rpc_client.sign_message_by_id(
2761-
id=encode_puzzle_hash(coin.launcher_id, AddressType.NFT.value), message=message
2761+
sign_by_id_res = await env.rpc_client.sign_message_by_id(
2762+
SignMessageByID(id=encode_puzzle_hash(coin.launcher_id, AddressType.NFT.value), message=message)
27622763
)
27632764
puzzle = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, message))
27642765
assert AugSchemeMPL.verify(
2765-
G1Element.from_bytes(bytes.fromhex(pubkey)),
2766+
sign_by_id_res.pubkey,
27662767
puzzle.get_tree_hash(),
2767-
G2Element.from_bytes(bytes.fromhex(sig)),
2768+
sign_by_id_res.signature,
27682769
)
27692770
# Test hex string
27702771
message = "0123456789ABCDEF"
2771-
pubkey, sig, _ = await env.rpc_client.sign_message_by_id(
2772-
id=encode_puzzle_hash(coin.launcher_id, AddressType.NFT.value), message=message, is_hex=True
2772+
sign_by_id_res = await env.rpc_client.sign_message_by_id(
2773+
SignMessageByID(id=encode_puzzle_hash(coin.launcher_id, AddressType.NFT.value), message=message, is_hex=True)
27732774
)
27742775
puzzle = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, bytes.fromhex(message)))
27752776
assert AugSchemeMPL.verify(
2776-
G1Element.from_bytes(bytes.fromhex(pubkey)),
2777+
sign_by_id_res.pubkey,
27772778
puzzle.get_tree_hash(),
2778-
G2Element.from_bytes(bytes.fromhex(sig)),
2779+
sign_by_id_res.signature,
27792780
)
27802781
# Test BLS sign string
27812782
message = "Hello World"
2782-
pubkey, sig, _ = await env.rpc_client.sign_message_by_id(
2783-
id=encode_puzzle_hash(coin.launcher_id, AddressType.NFT.value),
2784-
message=message,
2785-
is_hex=False,
2786-
safe_mode=False,
2783+
sign_by_id_res = await env.rpc_client.sign_message_by_id(
2784+
SignMessageByID(
2785+
id=encode_puzzle_hash(coin.launcher_id, AddressType.NFT.value),
2786+
message=message,
2787+
is_hex=False,
2788+
safe_mode=False,
2789+
)
27872790
)
27882791

27892792
assert AugSchemeMPL.verify(
2790-
G1Element.from_bytes(bytes.fromhex(pubkey)),
2791-
bytes(message, "utf-8"),
2792-
G2Element.from_bytes(bytes.fromhex(sig)),
2793+
sign_by_id_res.pubkey,
2794+
puzzle.get_tree_hash(),
2795+
sign_by_id_res.signature,
27932796
)
27942797
# Test BLS sign hex
27952798
message = "0123456789ABCDEF"
2796-
pubkey, sig, _ = await env.rpc_client.sign_message_by_id(
2797-
id=encode_puzzle_hash(coin.launcher_id, AddressType.NFT.value),
2798-
message=message,
2799-
is_hex=True,
2800-
safe_mode=False,
2799+
sign_by_id_res = await env.rpc_client.sign_message_by_id(
2800+
SignMessageByID(
2801+
id=encode_puzzle_hash(coin.launcher_id, AddressType.NFT.value),
2802+
message=message,
2803+
is_hex=True,
2804+
safe_mode=False,
2805+
)
28012806
)
28022807

28032808
assert AugSchemeMPL.verify(
2804-
G1Element.from_bytes(bytes.fromhex(pubkey)),
2805-
bytes.fromhex(message),
2806-
G2Element.from_bytes(bytes.fromhex(sig)),
2809+
sign_by_id_res.pubkey,
2810+
puzzle.get_tree_hash(),
2811+
sign_by_id_res.signature,
28072812
)

chia/cmds/wallet_funcs.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@
7474
RoyaltyAsset,
7575
SendTransactionResponse,
7676
SignMessageByAddress,
77+
SignMessageByAddressResponse,
78+
SignMessageByID,
79+
SignMessageByIDResponse,
7780
VCAddProofs,
7881
VCGet,
7982
VCGetList,
@@ -1627,30 +1630,27 @@ async def sign_message(
16271630
if address is None:
16281631
print("Address is required for XCH address type.")
16291632
return
1630-
response = await wallet_client.sign_message_by_address(
1631-
SignMessageByAddress(address.original_address, message)
1632-
)
1633-
pubkey = str(response.pubkey)
1634-
signature = str(response.signature)
1635-
signing_mode = response.signing_mode
1633+
response: Union[
1634+
SignMessageByAddressResponse, SignMessageByIDResponse
1635+
] = await wallet_client.sign_message_by_address(SignMessageByAddress(address.original_address, message))
16361636
elif addr_type == AddressType.DID:
16371637
if did_id is None:
16381638
print("DID id is required for DID address type.")
16391639
return
1640-
pubkey, signature, signing_mode = await wallet_client.sign_message_by_id(did_id.original_address, message)
1640+
response = await wallet_client.sign_message_by_id(SignMessageByID(did_id.original_address, message))
16411641
elif addr_type == AddressType.NFT:
16421642
if nft_id is None:
16431643
print("NFT id is required for NFT address type.")
16441644
return
1645-
pubkey, signature, signing_mode = await wallet_client.sign_message_by_id(nft_id.original_address, message)
1645+
response = await wallet_client.sign_message_by_id(SignMessageByID(nft_id.original_address, message))
16461646
else:
16471647
print("Invalid wallet type.")
16481648
return
16491649
print("")
16501650
print(f"Message: {message}")
1651-
print(f"Public Key: {pubkey}")
1652-
print(f"Signature: {signature}")
1653-
print(f"Signing Mode: {signing_mode}")
1651+
print(f"Public Key: {response.pubkey!s}")
1652+
print(f"Signature: {response.signature!s}")
1653+
print(f"Signing Mode: {response.signing_mode}")
16541654

16551655

16561656
async def spend_clawback(

chia/wallet/wallet_request_types.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,24 @@ class SignMessageByAddressResponse(Streamable):
393393
signing_mode: str
394394

395395

396+
@streamable
397+
@dataclass(frozen=True)
398+
class SignMessageByID(Streamable):
399+
id: str
400+
message: str
401+
is_hex: bool = False
402+
safe_mode: bool = True
403+
404+
405+
@streamable
406+
@dataclass(frozen=True)
407+
class SignMessageByIDResponse(Streamable):
408+
pubkey: G1Element
409+
signature: G2Element
410+
latest_coin_id: bytes32
411+
signing_mode: str
412+
413+
396414
@streamable
397415
@dataclass(frozen=True)
398416
class GetTransactionMemo(Streamable):

chia/wallet/wallet_rpc_api.py

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@
245245
SetWalletResyncOnStartup,
246246
SignMessageByAddress,
247247
SignMessageByAddressResponse,
248+
SignMessageByID,
249+
SignMessageByIDResponse,
248250
SplitCoins,
249251
SplitCoinsResponse,
250252
SubmitTransactions,
@@ -2047,28 +2049,23 @@ async def sign_message_by_address(self, request: SignMessageByAddress) -> SignMe
20472049
signing_mode=mode.value,
20482050
)
20492051

2050-
async def sign_message_by_id(self, request: dict[str, Any]) -> EndpointResult:
2052+
@marshal
2053+
async def sign_message_by_id(self, request: SignMessageByID) -> SignMessageByIDResponse:
20512054
"""
20522055
Given a NFT/DID ID, sign the message by the P2 private key.
20532056
:param request:
20542057
:return:
20552058
"""
2056-
entity_id: bytes32 = decode_puzzle_hash(request["id"])
2059+
entity_id: bytes32 = decode_puzzle_hash(request.id)
20572060
selected_wallet: Optional[WalletProtocol[Any]] = None
2058-
is_hex: bool = request.get("is_hex", False)
2059-
if isinstance(is_hex, str):
2060-
is_hex = True if is_hex.lower() == "true" else False
2061-
safe_mode: bool = request.get("safe_mode", True)
2062-
if isinstance(safe_mode, str):
2063-
safe_mode = True if safe_mode.lower() == "true" else False
20642061
mode: SigningMode = SigningMode.CHIP_0002
2065-
if is_hex and safe_mode:
2062+
if request.is_hex and request.safe_mode:
20662063
mode = SigningMode.CHIP_0002_HEX_INPUT
2067-
elif not is_hex and not safe_mode:
2064+
elif not request.is_hex and not request.safe_mode:
20682065
mode = SigningMode.BLS_MESSAGE_AUGMENTATION_UTF8_INPUT
2069-
elif is_hex and not safe_mode:
2066+
elif request.is_hex and not request.safe_mode:
20702067
mode = SigningMode.BLS_MESSAGE_AUGMENTATION_HEX_INPUT
2071-
if is_valid_address(request["id"], {AddressType.DID}, self.service.config):
2068+
if is_valid_address(request.id, {AddressType.DID}, self.service.config):
20722069
for wallet in self.service.wallet_state_manager.wallets.values():
20732070
if wallet.type() == WalletType.DECENTRALIZED_ID.value:
20742071
assert isinstance(wallet, DIDWallet)
@@ -2077,11 +2074,11 @@ async def sign_message_by_id(self, request: dict[str, Any]) -> EndpointResult:
20772074
selected_wallet = wallet
20782075
break
20792076
if selected_wallet is None:
2080-
return {"success": False, "error": f"DID for {entity_id.hex()} doesn't exist."}
2077+
raise ValueError(f"DID for {entity_id.hex()} doesn't exist.")
20812078
assert isinstance(selected_wallet, DIDWallet)
2082-
pubkey, signature = await selected_wallet.sign_message(request["message"], mode)
2079+
pubkey, signature = await selected_wallet.sign_message(request.message, mode)
20832080
latest_coin_id = (await selected_wallet.get_coin()).name()
2084-
elif is_valid_address(request["id"], {AddressType.NFT}, self.service.config):
2081+
elif is_valid_address(request.id, {AddressType.NFT}, self.service.config):
20852082
target_nft: Optional[NFTCoinInfo] = None
20862083
for wallet in self.service.wallet_state_manager.wallets.values():
20872084
if wallet.type() == WalletType.NFT.value:
@@ -2092,21 +2089,20 @@ async def sign_message_by_id(self, request: dict[str, Any]) -> EndpointResult:
20922089
target_nft = nft
20932090
break
20942091
if selected_wallet is None or target_nft is None:
2095-
return {"success": False, "error": f"NFT for {entity_id.hex()} doesn't exist."}
2092+
raise ValueError(f"NFT for {entity_id.hex()} doesn't exist.")
20962093

20972094
assert isinstance(selected_wallet, NFTWallet)
2098-
pubkey, signature = await selected_wallet.sign_message(request["message"], target_nft, mode)
2095+
pubkey, signature = await selected_wallet.sign_message(request.message, target_nft, mode)
20992096
latest_coin_id = target_nft.coin.name()
21002097
else:
2101-
return {"success": False, "error": f"Unknown ID type, {request['id']}"}
2098+
raise ValueError(f"Unknown ID type, {request.id}")
21022099

2103-
return {
2104-
"success": True,
2105-
"pubkey": str(pubkey),
2106-
"signature": str(signature),
2107-
"latest_coin_id": latest_coin_id.hex() if latest_coin_id is not None else None,
2108-
"signing_mode": mode.value,
2109-
}
2100+
return SignMessageByIDResponse(
2101+
pubkey=pubkey,
2102+
signature=signature,
2103+
latest_coin_id=latest_coin_id,
2104+
signing_mode=mode.value,
2105+
)
21102106

21112107
##########################################################################################
21122108
# CATs and Trading

chia/wallet/wallet_rpc_client.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@
162162
SetWalletResyncOnStartup,
163163
SignMessageByAddress,
164164
SignMessageByAddressResponse,
165+
SignMessageByID,
166+
SignMessageByIDResponse,
165167
SplitCoins,
166168
SplitCoinsResponse,
167169
SubmitTransactions,
@@ -1151,13 +1153,8 @@ async def sign_message_by_address(self, request: SignMessageByAddress) -> SignMe
11511153
await self.fetch("sign_message_by_address", request.to_json_dict())
11521154
)
11531155

1154-
async def sign_message_by_id(
1155-
self, id: str, message: str, is_hex: bool = False, safe_mode: bool = True
1156-
) -> tuple[str, str, str]:
1157-
response = await self.fetch(
1158-
"sign_message_by_id", {"id": id, "message": message, "is_hex": is_hex, "safe_mode": safe_mode}
1159-
)
1160-
return response["pubkey"], response["signature"], response["signing_mode"]
1156+
async def sign_message_by_id(self, request: SignMessageByID) -> SignMessageByIDResponse:
1157+
return SignMessageByIDResponse.from_json_dict(await self.fetch("sign_message_by_id", request.to_json_dict()))
11611158

11621159
async def verify_signature(self, request: VerifySignature) -> VerifySignatureResponse:
11631160
return VerifySignatureResponse.from_json_dict(await self.fetch("verify_signature", {**request.to_json_dict()}))

0 commit comments

Comments
 (0)