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:
luigi1111 2023-10-25 21:30:49 -04:00
commit 8f0343df16
No known key found for this signature in database
GPG key ID: F4ACA0183641E010
41 changed files with 1221 additions and 738 deletions

View file

@ -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)

View 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/

View file

@ -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

View file

@ -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; }

View file

@ -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()
{

View file

@ -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){

View file

@ -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);
}

View file

@ -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;