Skip to content

Instantly share code, notes, and snippets.

@AdamISZ
Created January 14, 2021 13:00
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save AdamISZ/d9db8d8abc611fa4c25618f02823123b to your computer and use it in GitHub Desktop.
Save AdamISZ/d9db8d8abc611fa4c25618f02823123b to your computer and use it in GitHub Desktop.
Script to recover pre-segwit Joinmarket wallet keys from the seedphrase only without Bitcoin Core
import os
from optparse import OptionParser
from jmbase import jmprint
from jmclient import load_program_config, LegacyWallet, VolatileStorage, get_network
def get_parser():
description = (
'Use this script to extract keys and addresses from pre-segwit '
'Joinmarket wallets if you do not have access to Bitcoin Core. Specify '
'number of mixdepths (default 5) with -m and number of addresses per '
'mixdepth with -N (default 20). So to print 100 addresses in each of '
'6 mixdepths use `python recover-old-keys.py -m 6 -N 100. Enter seed '
' when prompted. '
'PLEASE BE CAUTIOUS WHEN PRINTING PRIVATE KEYS!')
parser = OptionParser(usage='usage: %prog [options]',
description=description)
parser.add_option('-m',
'--mixdepths',
action='store',
type='int',
dest='mixdepths',
help="Mixdepth(s) to use in the wallet. Default=6",
default=6)
parser.add_option('-N',
'--num-addresses',
action='store',
type='int',
dest='num_addresses',
help="Number of addresses to print keys for per mixdepth, default=20",
default=20)
return parser
def wallet_dumpprivkeys(wallet, m, N):
"""returns a list of strings, each string is formatted:
hdpath, address, private key in wif - this is CSV.
"""
csvstrings = []
for i in range(m):
for j in range(2):
for k in range(N):
hdpath = "m/0/"+"/".join([str(x) for x in [i, j, k]])
path = wallet.path_repr_to_path(hdpath)
wif = wallet.get_wif_path(path)
addr = wallet.get_address_from_path(path)
csvstrings.append(",".join([hdpath, addr, wif])+"\n")
return "\n".join(csvstrings)
def recover_keys_main():
"""returned is a string (output or error)
"""
parser = get_parser()
(options, args) = parser.parse_args()
if options.mixdepths < 1:
parser.error("Must have at least one mixdepth.")
sys.exit(0)
while True:
proposed_seed = input("Enter 12 word seed: ")
word_count = len(proposed_seed.split())
if word_count == 12:
break
jmprint("Wrong seed length, should be 12 words.")
entropy = LegacyWallet.entropy_from_mnemonic(proposed_seed)
storage = VolatileStorage()
LegacyWallet.initialize(storage, get_network(), max_mixdepth=5, entropy=entropy)
wallet = LegacyWallet(storage)
return wallet_dumpprivkeys(wallet, options.mixdepths, options.num_addresses)
if __name__ == "__main__":
load_program_config()
jmprint(recover_keys_main(), "success")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment