forked from LBRYCommunity/lbry-sdk
script to migrate private keys to lbrycrd (#79)
* script to migrate private keys to lbrycrd * handle compressed keys too * validate private key actually gets added * add lbrycrdd and lbrycrd-cli checks * exit if no wallet path * move each imported address into the default account
This commit is contained in:
parent
5ebcc01bcc
commit
5817b80c94
1 changed files with 113 additions and 0 deletions
113
scripts/migrate_lbryum_to_lbrycrd.py
Normal file
113
scripts/migrate_lbryum_to_lbrycrd.py
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
import argparse
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import base58
|
||||||
|
|
||||||
|
from lbryum import SimpleConfig, Network
|
||||||
|
from lbryum.wallet import WalletStorage, Wallet
|
||||||
|
from lbryum.commands import known_commands, Commands
|
||||||
|
from lbryum import lbrycrd
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--wallet', help='path to lbryum wallet')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
ensureCliIsOnPathAndServerIsRunning()
|
||||||
|
|
||||||
|
wallet = getWallet(args.wallet)
|
||||||
|
addresses = wallet.addresses(True)
|
||||||
|
for addr in addresses[:-1]:
|
||||||
|
printBalance(wallet, addr)
|
||||||
|
saveAddr(wallet, addr)
|
||||||
|
# on the last one, rescan. Don't rescan early for sake of efficiency
|
||||||
|
addr = addresses[-1]
|
||||||
|
printBalance(wallet, addr)
|
||||||
|
saveAddr(wallet, addr, "true")
|
||||||
|
|
||||||
|
|
||||||
|
def ensureCliIsOnPathAndServerIsRunning():
|
||||||
|
try:
|
||||||
|
output = subprocess.check_output(['lbrycrd-cli', 'getinfo'])
|
||||||
|
except OSError:
|
||||||
|
print 'Failed to run: lbrycrd-cli needs to be on the PATH'
|
||||||
|
exit(1)
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
print 'Failed to run: could not connect to the lbrycrd server.'
|
||||||
|
print 'Make sure it is running and able to be connected to.'
|
||||||
|
print 'One way to do this is to run:'
|
||||||
|
print ' lbrycrdd -server -printtoconsole'
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def validateAddress(addr):
|
||||||
|
raw_output = subprocess.check_output(
|
||||||
|
['lbrycrd-cli', 'validateaddress', addr])
|
||||||
|
output = json.loads(raw_output)
|
||||||
|
if not output['isvalid']:
|
||||||
|
raise Exception('Address {} is not valid'.format(addr))
|
||||||
|
if not output['ismine']:
|
||||||
|
raise Exception('Address {} is not yours'.format(addr))
|
||||||
|
|
||||||
|
|
||||||
|
def printBalance(wallet, addr):
|
||||||
|
balance = getBalance(wallet, addr)
|
||||||
|
print 'Importing private key for %s with balance %s' % (addr, balance)
|
||||||
|
|
||||||
|
|
||||||
|
def getBalance(wallet, addr):
|
||||||
|
return sum(wallet.get_addr_balance(addr))
|
||||||
|
|
||||||
|
|
||||||
|
def getWallet(path=None):
|
||||||
|
if not path:
|
||||||
|
config = SimpleConfig()
|
||||||
|
path = config.get_wallet_path()
|
||||||
|
storage = WalletStorage(path)
|
||||||
|
if not storage.file_exists:
|
||||||
|
print "Failed to run: No wallet to migrate"
|
||||||
|
exit(1)
|
||||||
|
return Wallet(storage)
|
||||||
|
|
||||||
|
|
||||||
|
def saveAddr(wallet, addr, rescan="false"):
|
||||||
|
keys = wallet.get_private_key(addr, None)
|
||||||
|
assert len(keys) == 1, 'Address {} has {} keys. Expected 1'.format(addr, len(keys))
|
||||||
|
key = keys[0]
|
||||||
|
# copied from lbrycrd.regenerate_key
|
||||||
|
b = lbrycrd.ASecretToSecret(key)
|
||||||
|
pkey = b[0:32]
|
||||||
|
is_compressed = lbrycrd.is_compressed(key)
|
||||||
|
wif = pkeyToWif(pkey, is_compressed)
|
||||||
|
subprocess.check_call(
|
||||||
|
['lbrycrd-cli', 'importprivkey', wif, "lbryum import", rescan])
|
||||||
|
validateAddress(addr)
|
||||||
|
# during the import the account gets set to the label, but lbry
|
||||||
|
# needs the address to be in the default account
|
||||||
|
subprocess.check_call(['lbrycrd-cli', 'setaccount', addr, '""'])
|
||||||
|
|
||||||
|
|
||||||
|
def pkeyToWif(pkey, compressed):
|
||||||
|
# Follow https://en.bitcoin.it/wiki/Wallet_import_format
|
||||||
|
# to convert from a private key to the wallet import format
|
||||||
|
prefix = '\x1c'
|
||||||
|
wif = prefix + pkey
|
||||||
|
if compressed:
|
||||||
|
wif += '\x01'
|
||||||
|
intermediate_checksum = hashlib.sha256(wif).digest()
|
||||||
|
checksum = hashlib.sha256(intermediate_checksum).digest()
|
||||||
|
wif = wif + checksum[:4]
|
||||||
|
return base58.b58encode(wif)
|
||||||
|
|
||||||
|
|
||||||
|
def wifToPkey(wif):
|
||||||
|
pkey = base58.b58decode(wif)
|
||||||
|
return pkey[1:-4]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
Loading…
Reference in a new issue