mirror of
https://github.com/monero-project/monero.git
synced 2025-08-11 22:00:20 -04:00
Merge pull request #8752
c444a7e
trezor: support v2.5.2+, add more trezor tests, fix chaingen and tests (Dusan Klinec)056c996
fix chaingen tests (Dusan Klinec)
This commit is contained in:
commit
8f0343df16
41 changed files with 1221 additions and 738 deletions
|
@ -65,12 +65,16 @@ set(trezor_private_headers)
|
|||
|
||||
# Protobuf and LibUSB processed by CheckTrezor
|
||||
if(DEVICE_TREZOR_READY)
|
||||
message(STATUS "Trezor support enabled")
|
||||
message(STATUS "Trezor: support enabled")
|
||||
|
||||
if(USE_DEVICE_TREZOR_DEBUG)
|
||||
list(APPEND trezor_headers trezor/debug_link.hpp trezor/messages/messages-debug.pb.h)
|
||||
list(APPEND trezor_sources trezor/debug_link.cpp trezor/messages/messages-debug.pb.cc)
|
||||
message(STATUS "Trezor debugging enabled")
|
||||
message(STATUS "Trezor: debugging enabled")
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
set(TREZOR_EXTRA_LIBRARIES "log")
|
||||
endif()
|
||||
|
||||
monero_private_headers(device_trezor
|
||||
|
@ -93,10 +97,11 @@ if(DEVICE_TREZOR_READY)
|
|||
${Protobuf_LIBRARY}
|
||||
${TREZOR_LIBUSB_LIBRARIES}
|
||||
PRIVATE
|
||||
${EXTRA_LIBRARIES})
|
||||
${EXTRA_LIBRARIES}
|
||||
${TREZOR_EXTRA_LIBRARIES})
|
||||
|
||||
else()
|
||||
message(STATUS "Trezor support disabled")
|
||||
message(STATUS "Trezor: support disabled")
|
||||
monero_private_headers(device_trezor)
|
||||
monero_add_library(device_trezor device_trezor.cpp)
|
||||
target_link_libraries(device_trezor PUBLIC cncrypto)
|
||||
|
|
74
src/device_trezor/README.md
Normal file
74
src/device_trezor/README.md
Normal file
|
@ -0,0 +1,74 @@
|
|||
# Trezor hardware wallet support
|
||||
|
||||
This module adds [Trezor] hardware support to Monero.
|
||||
|
||||
|
||||
## Basic information
|
||||
|
||||
Trezor integration is based on the following original proposal: https://github.com/ph4r05/monero-trezor-doc
|
||||
|
||||
A custom high-level transaction signing protocol uses Trezor in a similar way a cold wallet is used.
|
||||
Transaction is build incrementally on the device.
|
||||
|
||||
Trezor implements the signing protocol in [trezor-firmware] repository, in the [monero](https://github.com/trezor/trezor-firmware/tree/master/core/src/apps/monero) application.
|
||||
Please, refer to [monero readme](https://github.com/trezor/trezor-firmware/blob/master/core/src/apps/monero/README.md) for more information.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Trezor uses [Protobuf](https://protobuf.dev/) library. As Monero is compiled with C++14, the newest Protobuf library version cannot be compiled because it requires C++17 (through its dependency Abseil library).
|
||||
This can result in a compilation failure.
|
||||
|
||||
Protobuf v21 is the latest compatible protobuf version.
|
||||
|
||||
If you want to compile Monero with Trezor support, please make sure the Protobuf v21 is installed.
|
||||
|
||||
More about this limitation: [PR #8752](https://github.com/monero-project/monero/pull/8752),
|
||||
[1](https://github.com/monero-project/monero/pull/8752#discussion_r1246174755), [2](https://github.com/monero-project/monero/pull/8752#discussion_r1246480393)
|
||||
|
||||
### OSX
|
||||
|
||||
To build with installed, but not linked protobuf:
|
||||
|
||||
```bash
|
||||
CMAKE_PREFIX_PATH=$(find /opt/homebrew/Cellar/protobuf@21 -maxdepth 1 -type d -name "21.*" -print -quit) \
|
||||
make release
|
||||
```
|
||||
|
||||
or to install and link as a default protobuf version:
|
||||
```bash
|
||||
# Either install all requirements as
|
||||
brew update && brew bundle --file=contrib/brew/Brewfile
|
||||
|
||||
# or install protobufv21 specifically
|
||||
brew install protobuf@21 && brew link protobuf@21
|
||||
```
|
||||
|
||||
### MSYS32
|
||||
|
||||
```bash
|
||||
curl -O https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-protobuf-c-1.4.1-1-any.pkg.tar.zst
|
||||
curl -O https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-protobuf-21.9-1-any.pkg.tar.zst
|
||||
pacman --noconfirm -U mingw-w64-x86_64-protobuf-c-1.4.1-1-any.pkg.tar.zst mingw-w64-x86_64-protobuf-21.9-1-any.pkg.tar.zst
|
||||
```
|
||||
|
||||
### Other systems
|
||||
|
||||
- install protobufv21
|
||||
- point `CMAKE_PREFIX_PATH` environment variable to Protobuf v21 installation.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
To disable Trezor support, set `USE_DEVICE_TREZOR=OFF`, e.g.:
|
||||
|
||||
```shell
|
||||
USE_DEVICE_TREZOR=OFF make release
|
||||
```
|
||||
|
||||
## Resources:
|
||||
|
||||
- First pull request https://github.com/monero-project/monero/pull/4241
|
||||
- Integration proposal https://github.com/ph4r05/monero-trezor-doc
|
||||
- Integration readme in trezor-firmware https://github.com/trezor/trezor-firmware/blob/master/core/src/apps/monero/README.md
|
||||
|
||||
[Trezor]: https://trezor.io/
|
||||
[trezor-firmware]: https://github.com/trezor/trezor-firmware/
|
|
@ -165,7 +165,7 @@ namespace trezor {
|
|||
auto res = get_address();
|
||||
|
||||
cryptonote::address_parse_info info{};
|
||||
bool r = cryptonote::get_account_address_from_str(info, this->network_type, res->address());
|
||||
bool r = cryptonote::get_account_address_from_str(info, this->m_network_type, res->address());
|
||||
CHECK_AND_ASSERT_MES(r, false, "Could not parse returned address. Address parse failed: " + res->address());
|
||||
CHECK_AND_ASSERT_MES(!info.is_subaddress, false, "Trezor returned a sub address");
|
||||
|
||||
|
@ -693,14 +693,11 @@ namespace trezor {
|
|||
unsigned device_trezor::client_version()
|
||||
{
|
||||
auto trezor_version = get_version();
|
||||
if (trezor_version < pack_version(2, 4, 3)){
|
||||
throw exc::TrezorException("Minimal Trezor firmware version is 2.4.3. Please update.");
|
||||
if (trezor_version < pack_version(2, 5, 2)){
|
||||
throw exc::TrezorException("Minimal Trezor firmware version is 2.5.2. Please update.");
|
||||
}
|
||||
|
||||
unsigned client_version = 3;
|
||||
if (trezor_version >= pack_version(2, 5, 2)){
|
||||
client_version = 4;
|
||||
}
|
||||
unsigned client_version = 4; // since 2.5.2
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
// Override client version for tests
|
||||
|
|
|
@ -102,7 +102,7 @@ namespace trezor {
|
|||
|
||||
bool has_ki_cold_sync() const override { return true; }
|
||||
bool has_tx_cold_sign() const override { return true; }
|
||||
void set_network_type(cryptonote::network_type network_type) override { this->network_type = network_type; }
|
||||
void set_network_type(cryptonote::network_type network_type) override { this->m_network_type = network_type; }
|
||||
void set_live_refresh_enabled(bool enabled) { m_live_refresh_enabled = enabled; }
|
||||
bool live_refresh_enabled() const { return m_live_refresh_enabled; }
|
||||
|
||||
|
|
|
@ -300,9 +300,6 @@ namespace trezor {
|
|||
case messages::MessageType_PassphraseRequest:
|
||||
on_passphrase_request(input, dynamic_cast<const messages::common::PassphraseRequest*>(input.m_msg.get()));
|
||||
return true;
|
||||
case messages::MessageType_Deprecated_PassphraseStateRequest:
|
||||
on_passphrase_state_request(input, dynamic_cast<const messages::common::Deprecated_PassphraseStateRequest*>(input.m_msg.get()));
|
||||
return true;
|
||||
case messages::MessageType_PinMatrixRequest:
|
||||
on_pin_request(input, dynamic_cast<const messages::common::PinMatrixRequest*>(input.m_msg.get()));
|
||||
return true;
|
||||
|
@ -475,21 +472,9 @@ namespace trezor {
|
|||
CHECK_AND_ASSERT_THROW_MES(msg, "Empty message");
|
||||
MDEBUG("on_passhprase_request");
|
||||
|
||||
// Backward compatibility, migration clause.
|
||||
if (msg->has__on_device() && msg->_on_device()){
|
||||
messages::common::PassphraseAck m;
|
||||
resp = call_raw(&m);
|
||||
return;
|
||||
}
|
||||
|
||||
m_seen_passphrase_entry_message = true;
|
||||
bool on_device = true;
|
||||
if (msg->has__on_device() && !msg->_on_device()){
|
||||
on_device = false; // do not enter on device, old devices.
|
||||
}
|
||||
|
||||
if (on_device && m_features && m_features->capabilities_size() > 0){
|
||||
on_device = false;
|
||||
bool on_device = false;
|
||||
if (m_features){
|
||||
for (auto it = m_features->capabilities().begin(); it != m_features->capabilities().end(); it++) {
|
||||
if (*it == messages::management::Features::Capability_PassphraseEntry){
|
||||
on_device = true;
|
||||
|
@ -526,18 +511,6 @@ namespace trezor {
|
|||
resp = call_raw(&m);
|
||||
}
|
||||
|
||||
void device_trezor_base::on_passphrase_state_request(GenericMessage & resp, const messages::common::Deprecated_PassphraseStateRequest * msg)
|
||||
{
|
||||
MDEBUG("on_passhprase_state_request");
|
||||
CHECK_AND_ASSERT_THROW_MES(msg, "Empty message");
|
||||
|
||||
if (msg->has_state()) {
|
||||
m_device_session_id = msg->state();
|
||||
}
|
||||
messages::common::Deprecated_PassphraseStateAck m;
|
||||
resp = call_raw(&m);
|
||||
}
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
void device_trezor_base::wipe_device()
|
||||
{
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace trezor {
|
|||
boost::optional<epee::wipeable_string> m_passphrase;
|
||||
messages::MessageType m_last_msg_type;
|
||||
|
||||
cryptonote::network_type network_type;
|
||||
cryptonote::network_type m_network_type;
|
||||
bool m_reply_with_empty_passphrase;
|
||||
bool m_always_use_empty_passphrase;
|
||||
bool m_seen_passphrase_entry_message;
|
||||
|
@ -227,9 +227,9 @@ namespace trezor {
|
|||
}
|
||||
|
||||
if (network_type){
|
||||
msg->set_network_type(static_cast<uint32_t>(network_type.get()));
|
||||
msg->set_network_type(static_cast<messages::monero::MoneroNetworkType>(network_type.get()));
|
||||
} else {
|
||||
msg->set_network_type(static_cast<uint32_t>(this->network_type));
|
||||
msg->set_network_type(static_cast<messages::monero::MoneroNetworkType>(this->m_network_type));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,7 +318,6 @@ namespace trezor {
|
|||
void on_button_pressed();
|
||||
void on_pin_request(GenericMessage & resp, const messages::common::PinMatrixRequest * msg);
|
||||
void on_passphrase_request(GenericMessage & resp, const messages::common::PassphraseRequest * msg);
|
||||
void on_passphrase_state_request(GenericMessage & resp, const messages::common::Deprecated_PassphraseStateRequest * msg);
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
void set_debug(bool debug){
|
||||
|
|
|
@ -67,7 +67,7 @@ namespace trezor{
|
|||
|
||||
void DebugLink::input_button(bool button){
|
||||
messages::debug::DebugLinkDecision decision;
|
||||
decision.set_yes_no(button);
|
||||
decision.set_button(button ? messages::debug::DebugLinkDecision_DebugButton_YES : messages::debug::DebugLinkDecision_DebugButton_NO);
|
||||
call(decision, boost::none, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -154,6 +154,7 @@ namespace trezor{
|
|||
// Helpers
|
||||
//
|
||||
|
||||
#define PROTO_MAGIC_SIZE 3
|
||||
#define PROTO_HEADER_SIZE 6
|
||||
|
||||
static size_t message_size(const google::protobuf::Message &req){
|
||||
|
@ -193,7 +194,7 @@ namespace trezor{
|
|||
}
|
||||
|
||||
serialize_message_header(buff, msg_wire_num, msg_size);
|
||||
if (!req.SerializeToArray(buff + 6, msg_size)){
|
||||
if (!req.SerializeToArray(buff + PROTO_HEADER_SIZE, msg_size)){
|
||||
throw exc::EncodingException("Message serialization error");
|
||||
}
|
||||
}
|
||||
|
@ -252,16 +253,16 @@ namespace trezor{
|
|||
throw exc::CommunicationException("Read chunk has invalid size");
|
||||
}
|
||||
|
||||
if (memcmp(chunk_buff_raw, "?##", 3) != 0){
|
||||
if (memcmp(chunk_buff_raw, "?##", PROTO_MAGIC_SIZE) != 0){
|
||||
throw exc::CommunicationException("Malformed chunk");
|
||||
}
|
||||
|
||||
uint16_t tag;
|
||||
uint32_t len;
|
||||
nread -= 3 + 6;
|
||||
deserialize_message_header(chunk_buff_raw + 3, tag, len);
|
||||
nread -= PROTO_MAGIC_SIZE + PROTO_HEADER_SIZE;
|
||||
deserialize_message_header(chunk_buff_raw + PROTO_MAGIC_SIZE, tag, len);
|
||||
|
||||
epee::wipeable_string data_acc(chunk_buff_raw + 3 + 6, nread);
|
||||
epee::wipeable_string data_acc(chunk_buff_raw + PROTO_MAGIC_SIZE + PROTO_HEADER_SIZE, nread);
|
||||
data_acc.reserve(len);
|
||||
|
||||
while(nread < len){
|
||||
|
@ -482,7 +483,7 @@ namespace trezor{
|
|||
uint16_t msg_tag;
|
||||
uint32_t msg_len;
|
||||
deserialize_message_header(bin_data->data(), msg_tag, msg_len);
|
||||
if (bin_data->size() != msg_len + 6){
|
||||
if (bin_data->size() != msg_len + PROTO_HEADER_SIZE){
|
||||
throw exc::CommunicationException("Response is not well hexcoded");
|
||||
}
|
||||
|
||||
|
@ -491,7 +492,7 @@ namespace trezor{
|
|||
}
|
||||
|
||||
std::shared_ptr<google::protobuf::Message> msg_wrap(MessageMapper::get_message(msg_tag));
|
||||
if (!msg_wrap->ParseFromArray(bin_data->data() + 6, msg_len)){
|
||||
if (!msg_wrap->ParseFromArray(bin_data->data() + PROTO_HEADER_SIZE, msg_len)){
|
||||
throw exc::EncodingException("Response is not well hexcoded");
|
||||
}
|
||||
msg = msg_wrap;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue