I had created a mnemonic seed and address using MMGEN wallet but forgot to store the mnemonic seed, but did store the bip 32 root key by using the mnemonic seed on Ian colmen
Now I want to derive the same address using a derivation path and bip 32 root key. can you please tell me what would be the derivation path, since it is mentioned in the wiki, that the wallet is deterministically deriving its keys, but uses a non-hierarchical scheme differing from the BIP32.
Please help me if anyone has any idea which derivation path they are using.
According to Mmgen's github repository, apart from the standard:
BIP44 (P2PKH): m/44 '/0'/0 '/0
BIP49 (P2SH-P2WPKH): m/49 '/0'/0 '/0
BIP84 (P2WPKH): m/84 '/0'/0 '/0
BIP86 (P2TR): M/86 '/0'/0 '/0
This could be the path in their derivations.
Taking as an example Bech32import hashlib
import bip32utils
def sha256(data):
return hashlib.sha256(data).digest()
def ripemd160(data):
h = hashlib.new('ripemd160')
h.update(data)
return h.digest()
def bech32_polymod(values):
generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
chk = 1
for v in values:
b = (chk >> 25)
chk = (chk & 0x1ffffff) << 5 ^ v
for i in range(5):
chk ^= generator[i] if ((b >> i) & 1) else 0
return chk
def bech_expand(hrp):
return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp]
def bech_checksum(hrp, data):
values = bech_expand(hrp) + data
polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ 1
return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)]
def bech32_encode(hrp, data):
combined = data + bech_checksum(hrp, data)
BECH_CHRS = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'
return hrp + '1' + ''.join([BECH_CHRS[d] for d in combined])
def cbits(data, frombits, tobits, pad=True):
acc = 0
bits = 0
ret = []
maxv = (1 << tobits) - 1
for value in data:
if value < 0 or (value >> frombits):
raise ValueError("Invalid value")
acc = (acc << frombits) | value
bits += frombits
while bits >= tobits:
bits -= tobits
ret.append((acc >> bits) & maxv)
if pad:
if bits:
ret.append((acc << (tobits - bits)) & maxv)
elif bits >= frombits or ((acc << (tobits - bits)) & maxv):
raise ValueError("Invalid bits")
return ret
def bech_address(pubkey):
sha256_r = sha256(pubkey)
ripemdr = ripemd160(sha256_r)
data = cbits(ripemdr, 8, 5)
data = [0] + data
hrp = 'bc' # for MainNet
address = bech32_encode(hrp, data)
return address
xprv = "XPRV here"
bip32_root_key_obj = bip32utils.BIP32Key.fromExtendedKey(xprv)
with open("derived_addresses.txt", "w") as file:
# Derive keys using the path m/0'/0'/0'
for i in range(1001):
derived_key = bip32_root_key_obj.ChildKey(0 + 0x80000000).ChildKey(0 + 0x80000000).ChildKey(i + 0x80000000)
priv_key = derived_key.WalletImportFormat()
pubkey = derived_key.PublicKey().hex()
pubkey_bytes = bytes.fromhex(pubkey)
bech32_address = bech_address(pubkey_bytes)
file.write(f"Private Key: {priv_key}\nPublic Key: {pubkey}\nSegWit (Bech32) Address: {bech32_address}\n\n")
# Derive keys using the path m/0'/1'/0'
for z in range(1001):
derived_key = bip32_root_key_obj.ChildKey(0 + 0x80000000).ChildKey(1 + 0x80000000).ChildKey(z + 0x80000000)
priv_key = derived_key.WalletImportFormat()
pubkey = derived_key.PublicKey().hex()
pubkey_bytes = bytes.fromhex(pubkey)
bech32_address = bech_address(pubkey_bytes)
file.write(f"Private Key: {priv_key}\nPublic Key: {pubkey}\nSegWit (Bech32) Address: {bech32_address}\n\n")
# Derive keys using the path m/84'/2'/0'
for x in range(1001):
derived_key = bip32_root_key_obj.ChildKey(84 + 0x80000000).ChildKey(2 + 0x80000000).ChildKey(x + 0x80000000)
priv_key = derived_key.WalletImportFormat()
pubkey = derived_key.PublicKey().hex()
pubkey_bytes = bytes.fromhex(pubkey)
bech32_address = bech_address(pubkey_bytes)
file.write(f"Private Key: {priv_key}\nPublic Key: {pubkey}\nSegWit (Bech32) Address: {bech32_address}\n\n")
print("Derivation completed. The results are saved in 'derived_addresses.txt'.")