Is this Grin Wallet URL Reachable?

Awesome!

Well, would you mind to share your code? I could try to fix it and then explain it here:

If you’re familiar with python here’s another testing code:

"""
Key Generation
Keys used in SlatepackAddresses are derived from a path from the master seed in a given wallet account. Currently the wallet uses separate derivation paths: one for the private bytes used for the blinding factor keys and one for the private bytes used to derive the ed25519 keys used to derive Tor onion addresses. ed25519 keys used for a SlatepackAddress are derived from this second derivation path of the master seed.

SlatepackAddress keys may be derived in parallel to the blinding factor derivation path such that a unique SlatepackAddress is derived each time a new blinding factor is derived for a transaction to satisfy the requirement for a unique SlatepackAddress to be used for each transaction by default.

In a future update it may be desirable to encode the derivation path for the SlatepackAddress for a given encrypted SlatepackMessage somewhere so that the x25519 decryption keys can be derived without grinding down the path to find the right key to use.

Example SlatepackAddress
grin1p4fuklglxqsgg602hu4c4jl4aunu5tynyf4lkg96ezh3jefzpy6swshp5x
"""

import base64
import binascii
from hashlib import sha3_256

import nacl.encoding
import nacl.hash
import nacl.signing
from Cryptodome.Random import get_random_bytes
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import ed25519
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from ecdsa import SigningKey, ecdsa
from mnemonic import Mnemonic

import segwit_addr
from seed import decrypt, encrypt


def generate_seed(length):
    return get_random_bytes(int(((4 * length) / 3)))


def tor_address(key_bytes):
    version = b"\x03"
    checksum = sha3_256(b".onion checksum" + key_bytes + version).digest()
    return base64.b32encode(key_bytes + checksum[0:2] + version).lower()


def encode_grin1_address(vk, hrp="grin"):
    values = segwit_addr.convertbits(list(vk), 8, 5)
    checksum = segwit_addr.bech32_create_checksum(
        hrp, values, segwit_addr.Encoding.BECH32
    )
    combined = values + checksum
    return hrp + "1" + "".join([segwit_addr.CHARSET[d] for d in combined])


def decode_grin1_address(addr, hrp="grin"):
    data = segwit_addr.bech32_decode(addr)
    decoded = segwit_addr.convertbits(data[1], 5, 8, False)
    return bytes(decoded)


if __name__ == "__main__":
    key_pair = Ed25519PrivateKey.from_private_bytes(
        bytes.fromhex(
            "29a5b01c3ecf2dff63e30d8857f12a2bc99e0ab51a610c5c33f5035070d62a0b"
        )
    )
    public_key = key_pair.public_key().public_bytes(
        encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw
    )
    address = tor_address(public_key).decode("utf8")
    grin1 = encode_grin1_address(public_key)
    print(f"Public Key:\t {public_key.hex()}")
    print(f"Tor Address:\t {address}")
    print(f"Bech32 Address:\t {grin1}")

    assert (
        public_key.hex()
        == "dcb57a361f64ca43b6c82fde6b2c771f0408d5115c007b90b1f249bc4efc5fcc"
    )
    assert address == "3s2xunq7mtfehnwif7pgwldxd4carvirlqahxefr6je3ytx4l7glq5yd"
    assert grin1 == "grin1mj6h5dslvn9y8dkg9l0xktrhruzq34g3tsq8hy937fymcnhutlxqkuf6xx"

    decoded = decode_grin1_address(grin1, "grin")
    assert decoded.hex() == public_key.hex()
    assert address == tor_address(public_key).decode("utf8")
    print(f"Decoded:\t {decoded.hex()}")

You can get the segwit_addr code here: https://github.com/sipa/bech32/blob/master/ref/python/segwit_addr.py

3 Likes