How to get the correct private key that pertains to puzzle hash of a coin you own?

Hi Guys, been working on a singleton project which I’m making gradual progress on. I’m now trying to spend a standard transaction coin. For this to happen I need the private and public key which are children of my master public key pertaining to the transaction in question (I will need these for my project later anyhow). My question is how can I find these children in python?

I see there is a function called get_keys() in chia/wallet/wallet_state_manager.py, and believe this should do the job, but its a method of the WalletStateManager class, which I’m really not sure how to initialise as there seems to be alot to pass in - (I code as a bit of a hobby, and still have much to learn!).

I’ts also been suggested that I try use chia keys derive - but not having much luck with this method either?

Can anyone help me out if there is a easy way to get these? in many of the tutorials for example in the chia concepts github, it seems they are using the sim so it’s much easier! Thanks for your help in advance!

If you want to get the child private keys, you have to derive from private key. However, for observer keys, you can also derive public keys from public key. More information about HD path and observer/non-observer keys can be found in 9.1 BLS Keys.

The python functions that you can use are in chia/wallet/derive_keys.py.

Let’s use chia keys derive first:

Fingerprint: 4293720451
Master public key (m): 8fe776afa643f3f1e6f5449bb7cfb1b82f7b594c4ebffba739a73b2d035feb1d6dc46b51ceb84b0f2fc59ddecfcb4b03
...
First wallet address: txch13c9thmchxzynp8t464d8slkrtpzgefth6ttgl5mhkrg48xw4gces5c8kxl
Master private key (m): 2a672d44d88a09f0a31b9bc3e2de344d67a376cb9a9e2179c580895cc1127062
First wallet secret key (m/12381/8444/2/0): <PrivateKey 309b626c696d3af174483bb74c1751e54fd89518bb03ede22f92627bb0e35e06>

❯ chia keys derive -f 4293720451 child-key --count 3 --derive-from-hd-path 'm/12381/8444/2/'   --show-hd-path --show-private-keys
Observer public key 0 (m/12381/8444/2/0): ab70e044607c003fecac7dbfc7729c4688e0c9f7d6a56ff7c73a0f96dcf65681073516e86785864dfc0c7c57878206fa
Observer private key 0 (m/12381/8444/2/0): 55735f11aac108a60037bc7e534410c622f86d987724ed8a4d1a91d777d41187
Observer public key 1 (m/12381/8444/2/1): 925acf522c09bfb4039d3d5acc3588f48339726521219b9f4df0a1426c13f9798a75cd5af2f06cb71698846df890edce
Observer private key 1 (m/12381/8444/2/1): 0ddd3bb391a1d85b42e6611e96d117eb3c2ceaad8b8a0a63d83941ac715e47dc
Observer public key 2 (m/12381/8444/2/2): b762db7f20dc8fa8b2b960f2ab01700b37cd8788bb3c17f4404f4d428790c78e7687abcc2e5360f0ae11101fa34edd19
Observer private key 2 (m/12381/8444/2/2): 1257f313b3ee14115a713e2e8874378c6f7b5b6e9e58348e305bb79a10ae9e03

Now, let’s do it in Python:

from blspy import (PrivateKey)
from chia.util.ints import uint32
from chia.wallet import derive_keys

master_sk: PrivateKey = PrivateKey.from_bytes(bytes.fromhex("2a672d44d88a09f0a31b9bc3e2de344d67a376cb9a9e2179c580895cc1127062"))

# non-observer or hardened key
print(derive_keys.master_sk_to_wallet_sk(master_sk, uint32(0)))

# observer or unhardened keys
for i in range(3):
    wallet_sk = derive_keys.master_sk_to_wallet_sk_unhardened(master_sk, uint32(i))
    print(wallet_sk)

# ❯ python ./derive-sks.py
# <PrivateKey 309b626c696d3af174483bb74c1751e54fd89518bb03ede22f92627bb0e35e06>
# <PrivateKey 55735f11aac108a60037bc7e534410c622f86d987724ed8a4d1a91d777d41187>
# <PrivateKey 0ddd3bb391a1d85b42e6611e96d117eb3c2ceaad8b8a0a63d83941ac715e47dc>
# <PrivateKey 1257f313b3ee14115a713e2e8874378c6f7b5b6e9e58348e305bb79a10ae9e03>

Thankyou! Your help is always invaluable! what I am trying to do is obtain the right puzzle reveal for a standard coin in my wallet I want to spend. The coin I get from my wallet by getting a signed transaction:

 signed_transaction = await wallet_client_f.create_signed_transaction(
            [{"puzzle_hash": ph, "amount": amt}], fee=fee
        )

and then just grabbing the coin.

I presumed that I could just use the hardened key to derive the right public key for this spend:

derive_keys.master_sk_to_wallet_sk(master_sk, uint32(0)).get_g1()

and then use

puzzle_for_public_key_and_hidden_puzzle_hash(pk, DEFAULT_HIDDEN_PUZZLE_HASH)

to get the right puzzle reveal. However, this doesn’t seem to work - how can I find the correct dervived key for this spend?

Thankyou so much for your help!

Dan

Coins in your wallet could have different puzzle hashes. The brute-force way to find the correct key is to derive lot of keys (i.e., 0-100), generate puzzle, and compare the puzzle hash of your selected coin with it to find the correct key.

Chia wallet keeps the records of puzzle hashes, their associated public keys, and the derivation index on the derivation_paths table of the wallet db (it’s sqlite db in the wallet/db folder). So it’s faster to get a correct key from a puzzle hash.

The create_signed_transaction rpc api actually uses this way to get the correct key to sign the transaction.