From 0770d8a54f350fab6cd937044215c0625e778c05 Mon Sep 17 00:00:00 2001 From: Thomas Kerin Date: Sun, 8 Apr 2018 21:39:43 +0200 Subject: [PATCH] wip button and debugging --- debug.php | 36 +++++++++ src/Bridge/Client.php | 10 ++- src/Bridge/Http/HttpClient.php | 37 +++++---- src/Bridge/Session.php | 36 ++++++--- src/Device/Button/ButtonAck.php | 14 ++++ src/Device/Button/DebugButtonAck.php | 62 +++++++++++++++ src/Device/Button/HumanButtonAck.php | 24 ++++++ src/Device/Command/DeviceService.php | 1 - src/Device/Command/LoadDeviceService.php | 43 +++++++++++ src/Device/DebugMessage.php | 44 +++++++++++ src/Device/Message.php | 37 +++------ src/Device/MessageBase.php | 38 ++++++++++ src/Device/RequestFactory.php | 76 +++++++++++++++++++ test/device/AbstractDeviceTest.php | 56 ++++++++++++++ test/device/AcquireDeviceTest.php | 10 ++- test/device/Bridge/ClientTest.php | 4 +- .../Device/{ => Command}/CommandTest.php | 14 +++- .../Device/Command/InitializeServiceTest.php | 21 ----- .../Device/Command/LoadDeviceServiceTest.php | 58 ++++++++++++++ .../device/Device/Command/SetupDeviceTest.php | 30 ++++++++ .../Command/UninitializedDeviceTest.php | 31 ++++++++ test/device/Device/Debug/DebugCommandTest.php | 12 +++ .../device/Device/Debug/DebugGetStateTest.php | 23 ++++++ test/device/TestCase.php | 10 ++- test/unit/Bridge/SessionTest.php | 2 +- test/unit/Device/MessageTest.php | 9 +++ 26 files changed, 652 insertions(+), 86 deletions(-) create mode 100644 debug.php create mode 100644 src/Device/Button/ButtonAck.php create mode 100644 src/Device/Button/DebugButtonAck.php create mode 100644 src/Device/Button/HumanButtonAck.php create mode 100644 src/Device/Command/LoadDeviceService.php create mode 100644 src/Device/DebugMessage.php create mode 100644 src/Device/MessageBase.php create mode 100644 test/device/AbstractDeviceTest.php rename test/device/Device/{ => Command}/CommandTest.php (69%) create mode 100644 test/device/Device/Command/LoadDeviceServiceTest.php create mode 100644 test/device/Device/Command/SetupDeviceTest.php create mode 100644 test/device/Device/Command/UninitializedDeviceTest.php create mode 100644 test/device/Device/Debug/DebugCommandTest.php create mode 100644 test/device/Device/Debug/DebugGetStateTest.php diff --git a/debug.php b/debug.php new file mode 100644 index 0000000..0f973c6 --- /dev/null +++ b/debug.php @@ -0,0 +1,36 @@ +privateHdNode($depth, $fingerprint, $numChild, $chainCode, $privateKey); +$loadDevice = $reqFactory->loadDeviceWithHdNode($hdNode, $language); + +$httpClient = HttpClient::forUri("http://localhost:21325"); +$client = new Client($httpClient); +$devices = $client->listDevices()->devices(); +if (empty($devices)) { + throw new \RuntimeException("No devices returned"); +} + +$session = $client->acquire($devices[0]); +$dbgSession = $client->acquire($devices[1]); + +$dbgBtnAck = new DebugButtonAck($dbgSession); +$loadService = new LoadDeviceService($dbgBtnAck); +$loaded = $loadService->call($session, $loadDevice); +var_dump($loaded); diff --git a/src/Bridge/Client.php b/src/Bridge/Client.php index 5a130b1..561d4ac 100644 --- a/src/Bridge/Client.php +++ b/src/Bridge/Client.php @@ -12,7 +12,8 @@ use BitWasp\Trezor\Bridge\Message\VersionResponse; use BitWasp\Trezor\Bridge\Schema\ValidatorFactory; use BitWasp\Trezor\Bridge\Http\HttpClient; -use BitWasp\Trezor\Device\Message; +use BitWasp\Trezor\Device\MessageBase; +use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\ResponseInterface; class Client @@ -147,8 +148,13 @@ public function release(string $sessionId): bool return true; } - public function call(string $sessionId, Message $message): Message + public function call(string $sessionId, MessageBase $message): MessageBase { return $this->client->call($sessionId, $message); } + + public function callAsync(string $sessionId, MessageBase $message, array $headers): PromiseInterface + { + return $this->client->callAsync($sessionId, $message, $headers); + } } diff --git a/src/Bridge/Http/HttpClient.php b/src/Bridge/Http/HttpClient.php index dd47489..243ee96 100644 --- a/src/Bridge/Http/HttpClient.php +++ b/src/Bridge/Http/HttpClient.php @@ -7,8 +7,10 @@ use BitWasp\Trezor\Bridge\Codec\CallMessage; use BitWasp\Trezor\Bridge\Message\Device; use BitWasp\Trezor\Device\Message; +use BitWasp\Trezor\Device\MessageBase; use BitWasp\TrezorProto\MessageType; use GuzzleHttp\Client as GuzzleClient; +use GuzzleHttp\Psr7\Response; use Psr\Http\Message\ResponseInterface; class HttpClient @@ -100,25 +102,34 @@ public function release(string $sessionId): ResponseInterface ]); } - public function call(string $sessionId, Message $message): Message + public function call(string $sessionId, MessageBase $message): Message + { + $responsePromise = $this->callAsync($sessionId, $message); + return $responsePromise->wait(true); + } + + public function callAsync(string $sessionId, MessageBase $message, array $headers = []) { static $prefixLen; if (null === $prefixLen) { $prefixLen = strlen("MessageType_"); } - $response = $this->client->post("/call/{$sessionId}", [ + return $this->client->postAsync("/call/{$sessionId}", [ + 'headers' => $headers, 'body' => $this->callCodec->encode($message->getType(), $message->getProto()), - ]); - - list ($type, $result) = $this->callCodec->parsePayload($response->getBody()); - - $messageType = MessageType::valueOf($type); - $protoType = substr($messageType->name(), $prefixLen); - $reader = ["\\BitWasp\\TrezorProto\\{$protoType}", 'fromStream']; - assert(class_exists($reader[0])); - - $protobuf = call_user_func($reader, $result); - return new Message($messageType, $protobuf); + ]) + ->then(function (Response $response) use ($prefixLen, $message) { + echo "got response back for ({$message->getType()})"; + list ($type, $result) = $this->callCodec->parsePayload($response->getBody()); + + $messageType = MessageType::valueOf($type); + $protoType = substr($messageType->name(), $prefixLen); + $reader = ["\\BitWasp\\TrezorProto\\{$protoType}", 'fromStream']; + assert(class_exists($reader[0])); + + $protobuf = call_user_func($reader, $result); + return new Message($messageType, $protobuf); + }); } } diff --git a/src/Bridge/Session.php b/src/Bridge/Session.php index 3133327..6863c73 100644 --- a/src/Bridge/Session.php +++ b/src/Bridge/Session.php @@ -8,7 +8,9 @@ use BitWasp\Trezor\Bridge\Message\Device; use BitWasp\Trezor\Device\Exception\FailureException; use BitWasp\Trezor\Device\Message; +use BitWasp\Trezor\Device\MessageBase; use BitWasp\TrezorProto\Failure; +use GuzzleHttp\Promise\PromiseInterface; use Protobuf\Message as ProtoMessage; class Session @@ -91,22 +93,38 @@ public function getDevice(): Device { return $this->device; } - /** - * @param Message $message + * @param MessageBase $message * @return ProtoMessage * @throws FailureException * @throws InactiveSessionException */ - public function sendMessage(Message $message): ProtoMessage + public function sendMessageAsync(MessageBase $request, array $headers = []): PromiseInterface { $this->assertSessionIsActive(); - $message = $this->client->call($this->getSessionId(), $message); - $proto = $message->getProto(); - if ($proto instanceof Failure) { - FailureException::handleFailure($proto); - } + fwrite(STDERR, "(sending {$request->getType()})\n"); + return $this->client->callAsync($this->getSessionId(), $request, $headers) + ->then(function (Message $message) use ($request) { + fwrite(STDERR, "(for {$request->getType()}) got message back {$message->getType()})\n"); + $proto = $message->getProto(); + if ($proto instanceof Failure) { + fwrite(STDERR, "(failure {$request->getType()}) got message back {$message->getType()})\n"); + FailureException::handleFailure($proto); + } - return $proto; + return $proto; + }); + } + /** + * @param MessageBase $message + * @return ProtoMessage + * @throws FailureException + * @throws InactiveSessionException + */ + public function sendMessage(MessageBase $message): ProtoMessage + { + $this->assertSessionIsActive(); + return $this->sendMessageAsync($message) + ->wait(true); } } diff --git a/src/Device/Button/ButtonAck.php b/src/Device/Button/ButtonAck.php new file mode 100644 index 0000000..80efe42 --- /dev/null +++ b/src/Device/Button/ButtonAck.php @@ -0,0 +1,14 @@ +debug = $debugSession; + } + + public function acknowledge(Session $session, ButtonRequest $request, ButtonRequestType $expectedType) + { + $theirType = $request->getCode(); + if ($theirType->value() !== $expectedType->value()) { + throw new \RuntimeException("Unexpected button request (expected: {$expectedType->name()}, got {$theirType->name()})"); + } + + fwrite(STDERR, microtime() . " - debugButtonAck.sending button ack (async)\n"); + $t1 = microtime(true); + $ack = new \BitWasp\TrezorProto\ButtonAck(); + + $decision = new DebugLinkDecision(); + $decision->setYesNo(true); + + fwrite(STDERR, microtime() . " - debugButtonAck.sending DECISION (async)\n"); + $t1 = microtime(true); + + $success = $session->sendMessageAsync(Message::buttonAck($ack)); + $debug = $this->debug->sendMessageAsync(DebugMessage::decision($decision), [ + 'Connection' => 'close', + ]); + + fwrite(STDERR, microtime() . " - debugButtonAck.DECISION async took ".(microtime(true)-$t1).PHP_EOL); + + fwrite(STDERR, "create promise"); + $val = null; + $success->then(function (Success $success) use (&$val) { + fwrite(STDERR, "success resolved"); + $val = $success; + }); + fwrite(STDERR, "wait for success"); + $success->wait(true); + fwrite(STDERR, "DONE waiting"); + + return $val; + } +} diff --git a/src/Device/Button/HumanButtonAck.php b/src/Device/Button/HumanButtonAck.php new file mode 100644 index 0000000..3a7845d --- /dev/null +++ b/src/Device/Button/HumanButtonAck.php @@ -0,0 +1,24 @@ +getCode(); + if ($theirType->value() !== $expectedType->value()) { + throw new \RuntimeException("Unexpected button request (expected: {$expectedType->name()}, got {$theirType->name()})"); + } + + echo "sending button ack\n"; + return $session->sendMessage(Message::buttonAck(new \BitWasp\TrezorProto\ButtonAck())); + } +} diff --git a/src/Device/Command/DeviceService.php b/src/Device/Command/DeviceService.php index 0ee36ee..9f03558 100644 --- a/src/Device/Command/DeviceService.php +++ b/src/Device/Command/DeviceService.php @@ -44,7 +44,6 @@ protected function provideCurrentPin(PinMatrixRequest $proto, CurrentPinInputInt return Message::pinMatrixAck($pinMatrixAck); } - protected function provideCurrentPassphrase(CurrentPassphraseInputInterface $passphraseInput): Message { $passphraseAck = new PassphraseAck(); diff --git a/src/Device/Command/LoadDeviceService.php b/src/Device/Command/LoadDeviceService.php new file mode 100644 index 0000000..80a665a --- /dev/null +++ b/src/Device/Command/LoadDeviceService.php @@ -0,0 +1,43 @@ +ack = $buttonAck; + } + + public function call( + Session $session, + TrezorProto\LoadDevice $loadDevice + ): TrezorProto\Success { + + fwrite(STDERR, "loadService.sending load device\n"); + $proto = $session->sendMessage(Message::loadDevice($loadDevice)); + fwrite(STDERR, "loadService.response for load device\n"); + + if ($proto instanceof TrezorProto\ButtonRequest) { + fwrite(STDERR, "loadService.send button ack\n"); + $proto = $this->ack->acknowledge($session, $proto, TrezorProto\ButtonRequestType::ButtonRequest_ProtectCall()); + fwrite(STDERR, "loadService.response for ack device\n"); + } + + if (!($proto instanceof TrezorProto\Success)) { + throw new UnexpectedResultException("Unexpected response, expecting Success, got " . get_class($proto)); + } + fwrite(STDERR, "done\n"); + return $proto; + } +} diff --git a/src/Device/DebugMessage.php b/src/Device/DebugMessage.php new file mode 100644 index 0000000..5b0e5fe --- /dev/null +++ b/src/Device/DebugMessage.php @@ -0,0 +1,44 @@ +type = $messageType; - $this->proto = $protobuf; - } - - public function getType(): int - { - return $this->type->value(); - } - - public function getProto(): \Protobuf\Message - { - return $this->proto; - } - public static function getPublicKey(GetPublicKey $getPublicKey): self { return new self( @@ -132,4 +107,12 @@ public static function clearSession(ClearSession $clear): self $clear ); } + + public static function loadDevice(LoadDevice $clear): self + { + return new self( + MessageType::MessageType_LoadDevice(), + $clear + ); + } } diff --git a/src/Device/MessageBase.php b/src/Device/MessageBase.php new file mode 100644 index 0000000..b9cd40a --- /dev/null +++ b/src/Device/MessageBase.php @@ -0,0 +1,38 @@ +type = $messageType; + $this->proto = $protobuf; + } + + public function getType(): int + { + return $this->type->value(); + } + + public function getProto(): \Protobuf\Message + { + return $this->proto; + } +} diff --git a/src/Device/RequestFactory.php b/src/Device/RequestFactory.php index dbd7a3c..5ffb19e 100644 --- a/src/Device/RequestFactory.php +++ b/src/Device/RequestFactory.php @@ -8,8 +8,10 @@ use BitWasp\TrezorProto\GetAddress; use BitWasp\TrezorProto\GetEntropy; use BitWasp\TrezorProto\GetPublicKey; +use BitWasp\TrezorProto\HDNodeType; use BitWasp\TrezorProto\Initialize; use BitWasp\TrezorProto\InputScriptType; +use BitWasp\TrezorProto\LoadDevice; use BitWasp\TrezorProto\Ping; use BitWasp\TrezorProto\SignMessage; use BitWasp\TrezorProto\VerifyMessage; @@ -111,4 +113,78 @@ public function clearSession(): ClearSession { return new ClearSession(); } + + private function prepareLoadDevice( + bool $skipChecksum, + bool $usePassphrase, + string $language = null, + int $u2fCounter = null, + string $pin = null, + string $label = null + ): LoadDevice { + $loadDevice = new LoadDevice(); + $loadDevice->setSkipChecksum($skipChecksum); + $loadDevice->setPassphraseProtection($usePassphrase); + if (is_string($language)) { + $loadDevice->setLanguage($language); + } + if (is_string($pin)) { + $loadDevice->setPin($pin); + } + if (is_string($label)) { + $loadDevice->setLabel($label); + } + if (is_int($u2fCounter)) { + $loadDevice->setU2fCounter($u2fCounter); + } + return $loadDevice; + } + + public function loadDeviceWithHdNode( + HDNodeType $hdNode, + string $language, + string $label = null, + string $pin = null, + bool $usePassphrase = false, + bool $skipChecksum = false, + int $u2fCounter = null + ): LoadDevice { + $loadDevice = $this->prepareLoadDevice($skipChecksum, $usePassphrase, $language, $u2fCounter, $pin, $label); + $loadDevice->setNode($hdNode); + return $loadDevice; + } + + public function loadDeviceWithMnemonic( + string $mnemonic, + string $language = null, + string $label = null, + string $pin = null, + bool $usePassphrase = false, + bool $skipChecksum = false, + int $u2fCounter = null + ): LoadDevice { + $loadDevice = $this->prepareLoadDevice($skipChecksum, $usePassphrase, $language, $u2fCounter, $pin, $label); + $loadDevice->setMnemonic($mnemonic); + return $loadDevice; + } + public function privateHdNode(int $depth, int $fingerprint, int $childNum, \Protobuf\Stream $chainCode, \Protobuf\Stream $privateKey): HDNodeType + { + $hdNode = new HDNodeType(); + $hdNode->setDepth($depth); + $hdNode->setFingerprint($fingerprint); + $hdNode->setChildNum($childNum); + $hdNode->setChainCode($chainCode); + $hdNode->setPrivateKey($privateKey); + return $hdNode; + } + public function publicHdNode(int $depth, int $fingerprint, int $childNum, \Protobuf\Stream $chainCode, \Protobuf\Stream $publicKey): HDNodeType + { + $hdNode = new HDNodeType(); + $hdNode->setDepth($depth); + $hdNode->setFingerprint($fingerprint); + $hdNode->setChildNum($childNum); + $hdNode->setChainCode($chainCode); + $hdNode->setPublicKey($publicKey); + return $hdNode; + } } diff --git a/test/device/AbstractDeviceTest.php b/test/device/AbstractDeviceTest.php new file mode 100644 index 0000000..2c51427 --- /dev/null +++ b/test/device/AbstractDeviceTest.php @@ -0,0 +1,56 @@ +httpClient = HttpClient::forUri("http://localhost:21325"); + $this->client = new Client($this->httpClient); + $devices = $this->client->listDevices()->devices(); + if (empty($devices)) { + throw new \RuntimeException("No devices returned"); + } + + foreach ($devices as $device) { + if ($device->getPath() === $this->targetDevice) { + $this->session = $this->client->acquire($device); + return; + } + } + + throw new \RuntimeException("Failed to find target device"); + } +} diff --git a/test/device/AcquireDeviceTest.php b/test/device/AcquireDeviceTest.php index 3947874..869cd67 100644 --- a/test/device/AcquireDeviceTest.php +++ b/test/device/AcquireDeviceTest.php @@ -19,10 +19,14 @@ public function testBridge() $httpClient = HttpClient::forUri("http://localhost:21325"); $client = new Client($httpClient); $devices = $client->listDevices(); - $this->assertCount(1, $devices); + + $this->assertCount(2, $devices); $this->assertEquals("emulator21324", $devices->devices()[0]->getPath()); $this->assertEquals(null, $devices->devices()[0]->getSession()); + $this->assertEquals("emulator21325", $devices->devices()[1]->getPath()); + $this->assertEquals(null, $devices->devices()[01]->getSession()); + $session = $client->acquire($devices->devices()[0]); $ping = new PingService(); @@ -33,14 +37,14 @@ public function testBridge() $this->assertEquals('abc', $result->getMessage()); $devices = $client->listDevices(); - $this->assertCount(1, $devices); + $this->assertCount(2, $devices); $this->assertEquals("emulator21324", $devices->devices()[0]->getPath()); $this->assertEquals($session->getSessionId(), $devices->devices()[0]->getSession()); $session->release(); $devices = $client->listDevices(); - $this->assertCount(1, $devices); + $this->assertCount(2, $devices); $this->assertEquals("emulator21324", $devices->devices()[0]->getPath()); $this->assertEquals(null, $devices->devices()[0]->getSession()); } diff --git a/test/device/Bridge/ClientTest.php b/test/device/Bridge/ClientTest.php index 9555a71..10b7146 100644 --- a/test/device/Bridge/ClientTest.php +++ b/test/device/Bridge/ClientTest.php @@ -36,7 +36,7 @@ public function testBridgeVersion() public function testAcquireAndRelease() { $devices = $this->client->listDevices(); - $this->assertCount(1, $devices); + $this->assertCount(2, $devices); $this->assertEquals("emulator21324", $devices->devices()[0]->getPath()); $this->assertEquals(null, $devices->devices()[0]->getSession()); @@ -47,7 +47,7 @@ public function testAcquireAndRelease() $this->assertFalse($session->isActive()); $devices = $this->client->listDevices(); - $this->assertCount(1, $devices); + $this->assertCount(2, $devices); $this->assertEquals("emulator21324", $devices->devices()[0]->getPath()); $this->assertEquals(null, $devices->devices()[0]->getSession()); } diff --git a/test/device/Device/CommandTest.php b/test/device/Device/Command/CommandTest.php similarity index 69% rename from test/device/Device/CommandTest.php rename to test/device/Device/Command/CommandTest.php index 0732e5b..e38c5fd 100644 --- a/test/device/Device/CommandTest.php +++ b/test/device/Device/Command/CommandTest.php @@ -2,11 +2,12 @@ declare(strict_types=1); -namespace BitWasp\Test\Trezor\Device\Device; +namespace BitWasp\Test\Trezor\Device\Device\Command; use BitWasp\Test\Trezor\Device\TestCase; use BitWasp\Trezor\Bridge\Client; use BitWasp\Trezor\Bridge\Http\HttpClient; +use BitWasp\Trezor\Bridge\Message\Device; use BitWasp\Trezor\Bridge\Session; abstract class CommandTest extends TestCase @@ -26,17 +27,22 @@ abstract class CommandTest extends TestCase */ protected $session; + /** + * @var Device[] + */ + protected $devices; + public function setUp() { parent::setUp(); // TODO: Change the autogenerated stub $this->httpClient = HttpClient::forUri("http://localhost:21325"); $this->client = new Client($this->httpClient); - $devices = $this->client->listDevices()->devices(); - if (empty($devices)) { + $this->devices = $this->client->listDevices()->devices(); + if (empty($this->devices)) { throw new \RuntimeException("No devices returned"); } - $this->session = $this->client->acquire($devices[0]); + $this->session = $this->client->acquire($this->devices[0]); } } diff --git a/test/device/Device/Command/InitializeServiceTest.php b/test/device/Device/Command/InitializeServiceTest.php index 414cef3..5412cae 100644 --- a/test/device/Device/Command/InitializeServiceTest.php +++ b/test/device/Device/Command/InitializeServiceTest.php @@ -4,13 +4,7 @@ namespace BitWasp\Test\Trezor\Device\Device\Command; -use BitWasp\Test\Trezor\Device\Device\CommandTest; -use BitWasp\Trezor\Device\Command\GetAddressService; use BitWasp\Trezor\Device\Command\InitializeService; -use BitWasp\Trezor\Device\Exception\Failure\NotInitializedException; -use BitWasp\Trezor\Device\RequestFactory; -use BitWasp\Trezor\Device\UserInput\CurrentPinInput; -use BitWasp\Trezor\Device\UserInput\DisabledUserInputRequest; use BitWasp\TrezorProto\Features; use BitWasp\TrezorProto\Initialize; @@ -25,19 +19,4 @@ public function testInitialize() $this->assertEquals("bitcointrezor.com", $features->getVendor()); $this->assertFalse($features->getInitialized()); } - - public function testUninitializedDevice() - { - $path = [44|0x80000000, 0|0x80000000, 0|0x80000000, 0, 0]; - - $reqFactory = new RequestFactory(); - $getAddress = $reqFactory->getAddress('Bitcoin', $path, InputScriptType::SPENDADDRESS(), false); - - $getAddressService = new GetAddressService(); - $pinInput = new CurrentPinInput(new DisabledUserInputRequest()); - - $this->expectException(NotInitializedException::class); - - $getAddressService->call($this->session, $pinInput, $getAddress); - } } diff --git a/test/device/Device/Command/LoadDeviceServiceTest.php b/test/device/Device/Command/LoadDeviceServiceTest.php new file mode 100644 index 0000000..f8aa579 --- /dev/null +++ b/test/device/Device/Command/LoadDeviceServiceTest.php @@ -0,0 +1,58 @@ +loadDeviceWithMnemonic($mnemonic, $language); + + $loadDeviceService = new LoadDeviceService(); + $success = $loadDeviceService->call($this->session, $getAddress); + }*/ + + public function testLoadWithHdNode() + { + $depth = 0; + $fingerprint = 0; + $numChild = 0; + $chainCode = \Protobuf\Stream::fromString(hex2bin('a86d0945bd342199a130b65255df75199fe09e539d60053003cc1c0e999982a5')); + $privateKey = \Protobuf\Stream::fromString(hex2bin('874c62f2c98f7c94f1a691492825a71e8e9b9251f03c208f37d1ec9c9cda2b24')); + $language = "EN"; + + $reqFactory = new RequestFactory(); + $hdNode = $reqFactory->privateHdNode($depth, $fingerprint, $numChild, $chainCode, $privateKey); + $loadDevice = $reqFactory->loadDeviceWithHdNode($hdNode, $language); + $debugSession = $this->client->acquire($this->devices[1]); + + $initService = new InitializeService(); + $features = $initService->call($this->session, new Initialize()); + + $buttonAck = new DebugButtonAck($debugSession); + $loadDeviceService = new LoadDeviceService($buttonAck); + + fwrite(STDERR, "firing load service\n"); + $l1 = microtime(true); + $success = $loadDeviceService->call($this->session, $loadDevice); + $this->assertInstanceOf(Success::class, $success); + + $stop = new DebugLinkStop(); + $debugSession->sendMessageAsync(DebugMessage::stop($stop)); + } +} diff --git a/test/device/Device/Command/SetupDeviceTest.php b/test/device/Device/Command/SetupDeviceTest.php new file mode 100644 index 0000000..8fd82f3 --- /dev/null +++ b/test/device/Device/Command/SetupDeviceTest.php @@ -0,0 +1,30 @@ +privateHdNode($depth, $fingerprint, $numChild, $chainCode, $privateKey); + $loadDevice = $reqFactory->loadDeviceWithHdNode($hdNode, $language); + + $loadDeviceService = new LoadDeviceService(); + $success = $loadDeviceService->call($this->session, $loadDevice); + $this->assertInstanceOf(Success::class, $success); + } +} diff --git a/test/device/Device/Command/UninitializedDeviceTest.php b/test/device/Device/Command/UninitializedDeviceTest.php new file mode 100644 index 0000000..dc8236e --- /dev/null +++ b/test/device/Device/Command/UninitializedDeviceTest.php @@ -0,0 +1,31 @@ +getAddress('Bitcoin', $path, InputScriptType::SPENDADDRESS(), false); + + $getAddressService = new GetAddressService(); + $pinInput = new CurrentPinInput(new DisabledUserInputRequest()); + + $this->expectException(NotInitializedException::class); + + $getAddressService->call($this->session, $pinInput, $getAddress); + } +} diff --git a/test/device/Device/Debug/DebugCommandTest.php b/test/device/Device/Debug/DebugCommandTest.php new file mode 100644 index 0000000..5c6173e --- /dev/null +++ b/test/device/Device/Debug/DebugCommandTest.php @@ -0,0 +1,12 @@ +session->sendMessage(DebugMessage::getState($getState)); + $this->assertInstanceOf(DebugLinkState::class, $state); + /** @var DebugLinkState $state */ + $this->assertNull($state->getPin()); + $this->assertFalse($state->getPassphraseProtection()); + $this->assertFalse($state->getPassphraseProtection()); + } +} diff --git a/test/device/TestCase.php b/test/device/TestCase.php index 8555c9d..f8f0891 100644 --- a/test/device/TestCase.php +++ b/test/device/TestCase.php @@ -23,6 +23,11 @@ public function getRootPath(): string return __DIR__ . "/../../"; } + public function getStateFile(): string + { + return "{$this->getRootPath()}/emulator.img"; + } + public function getEmulatorPath(): string { $path = getenv("EMULATOR_PATH"); @@ -35,14 +40,12 @@ public function getEmulatorPath(): string public function getEmulatorStartCommand(): string { return $this->getEmulatorPath() . - /* . " > /dev/null" . */ " > 1 & echo $! ; "; } public function getBridgeStartCommand(): string { return $this->getBridgePath() . - /* . " > /dev/null" . */ - " -u=false -e 21324 -l /tmp/trezor-bridge > 1 & echo $! ; "; + " -u=false -e 21324 -e 21325 -l /tmp/trezor-bridge > 1 & echo $! ; "; } public function getBridgePath(): string { @@ -73,5 +76,6 @@ public function tearDown() { exec("kill -9 {$this->emu}"); exec("kill -9 {$this->bridge}"); + unlink($this->getStateFile()); } } diff --git a/test/unit/Bridge/SessionTest.php b/test/unit/Bridge/SessionTest.php index 0fff9db..b01ce6c 100644 --- a/test/unit/Bridge/SessionTest.php +++ b/test/unit/Bridge/SessionTest.php @@ -9,6 +9,7 @@ use BitWasp\Trezor\Bridge\Exception\InactiveSessionException; use BitWasp\Trezor\Device\Exception\Failure\ActionCancelledException; use BitWasp\Trezor\Device\Message; +use BitWasp\Trezor\Device\MessageBase; use BitWasp\TrezorProto\Failure; use BitWasp\TrezorProto\FailureType; use BitWasp\TrezorProto\Features; @@ -18,7 +19,6 @@ use BitWasp\TrezorProto\MessageType; use BitWasp\TrezorProto\PublicKey; use GuzzleHttp\Psr7\Response; - use BitWasp\Test\Trezor\TestCase; use BitWasp\Trezor\Bridge\Client; use BitWasp\Trezor\Bridge\Http\HttpClient; diff --git a/test/unit/Device/MessageTest.php b/test/unit/Device/MessageTest.php index 268bf3e..ccdef87 100644 --- a/test/unit/Device/MessageTest.php +++ b/test/unit/Device/MessageTest.php @@ -12,6 +12,7 @@ use BitWasp\TrezorProto\GetEntropy; use BitWasp\TrezorProto\GetPublicKey; use BitWasp\TrezorProto\Initialize; +use BitWasp\TrezorProto\LoadDevice; use BitWasp\TrezorProto\MessageType; use BitWasp\TrezorProto\PassphraseAck; use BitWasp\TrezorProto\Ping; @@ -108,4 +109,12 @@ public function testVerifyMessage() $this->assertSame($m, $msg->getProto()); $this->assertEquals(MessageType::MessageType_VerifyMessage()->value(), $msg->getType()); } + + public function testLoadDevice() + { + $m = new LoadDevice(); + $msg = Message::loadDevice($m); + $this->assertSame($m, $msg->getProto()); + $this->assertEquals(MessageType::MessageType_LoadDevice()->value(), $msg->getType()); + } }