Closed tigermap7 closed 5 months ago
Hi,
First of all, you should use bip44_mst_ctx
and not bip44_addr_ctx
for getting the private key, because you are recovering from the master private key.
Secondly, when you recover from a raw private key, you also have to specify the chaincode that was generated from the seed (it's usually the second half of the computed HMAC). If not specified, it will be set to all zeroes. You don't need to specify it when you recover from an extended private key, because the chaincode is included in it. This is valid in general, i.e. also for BIP44/49/etc...
So, your example becomes:
from bip_utils import *
mnemonic = "solid dinner elephant audit toilet violin decade weasel invite orange purse say symbol behave typical"
seed = CardanoIcarusSeedGenerator(mnemonic).Generate()
bip44_mst_ctx = Cip1852.FromSeed(seed, Cip1852Coins.CARDANO_ICARUS)
shelly = CardanoShelley.FromCip1852Object(
bip44_mst_ctx.Purpose().Coin().Account(0)
)
bip44_addr_ctx = shelly.Change(Bip44Changes.CHAIN_EXT).AddressIndex(0)
print(f"Address: {bip44_addr_ctx.PublicKeys().ToAddress()}")
print(f"Public Key: {bip44_addr_ctx.PublicKeys().AddressKey().RawCompressed().ToHex()}")
print(f"Private Key: {bip44_addr_ctx.PrivateKeys().AddressKey().Raw().ToHex()}")
fromPk = Cip1852.FromPrivateKey(
bip44_mst_ctx.PrivateKey().Raw().ToBytes(),
Cip1852Coins.CARDANO_ICARUS,
Bip32KeyData(chain_code=bip44_mst_ctx.PrivateKey().Bip32Key().ChainCode().ToBytes())
)
shelly = CardanoShelley.FromCip1852Object(
fromPk.Purpose().Coin().Account(0)
)
bip44_addr_ctx = shelly.Change(Bip44Changes.CHAIN_EXT).AddressIndex(0)
# Same address
print(f"Address: {bip44_addr_ctx.PublicKeys().ToAddress()}")
Thank you for your response. I have a question from what you said.
bip44_addr_ctx.PrivateKeys().AddressKey().Raw().ToHex()
Can't I recover the address with this private key?
My intention is to get an address where the private key and the private key of one address match without a mnemonic. For example, getting an address in a private key for each address, such as Ethereum.
In the recovery code you told me, it seems that there must be a mnemonic.
Nope, I added a mnemonic just to make the code running, but if you see I'm using the private key to recover not the mnemonic. Anyway, I used the master private key because in your example you derived keys again, so I thought you wanted to use it.
It's possible to use the address private key to recover a BIP object (i.e. Bip44
, Bip49
, etc...), in this case you don't even need the chain code because you don't derive keys (chain code is only used to derive keys):
from bip_utils import *
# Just for the example
mnemonic = Bip39MnemonicGenerator().FromWordsNumber(Bip39WordsNum.WORDS_NUM_12)
seed = Bip39SeedGenerator(mnemonic).Generate()
bip44_mst = Bip44.FromSeed(seed, Bip44Coins.ETHEREUM)
bip44_addr = bip44_mst.Purpose().Coin().Account(0).Change(Bip44Changes.CHAIN_EXT).AddressIndex(0)
print(f"Address: {bip44_addr.PublicKey().ToAddress()}")
# Store private key in hex format
priv_key_hex = bip44_addr.PrivateKey().Raw().ToHex()
# Recover from stored private key
bip44_recovered = Bip44.FromPrivateKey(BytesUtils.FromHexString(priv_key_hex), Bip44Coins.ETHEREUM)
print(f"Recovered address from private key: {bip44_recovered.PublicKey().ToAddress()}")
However, for Cardano Shelley, this is not possible because it uses 2 private keys, one for receiving payments and one for staking.
I didn't create a method for recovering from the 2 private keys because it's mathematically impossible to know if the 2 keys are valid, i.e. they are derived from the same parent key.
What you can do is store the extended private key (in this way you don't need to store the chain code) of the Cip1852
account object and then use it to recover the CardanoShelley
object:
from bip_utils import *
# Just for the example
mnemonic = Bip39MnemonicGenerator().FromWordsNumber(Bip39WordsNum.WORDS_NUM_15)
seed = CardanoIcarusSeedGenerator(mnemonic).Generate()
cip1852_acc = Cip1852.FromSeed(seed, Cip1852Coins.CARDANO_ICARUS).Purpose().Coin().Account(0)
shelley_addr = CardanoShelley.FromCip1852Object(cip1852_acc).Change(Bip44Changes.CHAIN_EXT).AddressIndex(0)
print(f"Address: {shelley_addr.PublicKeys().ToAddress()}")
# Store private key in extended format
priv_key_ex = cip1852_acc.PrivateKey().ToExtended()
# Recover from stored private key
cip1852_recovered = Cip1852.FromExtendedKey(priv_key_ex, Cip1852Coins.CARDANO_ICARUS)
shelley_addr = CardanoShelley.FromCip1852Object(cip1852_recovered).Change(Bip44Changes.CHAIN_EXT).AddressIndex(0)
print(f"Recovered address from private ke: {shelley_addr.PublicKeys().ToAddress()}")
Hello I'm trying to create a Cardano address and recover the address with the Private key I created. I'm asking because there is a problem with the address you created and the address you recovered.
Cardano has created an address and a private key
seed = CardanoIcarusSeedGenerator(mnemonic).Generate() coinType = Cip1852Coins.CARDANO_ICARUS bip44_mst_ctx = Cip1852.FromSeed(seed, coinType) bip44_acc_ctx = bip44_mst_ctx.Purpose().Coin().Account(0) shelly = CardanoShelley.FromCip1852Object(bip44_acc_ctx) bip44_chg_ctx = shelly.Change(Bip44Changes.CHAIN_EXT) bip44_addr_ctx = bip44_chg_ctx.AddressIndex(0)
print(f"Address: {bip44_addr_ctx.PublicKeys().ToAddress()}") print(f"Public Key: {bip44_addr_ctx.PublicKeys().AddressKey().RawCompressed().ToHex()}") print(f"Private Key: {bip44_addr_ctx.PrivateKeys().AddressKey().Raw().ToHex()}")
So I'm going to get a private key and I'm going to get it back to the address from the private key (using bip44_addr_ctx.PrivateKeys().AddressKey().Raw().ToHex())
` fromPk = Cip1852.FromPrivateKey(bytes.fromhex(pk.lstrip('0x')), Cip1852Coins.CARDANO_ICARUS) bip44_acc_ctx = fromPk.Purpose().Coin().Account(0) shelly = CardanoShelley.FromCip1852Object(bip44_acc_ctx) bip44_chg_ctx = shelly.Change(Bip44Changes.CHAIN_EXT) bip44_addr_ctx = bip44_chg_ctx.AddressIndex(0)
print(f"Address: {bip44_addr_ctx.PublicKeys().ToAddress()}") `
create address : addr1q8uymmyzmj5q88patkq28wjscseawn2m8xxxc2npkzzv2sq2q7a0l82p3fg87ayem8cd00rta4djwysphquzu9h9vx4qe308w9
recovered address : addr1q8uwaz4gwxuslslr7j3z0gyd9usynfm9cnz4ex85qeqjwdm9f2fvh2g3s8ednkelqv6tvjqje8sys2h8r46yqxqu299smfy0tf
How do I implement it to recover the same way?