mirror of
https://github.com/monero-project/monero.git
synced 2025-06-21 12:34:13 -04:00
device/trezor: debugging features, trezor tests
This commit is contained in:
parent
31bdf7bd11
commit
5ea17909ca
24 changed files with 3616 additions and 177 deletions
|
@ -67,6 +67,12 @@ set(trezor_private_headers)
|
|||
if(DEVICE_TREZOR_READY)
|
||||
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")
|
||||
endif()
|
||||
|
||||
monero_private_headers(device_trezor
|
||||
${device_private_headers})
|
||||
|
||||
|
|
|
@ -97,7 +97,14 @@ namespace trezor {
|
|||
auto res = get_view_key();
|
||||
CHECK_AND_ASSERT_MES(res->watch_key().size() == 32, false, "Trezor returned invalid view key");
|
||||
|
||||
// Trezor does not make use of spendkey of the device API.
|
||||
// Ledger loads encrypted spendkey, Trezor loads null key (never leaves device).
|
||||
// In the test (debugging mode) we need to leave this field intact as it is already set by
|
||||
// the debugging code and need to remain same for the testing purposes.
|
||||
#ifndef WITH_TREZOR_DEBUGGING
|
||||
spendkey = crypto::null_skey; // not given
|
||||
#endif
|
||||
|
||||
memcpy(viewkey.data, res->watch_key().data(), 32);
|
||||
|
||||
return true;
|
||||
|
@ -362,13 +369,9 @@ namespace trezor {
|
|||
CHECK_AND_ASSERT_THROW_MES(m_features, "Device state not initialized"); // make sure the caller did not reset features
|
||||
const bool nonce_required = init_msg->tsx_data().has_payment_id() && init_msg->tsx_data().payment_id().size() > 0;
|
||||
|
||||
if (nonce_required){
|
||||
if (nonce_required && init_msg->tsx_data().payment_id().size() == 8){
|
||||
// Versions 2.0.9 and lower do not support payment ID
|
||||
CHECK_AND_ASSERT_THROW_MES(m_features->has_major_version() && m_features->has_minor_version() && m_features->has_patch_version(), "Invalid Trezor firmware version information");
|
||||
const uint32_t vma = m_features->major_version();
|
||||
const uint32_t vmi = m_features->minor_version();
|
||||
const uint32_t vpa = m_features->patch_version();
|
||||
if (vma < 2 || (vma == 2 && vmi == 0 && vpa <= 9)) {
|
||||
if (get_version() <= pack_version(2, 0, 9)) {
|
||||
throw exc::TrezorException("Trezor firmware 2.0.9 and lower does not support transactions with short payment IDs or integrated addresses. Please update.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,9 @@ namespace trezor {
|
|||
const uint32_t device_trezor_base::DEFAULT_BIP44_PATH[] = {0x8000002c, 0x80000080};
|
||||
|
||||
device_trezor_base::device_trezor_base(): m_callback(nullptr) {
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
m_debug = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
device_trezor_base::~device_trezor_base() {
|
||||
|
@ -130,6 +132,10 @@ namespace trezor {
|
|||
}
|
||||
|
||||
m_transport->open();
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
setup_debug();
|
||||
#endif
|
||||
return true;
|
||||
|
||||
} catch(std::exception const& e){
|
||||
|
@ -153,6 +159,13 @@ namespace trezor {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
if (m_debug_callback) {
|
||||
m_debug_callback->on_disconnect();
|
||||
m_debug_callback = nullptr;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -355,6 +368,32 @@ namespace trezor {
|
|||
device_state_reset_unsafe();
|
||||
}
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
#define TREZOR_CALLBACK(method, ...) do { \
|
||||
if (m_debug_callback) m_debug_callback->method(__VA_ARGS__); \
|
||||
if (m_callback) m_callback->method(__VA_ARGS__); \
|
||||
}while(0)
|
||||
|
||||
void device_trezor_base::setup_debug(){
|
||||
if (!m_debug){
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_debug_callback){
|
||||
CHECK_AND_ASSERT_THROW_MES(m_transport, "Transport does not exist");
|
||||
auto debug_transport = m_transport->find_debug();
|
||||
if (debug_transport) {
|
||||
m_debug_callback = std::make_shared<trezor_debug_callback>(debug_transport);
|
||||
} else {
|
||||
MDEBUG("Transport does not have debug link option");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#define TREZOR_CALLBACK(method, ...) do { if (m_callback) m_callback->method(__VA_ARGS__); } while(0)
|
||||
#endif
|
||||
|
||||
void device_trezor_base::on_button_request(GenericMessage & resp, const messages::common::ButtonRequest * msg)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(msg, "Empty message");
|
||||
|
@ -363,10 +402,7 @@ namespace trezor {
|
|||
messages::common::ButtonAck ack;
|
||||
write_raw(&ack);
|
||||
|
||||
if (m_callback){
|
||||
m_callback->on_button_request();
|
||||
}
|
||||
|
||||
TREZOR_CALLBACK(on_button_request);
|
||||
resp = read_raw();
|
||||
}
|
||||
|
||||
|
@ -377,9 +413,7 @@ namespace trezor {
|
|||
|
||||
epee::wipeable_string pin;
|
||||
|
||||
if (m_callback){
|
||||
m_callback->on_pin_request(pin);
|
||||
}
|
||||
TREZOR_CALLBACK(on_pin_request, pin);
|
||||
|
||||
// TODO: remove PIN from memory
|
||||
messages::common::PinMatrixAck m;
|
||||
|
@ -393,9 +427,7 @@ namespace trezor {
|
|||
MDEBUG("on_passhprase_request, on device: " << msg->on_device());
|
||||
epee::wipeable_string passphrase;
|
||||
|
||||
if (m_callback){
|
||||
m_callback->on_passphrase_request(msg->on_device(), passphrase);
|
||||
}
|
||||
TREZOR_CALLBACK(on_passphrase_request, msg->on_device(), passphrase);
|
||||
|
||||
messages::common::PassphraseAck m;
|
||||
if (!msg->on_device()){
|
||||
|
@ -421,5 +453,67 @@ namespace trezor {
|
|||
resp = call_raw(&m);
|
||||
}
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
void device_trezor_base::wipe_device()
|
||||
{
|
||||
auto msg = std::make_shared<messages::management::WipeDevice>();
|
||||
auto ret = client_exchange<messages::common::Success>(msg);
|
||||
(void)ret;
|
||||
init_device();
|
||||
}
|
||||
|
||||
void device_trezor_base::init_device()
|
||||
{
|
||||
auto msg = std::make_shared<messages::management::Initialize>();
|
||||
m_features = client_exchange<messages::management::Features>(msg);
|
||||
}
|
||||
|
||||
void device_trezor_base::load_device(const std::string & mnemonic, const std::string & pin,
|
||||
bool passphrase_protection, const std::string & label, const std::string & language,
|
||||
bool skip_checksum, bool expand)
|
||||
{
|
||||
if (m_features && m_features->initialized()){
|
||||
throw std::runtime_error("Device is initialized already. Call device.wipe() and try again.");
|
||||
}
|
||||
|
||||
auto msg = std::make_shared<messages::management::LoadDevice>();
|
||||
msg->set_mnemonic(mnemonic);
|
||||
msg->set_pin(pin);
|
||||
msg->set_passphrase_protection(passphrase_protection);
|
||||
msg->set_label(label);
|
||||
msg->set_language(language);
|
||||
msg->set_skip_checksum(skip_checksum);
|
||||
auto ret = client_exchange<messages::common::Success>(msg);
|
||||
(void)ret;
|
||||
|
||||
init_device();
|
||||
}
|
||||
|
||||
trezor_debug_callback::trezor_debug_callback(std::shared_ptr<Transport> & debug_transport){
|
||||
m_debug_link = std::make_shared<DebugLink>();
|
||||
m_debug_link->init(debug_transport);
|
||||
}
|
||||
|
||||
void trezor_debug_callback::on_button_request() {
|
||||
if (m_debug_link) m_debug_link->press_yes();
|
||||
}
|
||||
|
||||
void trezor_debug_callback::on_pin_request(epee::wipeable_string &pin) {
|
||||
|
||||
}
|
||||
|
||||
void trezor_debug_callback::on_passphrase_request(bool on_device, epee::wipeable_string &passphrase) {
|
||||
|
||||
}
|
||||
|
||||
void trezor_debug_callback::on_passphrase_state_request(const std::string &state) {
|
||||
|
||||
}
|
||||
|
||||
void trezor_debug_callback::on_disconnect(){
|
||||
if (m_debug_link) m_debug_link->close();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //WITH_DEVICE_TREZOR
|
||||
}}
|
||||
|
|
|
@ -42,6 +42,10 @@
|
|||
#include "cryptonote_config.h"
|
||||
#include "trezor.hpp"
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
#include "trezor/debug_link.hpp"
|
||||
#endif
|
||||
|
||||
//automatic lock one more level on device ensuring the current thread is allowed to use it
|
||||
#define AUTO_LOCK_CMD() \
|
||||
/* lock both mutexes without deadlock*/ \
|
||||
|
@ -57,6 +61,23 @@ namespace trezor {
|
|||
#ifdef WITH_DEVICE_TREZOR
|
||||
class device_trezor_base;
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
class trezor_debug_callback {
|
||||
public:
|
||||
trezor_debug_callback()=default;
|
||||
explicit trezor_debug_callback(std::shared_ptr<Transport> & debug_transport);
|
||||
|
||||
void on_button_request();
|
||||
void on_pin_request(epee::wipeable_string &pin);
|
||||
void on_passphrase_request(bool on_device, epee::wipeable_string &passphrase);
|
||||
void on_passphrase_state_request(const std::string &state);
|
||||
void on_disconnect();
|
||||
protected:
|
||||
std::shared_ptr<DebugLink> m_debug_link;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TREZOR device template with basic functions
|
||||
*/
|
||||
|
@ -77,6 +98,13 @@ namespace trezor {
|
|||
|
||||
cryptonote::network_type network_type;
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
std::shared_ptr<trezor_debug_callback> m_debug_callback;
|
||||
bool m_debug;
|
||||
|
||||
void setup_debug();
|
||||
#endif
|
||||
|
||||
//
|
||||
// Internal methods
|
||||
//
|
||||
|
@ -103,7 +131,7 @@ namespace trezor {
|
|||
* @throws UnexpectedMessageException if the response message type is different than expected.
|
||||
* Exception contains message type and the message itself.
|
||||
*/
|
||||
template<class t_message>
|
||||
template<class t_message=google::protobuf::Message>
|
||||
std::shared_ptr<t_message>
|
||||
client_exchange(const std::shared_ptr<const google::protobuf::Message> &req,
|
||||
const boost::optional<messages::MessageType> & resp_type = boost::none,
|
||||
|
@ -229,6 +257,12 @@ namespace trezor {
|
|||
return m_features;
|
||||
}
|
||||
|
||||
uint64_t get_version() const {
|
||||
CHECK_AND_ASSERT_THROW_MES(m_features, "Features not loaded");
|
||||
CHECK_AND_ASSERT_THROW_MES(m_features->has_major_version() && m_features->has_minor_version() && m_features->has_patch_version(), "Invalid Trezor firmware version information");
|
||||
return pack_version(m_features->major_version(), m_features->minor_version(), m_features->patch_version());
|
||||
}
|
||||
|
||||
void set_derivation_path(const std::string &deriv_path) override;
|
||||
|
||||
/* ======================================================================= */
|
||||
|
@ -268,6 +302,23 @@ namespace trezor {
|
|||
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::PassphraseStateRequest * msg);
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
void set_debug(bool debug){
|
||||
m_debug = debug;
|
||||
}
|
||||
|
||||
void set_debug_callback(std::shared_ptr<trezor_debug_callback> & debug_callback){
|
||||
m_debug_callback = debug_callback;
|
||||
}
|
||||
|
||||
void wipe_device();
|
||||
void init_device();
|
||||
void load_device(const std::string & mnemonic, const std::string & pin="", bool passphrase_protection=false,
|
||||
const std::string & label="test", const std::string & language="english",
|
||||
bool skip_checksum=false, bool expand=false);
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
90
src/device_trezor/trezor/debug_link.cpp
Normal file
90
src/device_trezor/trezor/debug_link.cpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
// Copyright (c) 2017-2018, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#include "debug_link.hpp"
|
||||
|
||||
namespace hw{
|
||||
namespace trezor{
|
||||
|
||||
DebugLink::DebugLink(){
|
||||
|
||||
}
|
||||
|
||||
DebugLink::~DebugLink(){
|
||||
if (m_transport){
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
void DebugLink::init(std::shared_ptr<Transport> & transport){
|
||||
CHECK_AND_ASSERT_THROW_MES(!m_transport, "Already initialized");
|
||||
m_transport = transport;
|
||||
m_transport->open();
|
||||
}
|
||||
|
||||
void DebugLink::close(){
|
||||
CHECK_AND_ASSERT_THROW_MES(m_transport, "Not initialized");
|
||||
if (m_transport) m_transport->close();
|
||||
}
|
||||
|
||||
std::shared_ptr<messages::debug::DebugLinkState> DebugLink::state(){
|
||||
return call<messages::debug::DebugLinkState>(
|
||||
messages::debug::DebugLinkGetState(),
|
||||
boost::make_optional(messages::MessageType_DebugLinkGetState));
|
||||
}
|
||||
|
||||
void DebugLink::input_word(const std::string & word){
|
||||
messages::debug::DebugLinkDecision decision;
|
||||
decision.set_input(word);
|
||||
call(decision, boost::none, true);
|
||||
}
|
||||
|
||||
void DebugLink::input_button(bool button){
|
||||
messages::debug::DebugLinkDecision decision;
|
||||
decision.set_yes_no(button);
|
||||
call(decision, boost::none, true);
|
||||
}
|
||||
|
||||
void DebugLink::input_swipe(bool swipe){
|
||||
messages::debug::DebugLinkDecision decision;
|
||||
decision.set_up_down(swipe);
|
||||
call(decision, boost::none, true);
|
||||
}
|
||||
|
||||
void DebugLink::stop(){
|
||||
messages::debug::DebugLinkStop msg;
|
||||
call(msg, boost::none, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
93
src/device_trezor/trezor/debug_link.hpp
Normal file
93
src/device_trezor/trezor/debug_link.hpp
Normal file
|
@ -0,0 +1,93 @@
|
|||
// Copyright (c) 2017-2018, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef MONERO_DEBUG_LINK_H
|
||||
#define MONERO_DEBUG_LINK_H
|
||||
|
||||
#include "transport.hpp"
|
||||
#include "messages/messages-debug.pb.h"
|
||||
|
||||
|
||||
namespace hw {
|
||||
namespace trezor {
|
||||
|
||||
class DebugLink {
|
||||
public:
|
||||
|
||||
DebugLink();
|
||||
virtual ~DebugLink();
|
||||
|
||||
void init(std::shared_ptr<Transport> & transport);
|
||||
void close();
|
||||
|
||||
std::shared_ptr<messages::debug::DebugLinkState> state();
|
||||
void input_word(const std::string & word);
|
||||
void input_button(bool button);
|
||||
void input_swipe(bool swipe);
|
||||
void press_yes() { input_button(true); }
|
||||
void press_no() { input_button(false); }
|
||||
void stop();
|
||||
|
||||
template<class t_message=messages::debug::DebugLinkState>
|
||||
std::shared_ptr<t_message> call(
|
||||
const google::protobuf::Message & req,
|
||||
const boost::optional<messages::MessageType> &resp_type = boost::none,
|
||||
bool no_wait = false)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(boost::is_base_of<google::protobuf::Message, t_message>::value);
|
||||
|
||||
m_transport->write(req);
|
||||
if (no_wait){
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Read the response
|
||||
std::shared_ptr<google::protobuf::Message> msg_resp;
|
||||
hw::trezor::messages::MessageType msg_resp_type;
|
||||
m_transport->read(msg_resp, &msg_resp_type);
|
||||
|
||||
messages::MessageType required_type = resp_type ? resp_type.get() : MessageMapper::get_message_wire_number<t_message>();
|
||||
if (msg_resp_type == required_type) {
|
||||
return message_ptr_retype<t_message>(msg_resp);
|
||||
} else if (msg_resp_type == messages::MessageType_Failure){
|
||||
throw_failure_exception(dynamic_cast<messages::common::Failure*>(msg_resp.get()));
|
||||
} else {
|
||||
throw exc::UnexpectedMessageException(msg_resp_type, msg_resp);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
std::shared_ptr<Transport> m_transport;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //MONERO_DEBUG_LINK_H
|
|
@ -33,6 +33,10 @@
|
|||
#include "messages/messages-management.pb.h"
|
||||
#include "messages/messages-monero.pb.h"
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
#include "messages/messages-debug.pb.h"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace hw::trezor;
|
||||
|
||||
|
@ -45,6 +49,9 @@ namespace trezor
|
|||
"hw.trezor.messages.",
|
||||
"hw.trezor.messages.common.",
|
||||
"hw.trezor.messages.management.",
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
"hw.trezor.messages.debug.",
|
||||
#endif
|
||||
"hw.trezor.messages.monero."
|
||||
};
|
||||
|
||||
|
@ -68,6 +75,10 @@ namespace trezor
|
|||
hw::trezor::messages::management::Cancel::default_instance();
|
||||
hw::trezor::messages::monero::MoneroGetAddress::default_instance();
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
hw::trezor::messages::debug::DebugLinkDecision::default_instance();
|
||||
#endif
|
||||
|
||||
google::protobuf::Descriptor const * desc = nullptr;
|
||||
for(const string &text : PACKAGES){
|
||||
desc = google::protobuf::DescriptorPool::generated_pool()
|
||||
|
|
|
@ -62,14 +62,14 @@ namespace trezor {
|
|||
static messages::MessageType get_message_wire_number(const google::protobuf::Message & msg);
|
||||
static messages::MessageType get_message_wire_number(const std::string & msg_name);
|
||||
|
||||
template<class t_message>
|
||||
template<class t_message=google::protobuf::Message>
|
||||
static messages::MessageType get_message_wire_number() {
|
||||
BOOST_STATIC_ASSERT(boost::is_base_of<google::protobuf::Message, t_message>::value);
|
||||
return get_message_wire_number(t_message::default_instance().GetDescriptor()->name());
|
||||
}
|
||||
};
|
||||
|
||||
template<class t_message>
|
||||
template<class t_message=google::protobuf::Message>
|
||||
std::shared_ptr<t_message> message_ptr_retype(std::shared_ptr<google::protobuf::Message> & in){
|
||||
BOOST_STATIC_ASSERT(boost::is_base_of<google::protobuf::Message, t_message>::value);
|
||||
if (!in){
|
||||
|
@ -79,7 +79,7 @@ namespace trezor {
|
|||
return std::dynamic_pointer_cast<t_message>(in);
|
||||
}
|
||||
|
||||
template<class t_message>
|
||||
template<class t_message=google::protobuf::Message>
|
||||
std::shared_ptr<t_message> message_ptr_retype_static(std::shared_ptr<google::protobuf::Message> & in){
|
||||
BOOST_STATIC_ASSERT(boost::is_base_of<google::protobuf::Message, t_message>::value);
|
||||
if (!in){
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-d", "--debug-msg", default=False, action="store_const", const=True, help="Build debug messages")
|
||||
args = parser.parse_args()
|
||||
|
||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||
ROOT_DIR = os.path.abspath(os.path.join(CWD, "..", "..", "..", ".."))
|
||||
|
@ -24,6 +30,10 @@ try:
|
|||
"messages-management.proto",
|
||||
"messages-monero.proto",
|
||||
]
|
||||
|
||||
if args.debug_msg:
|
||||
selected += ["messages-debug.proto"]
|
||||
|
||||
proto_srcs = [os.path.join(TREZOR_COMMON, "protob", x) for x in selected]
|
||||
exec_args = [
|
||||
sys.executable,
|
||||
|
|
|
@ -84,6 +84,17 @@ namespace trezor{
|
|||
return std::string(in.GetString());
|
||||
}
|
||||
|
||||
uint64_t pack_version(uint32_t major, uint32_t minor, uint32_t patch)
|
||||
{
|
||||
// packing (major, minor, patch) to 64 B: 16 B | 24 B | 24 B
|
||||
const unsigned bits_1 = 16;
|
||||
const unsigned bits_2 = 24;
|
||||
const uint32_t mask_1 = (1 << bits_1) - 1;
|
||||
const uint32_t mask_2 = (1 << bits_2) - 1;
|
||||
CHECK_AND_ASSERT_THROW_MES(major <= mask_1 && minor <= mask_2 && patch <= mask_2, "Version numbers overflow packing scheme");
|
||||
return patch | (((uint64_t)minor) << bits_2) | (((uint64_t)major) << (bits_1 + bits_2));
|
||||
}
|
||||
|
||||
//
|
||||
// Helpers
|
||||
//
|
||||
|
@ -212,6 +223,40 @@ namespace trezor{
|
|||
msg = msg_wrap;
|
||||
}
|
||||
|
||||
Transport::Transport(): m_open_counter(0) {
|
||||
|
||||
}
|
||||
|
||||
bool Transport::pre_open(){
|
||||
if (m_open_counter > 0){
|
||||
MTRACE("Already opened, count: " << m_open_counter);
|
||||
m_open_counter += 1;
|
||||
return false;
|
||||
|
||||
} else if (m_open_counter < 0){
|
||||
MTRACE("Negative open value: " << m_open_counter);
|
||||
|
||||
}
|
||||
|
||||
// Caller should set m_open_counter to 1 after open
|
||||
m_open_counter = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Transport::pre_close(){
|
||||
m_open_counter -= 1;
|
||||
|
||||
if (m_open_counter < 0){
|
||||
MDEBUG("Already closed. Counter " << m_open_counter);
|
||||
|
||||
} else if (m_open_counter == 0) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Bridge transport
|
||||
//
|
||||
|
@ -246,6 +291,10 @@ namespace trezor{
|
|||
}
|
||||
|
||||
void BridgeTransport::open() {
|
||||
if (!pre_open()){
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_device_path){
|
||||
throw exc::CommunicationException("Coud not open, empty device path");
|
||||
}
|
||||
|
@ -259,9 +308,15 @@ namespace trezor{
|
|||
}
|
||||
|
||||
m_session = boost::make_optional(json_get_string(bridge_res["session"]));
|
||||
m_open_counter = 1;
|
||||
}
|
||||
|
||||
void BridgeTransport::close() {
|
||||
if (!pre_close()){
|
||||
return;
|
||||
}
|
||||
|
||||
MTRACE("Closing Trezor:BridgeTransport");
|
||||
if (!m_device_path || !m_session){
|
||||
throw exc::CommunicationException("Device not open");
|
||||
}
|
||||
|
@ -423,6 +478,10 @@ namespace trezor{
|
|||
}
|
||||
|
||||
void UdpTransport::open() {
|
||||
if (!pre_open()){
|
||||
return;
|
||||
}
|
||||
|
||||
udp::resolver resolver(m_io_service);
|
||||
udp::resolver::query query(udp::v4(), m_device_host, std::to_string(m_device_port));
|
||||
m_endpoint = *resolver.resolve(query);
|
||||
|
@ -434,10 +493,16 @@ namespace trezor{
|
|||
check_deadline();
|
||||
|
||||
m_proto->session_begin(*this);
|
||||
m_open_counter = 1;
|
||||
}
|
||||
|
||||
void UdpTransport::close() {
|
||||
if (!m_socket){
|
||||
if (!pre_close()){
|
||||
return;
|
||||
}
|
||||
|
||||
MTRACE("Closing Trezor:UdpTransport");
|
||||
if (!m_socket) {
|
||||
throw exc::CommunicationException("Socket is already closed");
|
||||
}
|
||||
|
||||
|
@ -446,6 +511,19 @@ namespace trezor{
|
|||
m_socket = nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Transport> UdpTransport::find_debug() {
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
std::shared_ptr<UdpTransport> t = std::make_shared<UdpTransport>();
|
||||
t->m_proto = std::make_shared<ProtocolV1>();
|
||||
t->m_device_host = m_device_host;
|
||||
t->m_device_port = m_device_port + 1;
|
||||
return t;
|
||||
#else
|
||||
MINFO("Debug link is disabled in production");
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void UdpTransport::write_chunk(const void * buff, size_t size){
|
||||
require_socket();
|
||||
|
||||
|
@ -660,8 +738,7 @@ namespace trezor{
|
|||
WebUsbTransport::WebUsbTransport(
|
||||
boost::optional<libusb_device_descriptor*> descriptor,
|
||||
boost::optional<std::shared_ptr<Protocol>> proto
|
||||
): m_conn_count(0),
|
||||
m_usb_session(nullptr), m_usb_device(nullptr), m_usb_device_handle(nullptr),
|
||||
): m_usb_session(nullptr), m_usb_device(nullptr), m_usb_device_handle(nullptr),
|
||||
m_bus_id(-1), m_device_addr(-1)
|
||||
{
|
||||
if (descriptor){
|
||||
|
@ -672,7 +749,7 @@ namespace trezor{
|
|||
|
||||
m_proto = proto ? proto.get() : std::make_shared<ProtocolV1>();
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUG
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
m_debug_mode = false;
|
||||
#endif
|
||||
}
|
||||
|
@ -757,12 +834,10 @@ namespace trezor{
|
|||
};
|
||||
|
||||
void WebUsbTransport::open() {
|
||||
const int interface = get_interface();
|
||||
if (m_conn_count > 0){
|
||||
MTRACE("Already opened, count: " << m_conn_count);
|
||||
m_conn_count += 1;
|
||||
if (!pre_open()){
|
||||
return;
|
||||
}
|
||||
const int interface = get_interface();
|
||||
|
||||
#define TREZOR_DESTROY_SESSION() do { libusb_exit(m_usb_session); m_usb_session = nullptr; } while(0)
|
||||
|
||||
|
@ -840,45 +915,55 @@ namespace trezor{
|
|||
throw exc::DeviceAcquireException("Unable to claim libusb device");
|
||||
}
|
||||
|
||||
m_conn_count = 1;
|
||||
m_open_counter = 1;
|
||||
m_proto->session_begin(*this);
|
||||
|
||||
#undef TREZOR_DESTROY_SESSION
|
||||
};
|
||||
|
||||
void WebUsbTransport::close() {
|
||||
m_conn_count -= 1;
|
||||
if (!pre_close()){
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_conn_count < 0){
|
||||
MERROR("Close counter is negative: " << m_conn_count);
|
||||
MTRACE("Closing Trezor:WebUsbTransport");
|
||||
m_proto->session_end(*this);
|
||||
|
||||
} else if (m_conn_count == 0){
|
||||
MTRACE("Closing webusb device");
|
||||
int r = libusb_release_interface(m_usb_device_handle, get_interface());
|
||||
if (r != 0){
|
||||
MERROR("Could not release libusb interface: " << r);
|
||||
}
|
||||
|
||||
m_proto->session_end(*this);
|
||||
m_usb_device = nullptr;
|
||||
if (m_usb_device_handle) {
|
||||
libusb_close(m_usb_device_handle);
|
||||
m_usb_device_handle = nullptr;
|
||||
}
|
||||
|
||||
int r = libusb_release_interface(m_usb_device_handle, get_interface());
|
||||
if (r != 0){
|
||||
MERROR("Could not release libusb interface: " << r);
|
||||
}
|
||||
|
||||
m_usb_device = nullptr;
|
||||
if (m_usb_device_handle) {
|
||||
libusb_close(m_usb_device_handle);
|
||||
m_usb_device_handle = nullptr;
|
||||
}
|
||||
|
||||
if (m_usb_session) {
|
||||
libusb_exit(m_usb_session);
|
||||
m_usb_session = nullptr;
|
||||
}
|
||||
if (m_usb_session) {
|
||||
libusb_exit(m_usb_session);
|
||||
m_usb_session = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<Transport> WebUsbTransport::find_debug() {
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
require_device();
|
||||
auto t = std::make_shared<WebUsbTransport>(boost::make_optional(m_usb_device_desc.get()));
|
||||
t->m_bus_id = m_bus_id;
|
||||
t->m_device_addr = m_device_addr;
|
||||
t->m_port_numbers = m_port_numbers;
|
||||
t->m_debug_mode = true;
|
||||
return t;
|
||||
#else
|
||||
MINFO("Debug link is disabled in production");
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
int WebUsbTransport::get_interface() const{
|
||||
const int INTERFACE_NORMAL = 0;
|
||||
#ifdef WITH_TREZOR_DEBUG
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
const int INTERFACE_DEBUG = 1;
|
||||
return m_debug_mode ? INTERFACE_DEBUG : INTERFACE_NORMAL;
|
||||
#else
|
||||
|
@ -888,7 +973,7 @@ namespace trezor{
|
|||
|
||||
unsigned char WebUsbTransport::get_endpoint() const{
|
||||
const unsigned char ENDPOINT_NORMAL = 1;
|
||||
#ifdef WITH_TREZOR_DEBUG
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
const unsigned char ENDPOINT_DEBUG = 2;
|
||||
return m_debug_mode ? ENDPOINT_DEBUG : ENDPOINT_NORMAL;
|
||||
#else
|
||||
|
@ -1047,4 +1132,3 @@ namespace trezor{
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -62,6 +62,8 @@ namespace trezor {
|
|||
|
||||
const std::string DEFAULT_BRIDGE = "127.0.0.1:21325";
|
||||
|
||||
uint64_t pack_version(uint32_t major, uint32_t minor=0, uint32_t patch=0);
|
||||
|
||||
// Base HTTP comm serialization.
|
||||
bool t_serialize(const std::string & in, std::string & out);
|
||||
bool t_serialize(const json_val & in, std::string & out);
|
||||
|
@ -134,7 +136,7 @@ namespace trezor {
|
|||
|
||||
class Transport {
|
||||
public:
|
||||
Transport() = default;
|
||||
Transport();
|
||||
virtual ~Transport() = default;
|
||||
|
||||
virtual bool ping() { return false; };
|
||||
|
@ -144,10 +146,16 @@ namespace trezor {
|
|||
virtual void close(){};
|
||||
virtual void write(const google::protobuf::Message & req) =0;
|
||||
virtual void read(std::shared_ptr<google::protobuf::Message> & msg, messages::MessageType * msg_type=nullptr) =0;
|
||||
virtual std::shared_ptr<Transport> find_debug() { return nullptr; };
|
||||
|
||||
virtual void write_chunk(const void * buff, size_t size) { };
|
||||
virtual size_t read_chunk(void * buff, size_t size) { return 0; };
|
||||
virtual std::ostream& dump(std::ostream& o) const { return o << "Transport<>"; }
|
||||
protected:
|
||||
long m_open_counter;
|
||||
|
||||
virtual bool pre_open();
|
||||
virtual bool pre_close();
|
||||
};
|
||||
|
||||
// Bridge transport
|
||||
|
@ -212,6 +220,7 @@ namespace trezor {
|
|||
|
||||
void open() override;
|
||||
void close() override;
|
||||
std::shared_ptr<Transport> find_debug() override;
|
||||
|
||||
void write(const google::protobuf::Message &req) override;
|
||||
void read(std::shared_ptr<google::protobuf::Message> & msg, messages::MessageType * msg_type=nullptr) override;
|
||||
|
@ -259,6 +268,7 @@ namespace trezor {
|
|||
|
||||
void open() override;
|
||||
void close() override;
|
||||
std::shared_ptr<Transport> find_debug() override;
|
||||
|
||||
void write(const google::protobuf::Message &req) override;
|
||||
void read(std::shared_ptr<google::protobuf::Message> & msg, messages::MessageType * msg_type=nullptr) override;
|
||||
|
@ -274,7 +284,6 @@ namespace trezor {
|
|||
int get_interface() const;
|
||||
unsigned char get_endpoint() const;
|
||||
|
||||
int m_conn_count;
|
||||
std::shared_ptr<Protocol> m_proto;
|
||||
|
||||
libusb_context *m_usb_session;
|
||||
|
@ -285,7 +294,7 @@ namespace trezor {
|
|||
int m_bus_id;
|
||||
int m_device_addr;
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUG
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
bool m_debug_mode;
|
||||
#endif
|
||||
};
|
||||
|
@ -309,7 +318,7 @@ namespace trezor {
|
|||
/**
|
||||
* Transforms path to the particular transport
|
||||
*/
|
||||
template<class t_transport>
|
||||
template<class t_transport=Transport>
|
||||
std::shared_ptr<t_transport> transport_typed(const std::string & path){
|
||||
auto t = transport(path);
|
||||
if (!t){
|
||||
|
@ -362,7 +371,7 @@ namespace trezor {
|
|||
* @throws UnexpectedMessageException if the response message type is different than expected.
|
||||
* Exception contains message type and the message itself.
|
||||
*/
|
||||
template<class t_message>
|
||||
template<class t_message=google::protobuf::Message>
|
||||
std::shared_ptr<t_message>
|
||||
exchange_message(Transport & transport, const google::protobuf::Message & req,
|
||||
boost::optional<messages::MessageType> resp_type = boost::none)
|
||||
|
|
|
@ -30,5 +30,5 @@ set(net_sources error.cpp parse.cpp socks.cpp tor_address.cpp)
|
|||
set(net_headers error.h parse.h socks.h tor_address.h)
|
||||
|
||||
monero_add_library(net ${net_sources} ${net_headers})
|
||||
target_link_libraries(net epee ${Boost_ASIO_LIBRARY})
|
||||
target_link_libraries(net common epee ${Boost_ASIO_LIBRARY})
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.wallet2"
|
||||
|
||||
class Serialization_portability_wallet_Test;
|
||||
class wallet_accessor_test;
|
||||
|
||||
namespace tools
|
||||
{
|
||||
|
@ -171,6 +172,7 @@ namespace tools
|
|||
class wallet2
|
||||
{
|
||||
friend class ::Serialization_portability_wallet_Test;
|
||||
friend class ::wallet_accessor_test;
|
||||
friend class wallet_keys_unlocker;
|
||||
friend class wallet_device_callback;
|
||||
public:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue