feat(common): introduce `Failure_InProgress` code
What changed, and why it matters
This commit adds a new error code called Failure_InProgress to the Trezor firmware's communication protocol. It does not change any security logic; it simply gives the device a standardized way to tell a connected computer that a non-interruptible task is currently running. The actual behavior of blocking or allowing interruptions is not part of this change.
No security action required. Treat as a normal feature commit. Review the follow-up commits that actually emit Failure_InProgress to ensure non-interruptible workflows are enforced safely.
Security signals we found
No security-sensitive logic changed
New enum value only; no new handlers or state-machine changes
No buffer, memory, or cryptographic changes
No privilege boundary crossed
Evidence from the diff
The change introduces a new FailureType enum value, Failure_InProgress = 19, across the protobuf definition, Python/Rust host libraries, and legacy firmware’s fsm_sendFailure switch statement. The legacy firmware maps this code to the localized string “Operation in progress”. No code paths actually emit this new failure yet, and no workflow logic is modified. The bulk of the diff is regenerated protobuf serialization bytes.
Changed components
common/protob/messages-common.protocore/src/trezor/enums/FailureType.pycore/src/trezor/enums/__init__.pylegacy/firmware/fsm.cpython/src/trezorlib/messages.pyrust/trezor-client/src/protos/generated/messages_common.rsInspect captured patch +76 / −63
diff --git a/common/protob/messages-common.proto b/common/protob/messages-common.proto
index fccde25b..6e6300b8 100644
--- a/common/protob/messages-common.proto
+++ b/common/protob/messages-common.proto
@@ -43,6 +43,7 @@ message Failure {
Failure_ThpUnallocatedSession = 16;
Failure_InvalidProtocol = 17;
reserved 18;
+ Failure_InProgress = 19;
Failure_FirmwareError = 99;
}
}
diff --git a/core/src/trezor/enums/FailureType.py b/core/src/trezor/enums/FailureType.py
index c3ff2a27..8534afd9 100644
--- a/core/src/trezor/enums/FailureType.py
+++ b/core/src/trezor/enums/FailureType.py
@@ -20,6 +20,7 @@ WipeCodeMismatch = 13
InvalidSession = 14
Busy = 15
InvalidProtocol = 17
+InProgress = 19
FirmwareError = 99
if utils.USE_THP:
ThpUnallocatedSession = 16
diff --git a/core/src/trezor/enums/__init__.py b/core/src/trezor/enums/__init__.py
index 8e057cea..227e3127 100644
--- a/core/src/trezor/enums/__init__.py
+++ b/core/src/trezor/enums/__init__.py
@@ -25,6 +25,7 @@ if TYPE_CHECKING:
Busy = 15
ThpUnallocatedSession = 16
InvalidProtocol = 17
+ InProgress = 19
FirmwareError = 99
class ButtonRequestType(IntEnum):
diff --git a/legacy/firmware/fsm.c b/legacy/firmware/fsm.c
index 6627abd6..9b16ecd3 100644
--- a/legacy/firmware/fsm.c
+++ b/legacy/firmware/fsm.c
@@ -200,6 +200,9 @@ void fsm_sendFailure(FailureType code, const char *text)
case FailureType_Failure_InvalidProtocol:
text = _("Invalid protocol");
break;
+ case FailureType_Failure_InProgress:
+ text = _("Operation in progress");
+ break;
case FailureType_Failure_FirmwareError:
text = _("Firmware error");
break;
diff --git a/python/src/trezorlib/messages.py b/python/src/trezorlib/messages.py
index c0096fae..8184e580 100644
--- a/python/src/trezorlib/messages.py
+++ b/python/src/trezorlib/messages.py
@@ -26,6 +26,7 @@ class FailureType(IntEnum):
Busy = 15
ThpUnallocatedSession = 16
InvalidProtocol = 17
+ InProgress = 19
FirmwareError = 99
diff --git a/rust/trezor-client/src/protos/generated/messages_common.rs b/rust/trezor-client/src/protos/generated/messages_common.rs
index b032b217..734a1482 100644
--- a/rust/trezor-client/src/protos/generated/messages_common.rs
+++ b/rust/trezor-client/src/protos/generated/messages_common.rs
@@ -419,6 +419,8 @@ pub mod failure {
Failure_ThpUnallocatedSession = 16,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.common.Failure.FailureType.Failure_InvalidProtocol)
Failure_InvalidProtocol = 17,
+ // @@protoc_insertion_point(enum_value:hw.trezor.messages.common.Failure.FailureType.Failure_InProgress)
+ Failure_InProgress = 19,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.common.Failure.FailureType.Failure_FirmwareError)
Failure_FirmwareError = 99,
}
@@ -449,6 +451,7 @@ pub mod failure {
15 => ::std::option::Option::Some(FailureType::Failure_Busy),
16 => ::std::option::Option::Some(FailureType::Failure_ThpUnallocatedSession),
17 => ::std::option::Option::Some(FailureType::Failure_InvalidProtocol),
+ 19 => ::std::option::Option::Some(FailureType::Failure_InProgress),
99 => ::std::option::Option::Some(FailureType::Failure_FirmwareError),
_ => ::std::option::Option::None
}
@@ -473,6 +476,7 @@ pub mod failure {
"Failure_Busy" => ::std::option::Option::Some(FailureType::Failure_Busy),
"Failure_ThpUnallocatedSession" => ::std::option::Option::Some(FailureType::Failure_ThpUnallocatedSession),
"Failure_InvalidProtocol" => ::std::option::Option::Some(FailureType::Failure_InvalidProtocol),
+ "Failure_InProgress" => ::std::option::Option::Some(FailureType::Failure_InProgress),
"Failure_FirmwareError" => ::std::option::Option::Some(FailureType::Failure_FirmwareError),
_ => ::std::option::Option::None
}
@@ -496,6 +500,7 @@ pub mod failure {
FailureType::Failure_Busy,
FailureType::Failure_ThpUnallocatedSession,
FailureType::Failure_InvalidProtocol,
+ FailureType::Failure_InProgress,
FailureType::Failure_FirmwareError,
];
}
@@ -525,7 +530,8 @@ pub mod failure {
FailureType::Failure_Busy => 14,
FailureType::Failure_ThpUnallocatedSession => 15,
FailureType::Failure_InvalidProtocol => 16,
- FailureType::Failure_FirmwareError => 17,
+ FailureType::Failure_InProgress => 17,
+ FailureType::Failure_FirmwareError => 18,
};
Self::enum_descriptor().value_by_index(index)
}
@@ -4005,9 +4011,9 @@ pub mod payment_request {
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x15messages-common.proto\x12\x19hw.trezor.messages.common\x1a\roption\
s.proto\"%\n\x07Success\x12\x1a\n\x07message\x18\x01\x20\x01(\t:\0R\x07m\
- essage\"\xe7\x04\n\x07Failure\x12B\n\x04code\x18\x01\x20\x01(\x0e2..hw.t\
+ essage\"\xff\x04\n\x07Failure\x12B\n\x04code\x18\x01\x20\x01(\x0e2..hw.t\
rezor.messages.common.Failure.FailureTypeR\x04code\x12\x18\n\x07message\
- \x18\x02\x20\x01(\tR\x07message\"\xfd\x03\n\x0bFailureType\x12\x1d\n\x19\
+ \x18\x02\x20\x01(\tR\x07message\"\x95\x04\n\x0bFailureType\x12\x1d\n\x19\
Failure_UnexpectedMessage\x10\x01\x12\x1a\n\x16Failure_ButtonExpected\
\x10\x02\x12\x15\n\x11Failure_DataError\x10\x03\x12\x1b\n\x17Failure_Act\
ionCancelled\x10\x04\x12\x17\n\x13Failure_PinExpected\x10\x05\x12\x18\n\
@@ -4018,66 +4024,66 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\x12\x1c\n\x18Failure_WipeCodeMismatch\x10\r\x12\x1a\n\x16Failure_Invali\
dSession\x10\x0e\x12\x10\n\x0cFailure_Busy\x10\x0f\x12!\n\x1dFailure_Thp\
UnallocatedSession\x10\x10\x12\x1b\n\x17Failure_InvalidProtocol\x10\x11\
- \x12\x19\n\x15Failure_FirmwareError\x10c\"\x04\x08\x12\x10\x12\"\xab\x06\
- \n\rButtonRequest\x12N\n\x04code\x18\x01\x20\x01(\x0e2:.hw.trezor.messag\
- es.common.ButtonRequest.ButtonRequestTypeR\x04code\x12\x14\n\x05pages\
- \x18\x02\x20\x01(\rR\x05pages\x12\x12\n\x04name\x18\x04\x20\x01(\tR\x04n\
- ame\"\x99\x05\n\x11ButtonRequestType\x12\x17\n\x13ButtonRequest_Other\
- \x10\x01\x12\"\n\x1eButtonRequest_FeeOverThreshold\x10\x02\x12\x1f\n\x1b\
- ButtonRequest_ConfirmOutput\x10\x03\x12\x1d\n\x19ButtonRequest_ResetDevi\
- ce\x10\x04\x12\x1d\n\x19ButtonRequest_ConfirmWord\x10\x05\x12\x1c\n\x18B\
- uttonRequest_WipeDevice\x10\x06\x12\x1d\n\x19ButtonRequest_ProtectCall\
- \x10\x07\x12\x18\n\x14ButtonRequest_SignTx\x10\x08\x12\x1f\n\x1bButtonRe\
- quest_FirmwareCheck\x10\t\x12\x19\n\x15ButtonRequest_Address\x10\n\x12\
- \x1b\n\x17ButtonRequest_PublicKey\x10\x0b\x12#\n\x1fButtonRequest_Mnemon\
- icWordCount\x10\x0c\x12\x1f\n\x1bButtonRequest_MnemonicInput\x10\r\x120\
- \n(_Deprecated_ButtonRequest_PassphraseType\x10\x0e\x1a\x02\x08\x01\x12'\
- \n#ButtonRequest_UnknownDerivationPath\x10\x0f\x12\"\n\x1eButtonRequest_\
- RecoveryHomepage\x10\x10\x12\x19\n\x15ButtonRequest_Success\x10\x11\x12\
- \x19\n\x15ButtonRequest_Warning\x10\x12\x12!\n\x1dButtonRequest_Passphra\
- seEntry\x10\x13\x12\x1a\n\x16ButtonRequest_PinEntry\x10\x14J\x04\x08\x03\
- \x10\x04\"\x0b\n\tButtonAck\"\xbb\x02\n\x10PinMatrixRequest\x12T\n\x04ty\
- pe\x18\x01\x20\x01(\x0e2@.hw.trezor.messages.common.PinMatrixRequest.Pin\
- MatrixRequestTypeR\x04type\"\xd0\x01\n\x14PinMatrixRequestType\x12\x20\n\
- \x1cPinMatrixRequestType_Current\x10\x01\x12!\n\x1dPinMatrixRequestType_\
- NewFirst\x10\x02\x12\"\n\x1ePinMatrixRequestType_NewSecond\x10\x03\x12&\
- \n\"PinMatrixRequestType_WipeCodeFirst\x10\x04\x12'\n#PinMatrixRequestTy\
- pe_WipeCodeSecond\x10\x05\"\x20\n\x0cPinMatrixAck\x12\x10\n\x03pin\x18\
- \x01\x20\x02(\tR\x03pin\"5\n\x11PassphraseRequest\x12\x20\n\n_on_device\
- \x18\x01\x20\x01(\x08R\x08OnDeviceB\x02\x18\x01\"g\n\rPassphraseAck\x12\
- \x1e\n\npassphrase\x18\x01\x20\x01(\tR\npassphrase\x12\x19\n\x06_state\
- \x18\x02\x20\x01(\x0cR\x05StateB\x02\x18\x01\x12\x1b\n\ton_device\x18\
- \x03\x20\x01(\x08R\x08onDevice\"=\n!Deprecated_PassphraseStateRequest\
- \x12\x14\n\x05state\x18\x01\x20\x01(\x0cR\x05state:\x02\x18\x01\"#\n\x1d\
- Deprecated_PassphraseStateAck:\x02\x18\x01\"\xc0\x01\n\nHDNodeType\x12\
- \x14\n\x05depth\x18\x01\x20\x02(\rR\x05depth\x12\x20\n\x0bfingerprint\
- \x18\x02\x20\x02(\rR\x0bfingerprint\x12\x1b\n\tchild_num\x18\x03\x20\x02\
- (\rR\x08childNum\x12\x1d\n\nchain_code\x18\x04\x20\x02(\x0cR\tchainCode\
- \x12\x1f\n\x0bprivate_key\x18\x05\x20\x01(\x0cR\nprivateKey\x12\x1d\n\np\
- ublic_key\x18\x06\x20\x02(\x0cR\tpublicKey\"\xb4\x07\n\x0ePaymentRequest\
- \x12\x14\n\x05nonce\x18\x01\x20\x01(\x0cR\x05nonce\x12%\n\x0erecipient_n\
- ame\x18\x02\x20\x02(\tR\rrecipientName\x12R\n\x05memos\x18\x03\x20\x03(\
- \x0b2<.hw.trezor.messages.common.PaymentRequest.PaymentRequestMemoR\x05m\
- emos\x12\x16\n\x06amount\x18\x06\x20\x01(\x0cR\x06amount\x12\x1c\n\tsign\
- ature\x18\x05\x20\x02(\x0cR\tsignature\x1a\x8d\x03\n\x12PaymentRequestMe\
- mo\x12O\n\ttext_memo\x18\x01\x20\x01(\x0b22.hw.trezor.messages.common.Pa\
- ymentRequest.TextMemoR\x08textMemo\x12U\n\x0brefund_memo\x18\x02\x20\x01\
- (\x0b24.hw.trezor.messages.common.PaymentRequest.RefundMemoR\nrefundMemo\
- \x12h\n\x12coin_purchase_memo\x18\x03\x20\x01(\x0b2:.hw.trezor.messages.\
- common.PaymentRequest.CoinPurchaseMemoR\x10coinPurchaseMemo\x12e\n\x11te\
- xt_details_memo\x18\x04\x20\x01(\x0b29.hw.trezor.messages.common.Payment\
- Request.TextDetailsMemoR\x0ftextDetailsMemo\x1a\x1e\n\x08TextMemo\x12\
- \x12\n\x04text\x18\x01\x20\x02(\tR\x04text\x1a;\n\x0fTextDetailsMemo\x12\
- \x14\n\x05title\x18\x01\x20\x02(\tR\x05title\x12\x12\n\x04text\x18\x02\
- \x20\x02(\tR\x04text\x1aU\n\nRefundMemo\x12\x18\n\x07address\x18\x01\x20\
- \x02(\tR\x07address\x12\x1b\n\taddress_n\x18\x02\x20\x03(\rR\x08addressN\
- \x12\x10\n\x03mac\x18\x03\x20\x02(\x0cR\x03mac\x1a\x90\x01\n\x10CoinPurc\
- haseMemo\x12\x1b\n\tcoin_type\x18\x01\x20\x02(\rR\x08coinType\x12\x16\n\
- \x06amount\x18\x02\x20\x02(\tR\x06amount\x12\x18\n\x07address\x18\x03\
- \x20\x02(\tR\x07address\x12\x1b\n\taddress_n\x18\x04\x20\x03(\rR\x08addr\
- essN\x12\x10\n\x03mac\x18\x05\x20\x02(\x0cR\x03macJ\x04\x08\x04\x10\x05B\
- >\n#com.satoshilabs.trezor.lib.protobufB\x13TrezorMessageCommon\x80\xa6\
- \x1d\x01\
+ \x12\x16\n\x12Failure_InProgress\x10\x13\x12\x19\n\x15Failure_FirmwareEr\
+ ror\x10c\"\x04\x08\x12\x10\x12\"\xab\x06\n\rButtonRequest\x12N\n\x04code\
+ \x18\x01\x20\x01(\x0e2:.hw.trezor.messages.common.ButtonRequest.ButtonRe\
+ questTypeR\x04code\x12\x14\n\x05pages\x18\x02\x20\x01(\rR\x05pages\x12\
+ \x12\n\x04name\x18\x04\x20\x01(\tR\x04name\"\x99\x05\n\x11ButtonRequestT\
+ ype\x12\x17\n\x13ButtonRequest_Other\x10\x01\x12\"\n\x1eButtonRequest_Fe\
+ eOverThreshold\x10\x02\x12\x1f\n\x1bButtonRequest_ConfirmOutput\x10\x03\
+ \x12\x1d\n\x19ButtonRequest_ResetDevice\x10\x04\x12\x1d\n\x19ButtonReque\
+ st_ConfirmWord\x10\x05\x12\x1c\n\x18ButtonRequest_WipeDevice\x10\x06\x12\
+ \x1d\n\x19ButtonRequest_ProtectCall\x10\x07\x12\x18\n\x14ButtonRequest_S\
+ ignTx\x10\x08\x12\x1f\n\x1bButtonRequest_FirmwareCheck\x10\t\x12\x19\n\
+ \x15ButtonRequest_Address\x10\n\x12\x1b\n\x17ButtonRequest_PublicKey\x10\
+ \x0b\x12#\n\x1fButtonRequest_MnemonicWordCount\x10\x0c\x12\x1f\n\x1bButt\
+ onRequest_MnemonicInput\x10\r\x120\n(_Deprecated_ButtonRequest_Passphras\
+ eType\x10\x0e\x1a\x02\x08\x01\x12'\n#ButtonRequest_UnknownDerivationPath\
+ \x10\x0f\x12\"\n\x1eButtonRequest_RecoveryHomepage\x10\x10\x12\x19\n\x15\
+ ButtonRequest_Success\x10\x11\x12\x19\n\x15ButtonRequest_Warning\x10\x12\
+ \x12!\n\x1dButtonRequest_PassphraseEntry\x10\x13\x12\x1a\n\x16ButtonRequ\
+ est_PinEntry\x10\x14J\x04\x08\x03\x10\x04\"\x0b\n\tButtonAck\"\xbb\x02\n\
+ \x10PinMatrixRequest\x12T\n\x04type\x18\x01\x20\x01(\x0e2@.hw.trezor.mes\
+ sages.common.PinMatrixRequest.PinMatrixRequestTypeR\x04type\"\xd0\x01\n\
+ \x14PinMatrixRequestType\x12\x20\n\x1cPinMatrixRequestType_Current\x10\
+ \x01\x12!\n\x1dPinMatrixRequestType_NewFirst\x10\x02\x12\"\n\x1ePinMatri\
+ xRequestType_NewSecond\x10\x03\x12&\n\"PinMatrixRequestType_WipeCodeFirs\
+ t\x10\x04\x12'\n#PinMatrixRequestType_WipeCodeSecond\x10\x05\"\x20\n\x0c\
+ PinMatrixAck\x12\x10\n\x03pin\x18\x01\x20\x02(\tR\x03pin\"5\n\x11Passphr\
+ aseRequest\x12\x20\n\n_on_device\x18\x01\x20\x01(\x08R\x08OnDeviceB\x02\
+ \x18\x01\"g\n\rPassphraseAck\x12\x1e\n\npassphrase\x18\x01\x20\x01(\tR\n\
+ passphrase\x12\x19\n\x06_state\x18\x02\x20\x01(\x0cR\x05StateB\x02\x18\
+ \x01\x12\x1b\n\ton_device\x18\x03\x20\x01(\x08R\x08onDevice\"=\n!Depreca\
+ ted_PassphraseStateRequest\x12\x14\n\x05state\x18\x01\x20\x01(\x0cR\x05s\
+ tate:\x02\x18\x01\"#\n\x1dDeprecated_PassphraseStateAck:\x02\x18\x01\"\
+ \xc0\x01\n\nHDNodeType\x12\x14\n\x05depth\x18\x01\x20\x02(\rR\x05depth\
+ \x12\x20\n\x0bfingerprint\x18\x02\x20\x02(\rR\x0bfingerprint\x12\x1b\n\t\
+ child_num\x18\x03\x20\x02(\rR\x08childNum\x12\x1d\n\nchain_code\x18\x04\
+ \x20\x02(\x0cR\tchainCode\x12\x1f\n\x0bprivate_key\x18\x05\x20\x01(\x0cR\
+ \nprivateKey\x12\x1d\n\npublic_key\x18\x06\x20\x02(\x0cR\tpublicKey\"\
+ \xb4\x07\n\x0ePaymentRequest\x12\x14\n\x05nonce\x18\x01\x20\x01(\x0cR\
+ \x05nonce\x12%\n\x0erecipient_name\x18\x02\x20\x02(\tR\rrecipientName\
+ \x12R\n\x05memos\x18\x03\x20\x03(\x0b2<.hw.trezor.messages.common.Paymen\
+ tRequest.PaymentRequestMemoR\x05memos\x12\x16\n\x06amount\x18\x06\x20\
+ \x01(\x0cR\x06amount\x12\x1c\n\tsignature\x18\x05\x20\x02(\x0cR\tsignatu\
+ re\x1a\x8d\x03\n\x12PaymentRequestMemo\x12O\n\ttext_memo\x18\x01\x20\x01\
+ (\x0b22.hw.trezor.messages.common.PaymentRequest.TextMemoR\x08textMemo\
+ \x12U\n\x0brefund_memo\x18\x02\x20\x01(\x0b24.hw.trezor.messages.common.\
+ PaymentRequest.RefundMemoR\nrefundMemo\x12h\n\x12coin_purchase_memo\x18\
+ \x03\x20\x01(\x0b2:.hw.trezor.messages.common.PaymentRequest.CoinPurchas\
+ eMemoR\x10coinPurchaseMemo\x12e\n\x11text_details_memo\x18\x04\x20\x01(\
+ \x0b29.hw.trezor.messages.common.PaymentRequest.TextDetailsMemoR\x0ftext\
+ DetailsMemo\x1a\x1e\n\x08TextMemo\x12\x12\n\x04text\x18\x01\x20\x02(\tR\
+ \x04text\x1a;\n\x0fTextDetailsMemo\x12\x14\n\x05title\x18\x01\x20\x02(\t\
+ R\x05title\x12\x12\n\x04text\x18\x02\x20\x02(\tR\x04text\x1aU\n\nRefundM\
+ emo\x12\x18\n\x07address\x18\x01\x20\x02(\tR\x07address\x12\x1b\n\taddre\
+ ss_n\x18\x02\x20\x03(\rR\x08addressN\x12\x10\n\x03mac\x18\x03\x20\x02(\
+ \x0cR\x03mac\x1a\x90\x01\n\x10CoinPurchaseMemo\x12\x1b\n\tcoin_type\x18\
+ \x01\x20\x02(\rR\x08coinType\x12\x16\n\x06amount\x18\x02\x20\x02(\tR\x06\
+ amount\x12\x18\n\x07address\x18\x03\x20\x02(\tR\x07address\x12\x1b\n\tad\
+ dress_n\x18\x04\x20\x03(\rR\x08addressN\x12\x10\n\x03mac\x18\x05\x20\x02\
+ (\x0cR\x03macJ\x04\x08\x04\x10\x05B>\n#com.satoshilabs.trezor.lib.protob\
+ ufB\x13TrezorMessageCommon\x80\xa6\x1d\x01\
";
/// `FileDescriptorProto` object which was a source for this generated file
Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.