Skip to content

Commit 9b80c46

Browse files
committed
Release 0.90.4
2 parents 7fa4c20 + 7fee8a8 commit 9b80c46

25 files changed

+343
-111
lines changed

BlockSettleHW/hwcommonstructure.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ class HwWalletWrapper {
6969
!info_.xpubNativeSegwit.empty() &&
7070
!info_.xpubLegacy.empty();
7171
}
72+
73+
bool isFirmwareSupported_{true};
74+
std::string firmwareSupportedMsg_;
7275
};
7376
Q_DECLARE_METATYPE(HwWalletWrapper)
7477

BlockSettleHW/hwdeviceinterface.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class HwDeviceInterface : public QObject
3939

4040
// Management
4141
virtual void setMatrixPin(const std::string& pin) {};
42-
virtual void setPassword(const std::string& password) {};
42+
virtual void setPassword(const std::string& password, bool enterOnDevice) {};
4343

4444
// State
4545
virtual bool isBlocked() = 0;
@@ -54,7 +54,7 @@ class HwDeviceInterface : public QObject
5454

5555
// Management
5656
void requestPinMatrix();
57-
void requestHWPass();
57+
void requestHWPass(bool allowedOnDevice);
5858
void cancelledOnDevice();
5959
};
6060

BlockSettleHW/hwdevicemanager.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,14 @@ void HwDeviceManager::setMatrixPin(int deviceIndex, QString pin)
8686
device->setMatrixPin(pin.toStdString());
8787
}
8888

89-
void HwDeviceManager::setPassphrase(int deviceIndex, QString passphrase)
89+
void HwDeviceManager::setPassphrase(int deviceIndex, QString passphrase, bool enterOnDevice)
9090
{
9191
auto device = getDevice(model_->getDevice(deviceIndex));
9292
if (!device) {
9393
return;
9494
}
9595

96-
device->setPassword(passphrase.toStdString());
96+
device->setPassword(passphrase.toStdString(), enterOnDevice);
9797
}
9898

9999
void HwDeviceManager::cancel(int deviceIndex)

BlockSettleHW/hwdevicemanager.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class HwDeviceManager : public QObject
5050
Q_INVOKABLE void scanDevices();
5151
Q_INVOKABLE void requestPublicKey(int deviceIndex);
5252
Q_INVOKABLE void setMatrixPin(int deviceIndex, QString pin);
53-
Q_INVOKABLE void setPassphrase(int deviceIndex, QString passphrase);
53+
Q_INVOKABLE void setPassphrase(int deviceIndex, QString passphrase, bool enterOnDevice);
5454
Q_INVOKABLE void cancel(int deviceIndex);
5555
Q_INVOKABLE void prepareHwDeviceForSign(QString walletId);
5656
Q_INVOKABLE void signTX(QVariant reqTX);
@@ -64,7 +64,7 @@ class HwDeviceManager : public QObject
6464
void devicesChanged();
6565
void publicKeyReady(QVariant walletInfo);
6666
void requestPinMatrix();
67-
void requestHWPass();
67+
void requestHWPass(bool allowedOnDevice);
6868

6969
void deviceNotFound(QString deviceId);
7070
void deviceReady(QString deviceId);

BlockSettleHW/ledger/ledgerDevice.cpp

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,19 +1049,10 @@ void LedgerCommandThread::sendTxSigningResult(const QVector<QByteArray>& respons
10491049
Blocksettle::Communication::headless::InputSigs sigs;
10501050
for (std::size_t i = 0; i < responseSigned.size(); ++i) {
10511051
auto &signedInput = responseSigned[i];
1052-
auto pubKey = inputNodes[i].getPublicKey();
1053-
Asset_PublicKey pubKeyAsset(pubKey);
1054-
auto compressedKey = pubKeyAsset.getCompressedKey();
1055-
1056-
QByteArray composedData;
1057-
composedData.append(static_cast<char>(signedInput.size()));
1058-
composedData.append(signedInput);
1059-
composedData.append(static_cast<char>(compressedKey.getSize()));
1060-
composedData.push_back(QByteArray::fromStdString(compressedKey.toBinStr()));
10611052

10621053
auto *sig = sigs.add_inputsig();
10631054
sig->set_index(static_cast<uint>(i));
1064-
sig->set_data(composedData.toStdString().c_str(), composedData.size());
1055+
sig->set_data(signedInput.toStdString().c_str(), signedInput.size());
10651056
}
10661057

10671058
HWSignedTx wrapper;

BlockSettleHW/trezor/trezorDevice.cpp

Lines changed: 90 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@
2626
using namespace hw::trezor::messages;
2727

2828
namespace {
29+
const auto kModel1 = "1";
30+
const auto kModelT = "T";
31+
32+
const std::map<std::string, std::array<unsigned, 3>> kMinVersion = {
33+
{ kModel1, { 1, 9, 1 } },
34+
{ kModelT, { 2, 3, 1 } }
35+
};
36+
2937
// Trezor package rule (source - https://github.com/trezor/trezord-go)
3038
int getMessageType(const google::protobuf::Message &msg)
3139
{
@@ -128,6 +136,13 @@ void TrezorDevice::getPublicKey(AsyncCallBackCall&& cb)
128136
awaitingWalletInfo_.info_.deviceId = features_.device_id();
129137
awaitingWalletInfo_.info_.vendor = features_.vendor();
130138

139+
awaitingWalletInfo_.isFirmwareSupported_ = isFirmwareSupported();
140+
if (!awaitingWalletInfo_.isFirmwareSupported_) {
141+
awaitingWalletInfo_.firmwareSupportedMsg_ = firmwareSupportedVersion();
142+
cb(QVariant::fromValue<>(awaitingWalletInfo_));
143+
return;
144+
}
145+
131146
// We cannot get all data from one call so we make four calls:
132147
// fetching first address for "m/0'" as wallet id
133148
// fetching first address for "m/84'" as native segwit xpub
@@ -215,11 +230,15 @@ void TrezorDevice::setMatrixPin(const std::string& pin)
215230
makeCall(message);
216231
}
217232

218-
void TrezorDevice::setPassword(const std::string& password)
233+
void TrezorDevice::setPassword(const std::string& password, bool enterOnDevice)
219234
{
220235
connectionManager_->GetLogger()->debug("[TrezorDevice] setPassword - send passphrase response");
221236
common::PassphraseAck message;
222-
message.set_passphrase(password);
237+
if (enterOnDevice) {
238+
message.set_on_device(true);
239+
} else {
240+
message.set_passphrase(password);
241+
}
223242
makeCall(message);
224243
}
225244

@@ -308,7 +327,8 @@ void TrezorDevice::handleMessage(const MessageData& data)
308327
case MessageType_Features:
309328
{
310329
if (parseResponse(features_, data)) {
311-
connectionManager_->GetLogger()->debug("[TrezorDevice] handleMessage Features ");
330+
connectionManager_->GetLogger()->debug("[TrezorDevice] handleMessage Features, model: '{}' - {}.{}.{} ({})"
331+
, features_.model(), features_.major_version(), features_.minor_version(), features_.patch_version(), features_.revision());
312332
// + getJSONReadableMessage(features_));
313333
}
314334
}
@@ -339,7 +359,7 @@ void TrezorDevice::handleMessage(const MessageData& data)
339359
{
340360
common::PassphraseRequest request;
341361
if (parseResponse(request, data)) {
342-
emit requestHWPass();
362+
emit requestHWPass(hasCapability(management::Features_Capability_Capability_PassphraseEntry));
343363
sendTxMessage(HWInfoStatus::kRequestPassphrase);
344364
}
345365
}
@@ -398,7 +418,6 @@ void TrezorDevice::resetCaches()
398418
currentTxSignReq_.reset(nullptr);
399419
awaitingTransaction_ = {};
400420
awaitingWalletInfo_ = {};
401-
prevTxs_.clear();
402421
}
403422

404423
void TrezorDevice::setCallbackNoData(MessageType type, AsyncCallBack&& cb)
@@ -449,16 +468,17 @@ void TrezorDevice::handleTxRequest(const MessageData& data)
449468
{
450469
case bitcoin::TxRequest_RequestType_TXINPUT:
451470
{
452-
// Legacy inputs support
453471
if (!txRequest.details().tx_hash().empty()) {
454-
auto tx = prevTx(txRequest);
455-
auto txIn = tx.getTxInCopy(txRequest.details().request_index());
456-
457472
auto input = txAck.mutable_tx()->add_inputs();
458-
input->set_prev_hash(txIn.getOutPoint().getTxHash().copySwapEndian().toBinStr());
459-
input->set_prev_index(txIn.getOutPoint().getTxOutIndex());
460-
input->set_sequence(txIn.getSequence());
461-
input->set_script_sig(txIn.getScript().toBinStr());
473+
474+
auto tx = prevTx(txRequest);
475+
if (tx.isInitialized()) {
476+
auto txIn = tx.getTxInCopy(txRequest.details().request_index());
477+
input->set_prev_hash(txIn.getOutPoint().getTxHash().copySwapEndian().toBinStr());
478+
input->set_prev_index(txIn.getOutPoint().getTxOutIndex());
479+
input->set_sequence(txIn.getSequence());
480+
input->set_script_sig(txIn.getScript().toBinStr());
481+
}
462482

463483
connectionManager_->GetLogger()->debug("[TrezorDevice] handleTxRequest TXINPUT for prev hash"
464484
+ getJSONReadableMessage(txAck));
@@ -520,11 +540,12 @@ void TrezorDevice::handleTxRequest(const MessageData& data)
520540
// Legacy inputs support
521541
if (!txRequest.details().tx_hash().empty()) {
522542
auto tx = prevTx(txRequest);
523-
auto txOut = tx.getTxOutCopy(txRequest.details().request_index());
524-
525543
auto binOutput = txAck.mutable_tx()->add_bin_outputs();
526-
binOutput->set_amount(txOut.getValue());
527-
binOutput->set_script_pubkey(txOut.getScript().toBinStr());
544+
if (tx.isInitialized()) {
545+
auto txOut = tx.getTxOutCopy(txRequest.details().request_index());
546+
binOutput->set_amount(txOut.getValue());
547+
binOutput->set_script_pubkey(txOut.getScript().toBinStr());
548+
}
528549

529550
connectionManager_->GetLogger()->debug("[TrezorDevice] handleTxRequest TXOUTPUT for prev hash"
530551
+ getJSONReadableMessage(txAck));
@@ -593,12 +614,13 @@ void TrezorDevice::handleTxRequest(const MessageData& data)
593614
// Return previous tx details for legacy inputs
594615
// See https://wiki.trezor.io/Developers_guide:Message_Workflows
595616
auto tx = prevTx(txRequest);
596-
597617
auto data = txAck.mutable_tx();
598-
data->set_version(tx.getVersion());
599-
data->set_lock_time(tx.getLockTime());
600-
data->set_inputs_cnt(tx.getNumTxIn());
601-
data->set_outputs_cnt(tx.getNumTxOut());
618+
if (tx.isInitialized()) {
619+
data->set_version(tx.getVersion());
620+
data->set_lock_time(tx.getLockTime());
621+
data->set_inputs_cnt(tx.getNumTxIn());
622+
data->set_outputs_cnt(tx.getNumTxOut());
623+
}
602624

603625
connectionManager_->GetLogger()->debug("[TrezorDevice] handleTxRequest TXMETA"
604626
+ getJSONReadableMessage(txAck));
@@ -627,13 +649,53 @@ void TrezorDevice::sendTxMessage(const QString& status)
627649
emit deviceTxStatusChanged(status);
628650
}
629651

630-
const Tx &TrezorDevice::prevTx(const bitcoin::TxRequest &txRequest)
652+
Tx TrezorDevice::prevTx(const bitcoin::TxRequest &txRequest)
631653
{
632654
auto txHash = BinaryData::fromString(txRequest.details().tx_hash()).swapEndian();
633-
auto &tx = prevTxs_[txHash];
634-
if (!tx.isInitialized()) {
635-
auto txRaw = currentTxSignReq_->supportingTXs.at(txHash);
636-
tx = Tx(txRaw);
655+
auto supportingTxIt = currentTxSignReq_->supportingTXs.find(txHash);
656+
if (supportingTxIt == currentTxSignReq_->supportingTXs.end()) {
657+
SPDLOG_LOGGER_ERROR(connectionManager_->GetLogger(), "can't find prev TX {}", txHash.toHexStr(1));
658+
return {};
659+
}
660+
return Tx(supportingTxIt->second);
661+
}
662+
663+
bool TrezorDevice::hasCapability(management::Features::Capability cap) const
664+
{
665+
return std::find(features_.capabilities().begin(), features_.capabilities().end(), cap)
666+
!= features_.capabilities().end();
667+
}
668+
669+
bool TrezorDevice::isFirmwareSupported() const
670+
{
671+
auto verIt = kMinVersion.find(features_.model());
672+
if (verIt == kMinVersion.end()) {
673+
return false;
674+
}
675+
676+
const auto &minVer = verIt->second;
677+
if (features_.major_version() > minVer[0]) {
678+
return true;
679+
}
680+
if (features_.major_version() < minVer[0]) {
681+
return false;
682+
}
683+
if (features_.minor_version() > minVer[1]) {
684+
return true;
685+
}
686+
if (features_.minor_version() < minVer[1]) {
687+
return false;
688+
}
689+
return features_.patch_version() >= minVer[2];
690+
}
691+
692+
std::string TrezorDevice::firmwareSupportedVersion() const
693+
{
694+
auto verIt = kMinVersion.find(features_.model());
695+
if (verIt == kMinVersion.end()) {
696+
return fmt::format("Unknown model: {}", features_.model());
637697
}
638-
return tx;
698+
const auto &minVer = verIt->second;
699+
return fmt::format("Please update wallet firmware to version {}.{}.{} or later"
700+
, minVer[0], minVer[1], minVer[2]);
639701
}

BlockSettleHW/trezor/trezorDevice.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ class TrezorDevice : public HwDeviceInterface
4545
Q_OBJECT
4646

4747
public:
48-
TrezorDevice(const std::shared_ptr<ConnectionManager> &, std::shared_ptr<bs::sync::WalletsManager> walletManager, bool testNet
48+
TrezorDevice(const std::shared_ptr<ConnectionManager> &
49+
, std::shared_ptr<bs::sync::WalletsManager> walletManager, bool testNet
4950
, const QPointer<TrezorClient> &, QObject* parent = nullptr);
5051
~TrezorDevice() override;
5152

@@ -64,7 +65,7 @@ class TrezorDevice : public HwDeviceInterface
6465

6566
// Management
6667
void setMatrixPin(const std::string& pin) override;
67-
void setPassword(const std::string& password) override;
68+
void setPassword(const std::string& password, bool enterOnDevice) override;
6869

6970
// State
7071
bool isBlocked() override {
@@ -91,9 +92,15 @@ class TrezorDevice : public HwDeviceInterface
9192
void sendTxMessage(const QString& status);
9293

9394
// Returns previous Tx for legacy inputs
94-
const Tx &prevTx(const hw::trezor::messages::bitcoin::TxRequest &txRequest);
95+
// Trezor could request non-existing hash if wrong passphrase entered
96+
Tx prevTx(const hw::trezor::messages::bitcoin::TxRequest &txRequest);
9597

9698
private:
99+
bool hasCapability(hw::trezor::messages::management::Features::Capability cap) const;
100+
101+
bool isFirmwareSupported() const;
102+
std::string firmwareSupportedVersion() const;
103+
97104
std::shared_ptr<ConnectionManager> connectionManager_{};
98105
std::shared_ptr<bs::sync::WalletsManager> walletManager_{};
99106

@@ -107,7 +114,6 @@ class TrezorDevice : public HwDeviceInterface
107114
bool txSignedByUser_ = false;
108115
std::unordered_map<int, AsyncCallBack> awaitingCallbackNoData_;
109116
std::unordered_map<int, AsyncCallBackCall> awaitingCallbackData_;
110-
std::map<BinaryData, Tx> prevTxs_;
111117
};
112118

113119
#endif // TREZORDEVICE_H

BlockSettleSigner/WalletsProxy.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,13 @@ void WalletsProxy::importHwWallet(HwWalletWrapper walletInfo, const QJSValue &js
804804
});
805805
};
806806

807+
if (!walletInfo.isFirmwareSupported_) {
808+
bs::sync::WatchingOnlyWallet result;
809+
result.description = walletInfo.firmwareSupportedMsg_;
810+
cb(result);
811+
return;
812+
}
813+
807814
adapter_->importHwWallet(walletInfo.info_, cb);
808815
}
809816

BlockSettleSigner/qml/BsDialogs/TxSignDialog.qml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ BSWalletHandlerDialog {
9292
target: hwDeviceManager
9393
onRequestPinMatrix: JsHelper.showHwPinMatrix(0);
9494
onDeviceReady: hwDeviceManager.signTX(passwordDialogData.TxRequest);
95+
onRequestHWPass: JsHelper.showHwPassphrase(0, allowedOnDevice);
9596
onDeviceNotFound: {
9697
hwDeviceStatus = "Searching for device"
9798
let lastDeviceError = hwDeviceManager.lastDeviceError(0);

BlockSettleSigner/qml/BsDialogs/TxSignSettlementBaseDialog.qml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ CustomTitleDialogWindowWithExpander {
166166
target: hwDeviceManager
167167
onRequestPinMatrix: JsHelper.showHwPinMatrix(0);
168168
onDeviceReady: hwDeviceManager.signTX(passwordDialogData.TxRequest);
169+
onRequestHWPass: JsHelper.showHwPassphrase(0, allowedOnDevice);
169170
onDeviceNotFound: {
170171
hwDeviceStatus = qsTr("Searching for device")
171172
let lastDeviceError = hwDeviceManager.lastDeviceError(0);

0 commit comments

Comments
 (0)