2012-12-03 15:36:03 +00:00
#!/usr/bin/python
import binascii
import argparse
import json
import bitkeylib . bitkey_pb2 as proto
from bitkeylib . client import BitkeyClient
2013-01-05 14:43:21 +00:00
from bitkeylib . debuglink import DebugLink
2012-12-03 15:36:03 +00:00
def parse_args ( commands ) :
parser = argparse . ArgumentParser ( description = ' Commandline tool for Bitkey devices. ' )
parser . add_argument ( ' -a ' , ' --algorithm ' , dest = ' algorithm ' , choices = [ ' bip32 ' , ' electrum ' ] , default = ' bip32 ' , help = ' Key derivation algorithm ' )
parser . add_argument ( ' -t ' , ' --transport ' , dest = ' transport ' , choices = [ ' usb ' , ' serial ' , ' pipe ' , ' socket ' ] , default = ' serial ' , help = " Transport used for talking with the device " )
parser . add_argument ( ' -p ' , ' --path ' , dest = ' path ' , default = ' /dev/ttyAMA0 ' , help = " Path used by the transport (usually serial port) " )
parser . add_argument ( ' -dt ' , ' --debuglink-transport ' , dest = ' debuglink_transport ' , choices = [ ' usb ' , ' serial ' , ' pipe ' , ' socket ' ] , default = ' socket ' , help = " Debuglink transport " )
parser . add_argument ( ' -dp ' , ' --debuglink-path ' , dest = ' debuglink_path ' , default = ' 0.0.0.0:8001 ' , help = " Path used by the transport (usually serial port) " )
parser . add_argument ( ' -j ' , ' --json ' , dest = ' json ' , action = ' store_true ' , help = " Prints result as json object " )
2012-12-05 19:31:26 +00:00
parser . add_argument ( ' -d ' , ' --debug ' , dest = ' debug ' , action = ' store_true ' , help = ' Enable low-level debugging ' )
2012-12-03 15:36:03 +00:00
cmdparser = parser . add_subparsers ( title = ' Available commands ' )
for cmd in commands . _list_commands ( ) :
func = object . __getattribute__ ( commands , cmd )
try :
help = func . help
except AttributeError :
help = ' '
try :
arguments = func . arguments
except AttributeError :
arguments = ( ( ( ' params ' , ) , { ' nargs ' : ' * ' } ) , )
item = cmdparser . add_parser ( cmd , help = func . help )
for arg in arguments :
item . add_argument ( * arg [ 0 ] , * * arg [ 1 ] )
item . set_defaults ( func = func )
return parser . parse_args ( )
def get_transport ( transport_string , path ) :
if transport_string == ' usb ' :
raise NotImplemented ( " USB HID transport not implemented yet " )
if transport_string == ' serial ' :
from bitkeylib . transport_serial import SerialTransport
return SerialTransport ( path )
if transport_string == ' pipe ' :
from bitkeylib . transport_pipe import PipeTransport
return PipeTransport ( path , is_device = False )
if transport_string == ' socket ' :
2012-12-05 19:31:26 +00:00
from bitkeylib . transport_socket import SocketTransportClient
return SocketTransportClient ( path )
2012-12-03 15:36:03 +00:00
if transport_string == ' fake ' :
from bitkeylib . transport_fake import FakeTransport
return FakeTransport ( path )
raise NotImplemented ( " Unknown transport " )
class Commands ( object ) :
def __init__ ( self , client ) :
self . client = client
@classmethod
def _list_commands ( cls ) :
return [ x for x in dir ( cls ) if not x . startswith ( ' _ ' ) ]
2013-01-05 14:43:21 +00:00
def get_address ( self , args ) :
return self . client . get_address ( args . n )
2012-12-03 15:36:03 +00:00
def get_entropy ( self , args ) :
return binascii . hexlify ( self . client . get_entropy ( args . size ) )
2013-01-05 14:43:21 +00:00
def get_master_public_key ( self , args ) :
return binascii . hexlify ( self . client . get_master_public_key ( ) )
2012-12-03 15:36:03 +00:00
2013-01-05 14:43:21 +00:00
def get_uuid ( self , args ) :
return binascii . hexlify ( self . client . get_uuid ( ) )
2012-12-05 19:31:26 +00:00
def load_device ( self , args ) :
seed = ' ' . join ( args . seed )
return self . client . load_device ( seed , args . otp , args . pin , args . spv )
2013-01-05 14:43:21 +00:00
get_address . help = ' Get bitcoin address in base58 encoding '
2012-12-03 15:36:03 +00:00
get_entropy . help = ' Get example entropy '
2013-01-05 14:43:21 +00:00
get_uuid . help = ' Get device \' s unique identifier '
2012-12-03 15:36:03 +00:00
get_master_public_key . help = ' Get master public key '
2012-12-05 19:31:26 +00:00
load_device . help = ' Load custom configuration to the device '
2012-12-03 15:36:03 +00:00
2013-01-05 14:43:21 +00:00
get_address . arguments = (
( ( ' n ' , ) , { ' metavar ' : ' N ' , ' type ' : int , ' nargs ' : ' + ' } ) ,
)
2012-12-03 15:36:03 +00:00
get_entropy . arguments = (
( ( ' size ' , ) , { ' type ' : int } ) ,
)
2012-12-05 19:31:26 +00:00
load_device . arguments = (
( ( ' -s ' , ' --seed ' ) , { ' type ' : str , ' nargs ' : ' + ' } ) ,
( ( ' -n ' , ' --pin ' ) , { ' type ' : str , ' default ' : ' ' } ) ,
( ( ' -o ' , ' --otp ' ) , { ' action ' : ' store_true ' } ) ,
( ( ' -p ' , ' --spv ' ) , { ' action ' : ' store_true ' } ) ,
)
2012-12-03 15:36:03 +00:00
def main ( ) :
args = parse_args ( Commands )
transport = get_transport ( args . transport , args . path )
2012-12-05 19:31:26 +00:00
if args . debug :
debuglink_transport = get_transport ( args . debuglink_transport , args . debuglink_path )
2013-01-05 14:43:21 +00:00
debuglink = DebugLink ( debuglink_transport )
2012-12-05 19:31:26 +00:00
else :
2013-01-05 14:43:21 +00:00
debuglink = None
2012-12-03 15:36:03 +00:00
if args . algorithm == ' electrum ' :
algo = proto . ELECTRUM
elif args . algorithm == ' bip32 ' :
algo = proto . BIP32
else :
raise Exception ( " Unknown algorithm " )
2013-01-05 14:43:21 +00:00
client = BitkeyClient ( transport , debuglink = debuglink , algo = algo )
client . setup_debuglink ( button = True , otp_correct = True , pin_correct = True )
2012-12-03 15:36:03 +00:00
cmds = Commands ( client )
res = args . func ( cmds , args )
if args . json :
print json . dumps ( res )
else :
print res
if __name__ == ' __main__ ' :
main ( )