Skip to content

Commit b554549

Browse files
committed
bip85: restructure api messages to allow for different bip85 apps
For now the same app as before is supported - bip39, but explicit. The empty message now returns InvalidInput - would have been a breaking change but the BIP85 API endpoint was never released (disabled by not activating the app-bip85 Rust feature). Reason: we want to add another dedicated app number for the generation of deterministic entropy for the Breez SDK Lightning hot wallet in the BitBoxApp. This will segregate keys so that BIP85-BIP39 mnemonics which the user already might use (or will use) are not unintentionally re-used and made hot in the Lightning wallet.
1 parent 1bcb6dd commit b554549

File tree

8 files changed

+87
-22
lines changed

8 files changed

+87
-22
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ endif()
8888
#
8989
# Versions MUST contain three parts and start with lowercase 'v'.
9090
# Example 'v1.0.0'. They MUST not contain a pre-release label such as '-beta'.
91-
set(FIRMWARE_VERSION "v9.16.0")
92-
set(FIRMWARE_BTC_ONLY_VERSION "v9.16.0")
91+
set(FIRMWARE_VERSION "v9.17.0")
92+
set(FIRMWARE_BTC_ONLY_VERSION "v9.17.0")
9393
set(BOOTLOADER_VERSION "v1.0.5")
9494

9595
find_package(PythonInterp 3.6 REQUIRED)

messages/keystore.proto

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
syntax = "proto3";
55
package shiftcrypto.bitbox02;
66

7+
import "google/protobuf/empty.proto";
8+
79
message ElectrumEncryptionKeyRequest {
810
repeated uint32 keypath = 1;
911
}
@@ -13,7 +15,13 @@ message ElectrumEncryptionKeyResponse {
1315
}
1416

1517
message BIP85Request {
18+
oneof app {
19+
google.protobuf.Empty bip39 = 1;
20+
}
1621
}
1722

1823
message BIP85Response {
24+
oneof app {
25+
google.protobuf.Empty bip39 = 1;
26+
}
1927
}

py/bitbox02/bitbox02/bitbox02/bitbox02.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
from bitbox02.communication.generated import common_pb2 as common
4444
from bitbox02.communication.generated import keystore_pb2 as keystore
4545
from bitbox02.communication.generated import antiklepto_pb2 as antiklepto
46+
import google.protobuf.empty_pb2
4647

4748
# pylint: disable=unused-import
4849
# We export it in __init__.py
@@ -678,13 +679,17 @@ def electrum_encryption_key(self, keypath: Sequence[int]) -> str:
678679
)
679680
return self._msg_query(request).electrum_encryption_key.key
680681

681-
def bip85(self) -> None:
682-
"""Invokes the BIP-85 workflow on the device"""
683-
self._require_atleast(semver.VersionInfo(9, 16, 0))
682+
def bip85_bip39(self) -> None:
683+
"""Invokes the BIP85-BIP39 workflow on the device"""
684+
self._require_atleast(semver.VersionInfo(9, 17, 0))
684685

685686
# pylint: disable=no-member
686687
request = hww.Request()
687-
request.bip85.CopyFrom(keystore.BIP85Request())
688+
request.bip85.CopyFrom(
689+
keystore.BIP85Request(
690+
bip39=google.protobuf.empty_pb2.Empty(),
691+
)
692+
)
688693
self._msg_query(request)
689694

690695
def enable_mnemonic_passphrase(self) -> None:

py/bitbox02/bitbox02/communication/generated/keystore_pb2.py

Lines changed: 10 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

py/bitbox02/bitbox02/communication/generated/keystore_pb2.pyi

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ isort:skip_file
44
"""
55
import builtins
66
import google.protobuf.descriptor
7+
import google.protobuf.empty_pb2
78
import google.protobuf.internal.containers
89
import google.protobuf.message
910
import typing
@@ -36,12 +37,28 @@ global___ElectrumEncryptionKeyResponse = ElectrumEncryptionKeyResponse
3637

3738
class BIP85Request(google.protobuf.message.Message):
3839
DESCRIPTOR: google.protobuf.descriptor.Descriptor
40+
BIP39_FIELD_NUMBER: builtins.int
41+
@property
42+
def bip39(self) -> google.protobuf.empty_pb2.Empty: ...
3943
def __init__(self,
44+
*,
45+
bip39: typing.Optional[google.protobuf.empty_pb2.Empty] = ...,
4046
) -> None: ...
47+
def HasField(self, field_name: typing_extensions.Literal["app",b"app","bip39",b"bip39"]) -> builtins.bool: ...
48+
def ClearField(self, field_name: typing_extensions.Literal["app",b"app","bip39",b"bip39"]) -> None: ...
49+
def WhichOneof(self, oneof_group: typing_extensions.Literal["app",b"app"]) -> typing.Optional[typing_extensions.Literal["bip39"]]: ...
4150
global___BIP85Request = BIP85Request
4251

4352
class BIP85Response(google.protobuf.message.Message):
4453
DESCRIPTOR: google.protobuf.descriptor.Descriptor
54+
BIP39_FIELD_NUMBER: builtins.int
55+
@property
56+
def bip39(self) -> google.protobuf.empty_pb2.Empty: ...
4557
def __init__(self,
58+
*,
59+
bip39: typing.Optional[google.protobuf.empty_pb2.Empty] = ...,
4660
) -> None: ...
61+
def HasField(self, field_name: typing_extensions.Literal["app",b"app","bip39",b"bip39"]) -> builtins.bool: ...
62+
def ClearField(self, field_name: typing_extensions.Literal["app",b"app","bip39",b"bip39"]) -> None: ...
63+
def WhichOneof(self, oneof_group: typing_extensions.Literal["app",b"app"]) -> typing.Optional[typing_extensions.Literal["bip39"]]: ...
4764
global___BIP85Response = BIP85Response

py/send_message.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -340,8 +340,8 @@ def _get_electrum_encryption_key(self) -> None:
340340
),
341341
)
342342

343-
def _bip85(self) -> None:
344-
self._device.bip85()
343+
def _bip85_bip39(self) -> None:
344+
self._device.bip85_bip39()
345345

346346
def _btc_address(self) -> None:
347347
def address(display: bool) -> str:
@@ -1391,7 +1391,7 @@ def _menu_init(self) -> None:
13911391
("Sign Ethereum Typed Message (EIP-712)", self._sign_eth_typed_message),
13921392
("Cardano", self._cardano),
13931393
("Show Electrum wallet encryption key", self._get_electrum_encryption_key),
1394-
("BIP85", self._bip85),
1394+
("BIP85 - BIP39", self._bip85_bip39),
13951395
("Reset Device", self._reset_device),
13961396
)
13971397
choice = ask_user(choices)

src/rust/bitbox02-rust/src/hww/api/bip85.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,19 @@ use crate::workflow::{confirm, menu, mnemonic, status, trinary_input_string};
2424

2525
use alloc::vec::Vec;
2626

27+
/// Processes a BIP-85 API call.
28+
pub async fn process(request: &pb::Bip85Request) -> Result<Response, Error> {
29+
match request.app {
30+
None => Err(Error::InvalidInput),
31+
Some(pb::bip85_request::App::Bip39(())) => Ok(Response::Bip85(pb::Bip85Response {
32+
app: Some(pb::bip85_response::App::Bip39(process_bip39().await?)),
33+
})),
34+
}
35+
}
36+
2737
/// Derives and displays a BIP-39 seed according to BIP-85:
2838
/// https://github.com/bitcoin/bips/blob/master/bip-0085.mediawiki#bip39.
29-
pub async fn process(pb::Bip85Request {}: &pb::Bip85Request) -> Result<Response, Error> {
39+
async fn process_bip39() -> Result<(), Error> {
3040
confirm::confirm(&confirm::Params {
3141
title: "BIP-85",
3242
body: "Derive BIP-39\nmnemonic?",
@@ -104,5 +114,5 @@ pub async fn process(pb::Bip85Request {}: &pb::Bip85Request) -> Result<Response,
104114

105115
status::status("Finished", true).await;
106116

107-
Ok(Response::Bip85(pb::Bip85Response {}))
117+
Ok(())
108118
}

src/rust/bitbox02-rust/src/shiftcrypto.bitbox02.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,10 +1512,34 @@ pub struct ElectrumEncryptionKeyResponse {
15121512
}
15131513
#[allow(clippy::derive_partial_eq_without_eq)]
15141514
#[derive(Clone, PartialEq, ::prost::Message)]
1515-
pub struct Bip85Request {}
1515+
pub struct Bip85Request {
1516+
#[prost(oneof = "bip85_request::App", tags = "1")]
1517+
pub app: ::core::option::Option<bip85_request::App>,
1518+
}
1519+
/// Nested message and enum types in `BIP85Request`.
1520+
pub mod bip85_request {
1521+
#[allow(clippy::derive_partial_eq_without_eq)]
1522+
#[derive(Clone, PartialEq, ::prost::Oneof)]
1523+
pub enum App {
1524+
#[prost(message, tag = "1")]
1525+
Bip39(()),
1526+
}
1527+
}
15161528
#[allow(clippy::derive_partial_eq_without_eq)]
15171529
#[derive(Clone, PartialEq, ::prost::Message)]
1518-
pub struct Bip85Response {}
1530+
pub struct Bip85Response {
1531+
#[prost(oneof = "bip85_response::App", tags = "1")]
1532+
pub app: ::core::option::Option<bip85_response::App>,
1533+
}
1534+
/// Nested message and enum types in `BIP85Response`.
1535+
pub mod bip85_response {
1536+
#[allow(clippy::derive_partial_eq_without_eq)]
1537+
#[derive(Clone, PartialEq, ::prost::Oneof)]
1538+
pub enum App {
1539+
#[prost(message, tag = "1")]
1540+
Bip39(()),
1541+
}
1542+
}
15191543
#[allow(clippy::derive_partial_eq_without_eq)]
15201544
#[derive(Clone, PartialEq, ::prost::Message)]
15211545
pub struct ShowMnemonicRequest {}

0 commit comments

Comments
 (0)