diff --git a/bitkeylib/client.py b/bitkeylib/client.py index 5b17a1d6c..2fd7dbcb8 100644 --- a/bitkeylib/client.py +++ b/bitkeylib/client.py @@ -45,21 +45,26 @@ class BitkeyClient(object): def _pprint(self, msg): return "<%s>:\n%s" % (msg.__class__.__name__, msg) - def setup_debuglink(self, pin_correct=False, otp_correct=False): + def setup_debuglink(self, button=None, pin_correct=False, otp_correct=False): + self.debug_button = button self.debug_pin = pin_correct self.debug_otp = otp_correct - def call(self, msg, button=None, tries=1): + def call(self, msg): if self.debug: print '----------------------' print "Sending", self._pprint(msg) self.transport.write(msg) - - if self.debuglink and button != None: - self.debuglink.press_button(button) + resp = self.transport.read_blocking() - resp = self.transport.read() + if isinstance(resp, proto.ButtonRequest): + if self.debuglink and self.debug_button: + print "Pressing button", self.debug_button + self.debuglink.press_button(self.debug_button) + + self.transport.write(proto.ButtonAck()) + resp = self.transport.read_blocking() if isinstance(resp, proto.OtpRequest): if self.debuglink: @@ -72,7 +77,7 @@ class BitkeyClient(object): otp = self.input_func("OTP required: ", resp.message) msg2 = proto.OtpAck(otp=otp) - return self.call(msg2, button, tries) + return self.call(msg2) if isinstance(resp, proto.PinRequest): if self.debuglink: @@ -85,27 +90,20 @@ class BitkeyClient(object): pin = self.input_func("PIN required: ", resp.message) msg2 = proto.PinAck(pin=pin) - return self.call(msg2, button, tries) + return self.call(msg2) if isinstance(resp, proto.Failure): self.message_func(resp.message) if resp.code == 3: - if tries <= 1: - raise Exception("OTP is invalid, too many retries") - self.message_func("OTP is invalid, let's try again...") + raise Exception("OTP is invalid") elif resp.code == 4: raise Exception("Action cancelled by user") elif resp.code == 6: - if tries <= 1: - raise Exception("PIN is invalid, too many retries") - self.message_func("PIN is invalid, let's try again...") + raise Exception("PIN is invalid") - return self.call(msg, button, tries-1) - - if isinstance(resp, proto.Failure): raise Exception(resp.code, resp.message) if self.debug: @@ -122,6 +120,7 @@ class BitkeyClient(object): outputs: list of TxOutput ''' + tx = proto.SignTx() tx.algo = self.algo # Choose BIP32 or ELECTRUM way for deterministic keys tx.random = os.urandom(256) # Provide additional entropy to the device @@ -159,6 +158,7 @@ class BitkeyClient(object): return s_inputs ''' - def load_device(self, seed, otp, pin, spv, button=None): - self.call(proto.LoadDevice(seed=seed, otp=otp, pin=pin, spv=spv), button=button) - self.init_device() \ No newline at end of file + def load_device(self, seed, otp, pin, spv): + resp = self.call(proto.LoadDevice(seed=seed, otp=otp, pin=pin, spv=spv)) + self.init_device() + return isinstance(resp, proto.Success) \ No newline at end of file diff --git a/bitkeylib/debuglink.py b/bitkeylib/debuglink.py index 98e81525d..2e072f6fb 100644 --- a/bitkeylib/debuglink.py +++ b/bitkeylib/debuglink.py @@ -1,10 +1,10 @@ import bitkey_pb2 as proto - + def otp_info(otp): - print "Device asks for OTP %s" % otp + print "Device asks for OTP %s" % otp.otp def pin_info(pin): - print "Device asks for PIN %s" % pin + print "Device asks for PIN %s" % pin.pin def button_press(yes_no): print "User pressed", '"y"' if yes_no else '"n"' @@ -12,31 +12,32 @@ def button_press(yes_no): class DebugLink(object): def __init__(self, transport, otp_func=otp_info, pin_func=pin_info, button_func=button_press): self.transport = transport + self.otp_func = otp_func self.pin_func = pin_func self.button_func = button_func + def get_state(self, otp=False, pin=False): + self.transport.write(proto.DebugLinkGetState(otp=otp, pin=pin)) + return self.transport.read_blocking() + def read_otp(self): - obj = self.transport.read() - if not isinstance(obj, proto.OtpAck): - raise Exception("Expected OtpAck object, got %s" % obj) + obj = self.get_state(otp=True).otp + print "Read OTP:", obj.otp self.otp_func(obj) return obj def read_pin(self): - obj = self.transport.read() - if not isinstance(obj, proto.PinAck): - raise Exception("Expected PinAck object, got %s" % obj) + obj = self.get_state(pin=True).pin + print "Read PIN:", obj.pin self.pin_func(obj) return obj def press_button(self, yes_no): + print "Pressing", yes_no self.button_func(yes_no) self.transport.write(proto.DebugLinkDecision(yes_no=yes_no)) - #obj = self.transport.read() - #if not isinstance(obj, proto.Success): - # raise Exception("Expected Success object, got %s" % obj) - + def press_yes(self): self.press_button(True)