device: enable to use multiple independent device wallets

- adds a new option `--hw-device-deriv-path` to the simple wallet. Enables to specify wallet derivation path / wallet code (path avoided so it can be misinterpreted as a file path).
- devices can use different derivation mechanisms. Trezor uses standard SLIP-10 mechanism with fixed SLIP-44 prefix for Monero
- Trezor: when empty, the default derivation mechanism is used with 44'/128'/0'. When entered the derivation path is 44'/128'/PATH.
- Trezor: the path is always taken as elements are hardened (1<<31 bit turned on)
This commit is contained in:
Dusan Klinec 2018-11-12 00:07:25 +01:00
parent 318cc78457
commit d21dad70dd
No known key found for this signature in database
GPG key ID: 6337E118CCBCE103
6 changed files with 73 additions and 2 deletions

View file

@ -28,6 +28,9 @@
//
#include "device_trezor_base.hpp"
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/regex.hpp>
namespace hw {
namespace trezor {
@ -36,8 +39,9 @@ namespace trezor {
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "device.trezor"
#define TREZOR_BIP44_HARDENED_ZERO 0x80000000
const uint32_t device_trezor_base::DEFAULT_BIP44_PATH[] = {0x8000002c, 0x80000080, 0x80000000};
const uint32_t device_trezor_base::DEFAULT_BIP44_PATH[] = {0x8000002c, 0x80000080};
device_trezor_base::device_trezor_base(): m_callback(nullptr) {
@ -252,6 +256,39 @@ namespace trezor {
}
}
void device_trezor_base::ensure_derivation_path() noexcept {
if (m_wallet_deriv_path.empty()){
m_wallet_deriv_path.push_back(TREZOR_BIP44_HARDENED_ZERO); // default 0'
}
}
void device_trezor_base::set_derivation_path(const std::string &deriv_path){
this->m_wallet_deriv_path.clear();
if (deriv_path.empty() || deriv_path == "-"){
ensure_derivation_path();
return;
}
CHECK_AND_ASSERT_THROW_MES(deriv_path.size() <= 255, "Derivation path is too long");
std::vector<std::string> fields;
boost::split(fields, deriv_path, boost::is_any_of("/"));
CHECK_AND_ASSERT_THROW_MES(fields.size() <= 10, "Derivation path is too long");
boost::regex rgx("^([0-9]+)'?$");
boost::cmatch match;
this->m_wallet_deriv_path.reserve(fields.size());
for(const std::string & cur : fields){
const bool ok = boost::regex_match(cur.c_str(), match, rgx);
CHECK_AND_ASSERT_THROW_MES(ok, "Invalid wallet code: " << deriv_path << ". Invalid path element: " << cur);
CHECK_AND_ASSERT_THROW_MES(match[0].length() > 0, "Invalid wallet code: " << deriv_path << ". Invalid path element: " << cur);
const unsigned long cidx = std::stoul(match[0].str()) | TREZOR_BIP44_HARDENED_ZERO;
this->m_wallet_deriv_path.push_back((unsigned int)cidx);
}
}
/* ======================================================================= */
/* TREZOR PROTOCOL */

View file

@ -71,6 +71,7 @@ namespace trezor {
i_device_callback * m_callback;
std::string full_name;
std::vector<unsigned int> m_wallet_deriv_path;
cryptonote::network_type network_type;
@ -81,6 +82,7 @@ namespace trezor {
void require_connected();
void call_ping_unsafe();
void test_ping();
void ensure_derivation_path() noexcept;
// Communication methods
@ -176,9 +178,13 @@ namespace trezor {
msg->add_address_n(x);
}
} else {
ensure_derivation_path();
for (unsigned int i : DEFAULT_BIP44_PATH) {
msg->add_address_n(i);
}
for (unsigned int i : m_wallet_deriv_path) {
msg->add_address_n(i);
}
}
if (network_type){
@ -201,7 +207,7 @@ namespace trezor {
bool reset();
// Default derivation path for Monero
static const uint32_t DEFAULT_BIP44_PATH[3];
static const uint32_t DEFAULT_BIP44_PATH[2];
std::shared_ptr<Transport> getTransport(){
return m_transport;
@ -215,6 +221,8 @@ namespace trezor {
return m_callback;
}
void set_derivation_path(const std::string &deriv_path) override;
/* ======================================================================= */
/* SETUP/TEARDOWN */
/* ======================================================================= */