refactor: remove unused QR code protocols
What changed, and why it matters
This commit removes old, custom QR-code transaction formats for Bitcoin-family coins, Ethereum, and XRP, and replaces them with standardized formats. It also adds explicit rejections when the device receives a transaction through the generic 'ur:bytes' QR type for Bitcoin and Ethereum. The change is described by the vendor as a cleanup of unused protocols, but it also closes a path where a specially crafted QR code could potentially be misinterpreted as a valid transaction.
Treat this as a security-hardening refactor. Verify that all call sites of the removed *_bytes functions have been updated and that no fallback code path still accepts ur:bytes for BTC/ETH/XRP. Review whether other chains still allowed through ur:bytes (e.g., Tron) perform sufficient validation, since the generic inference path remains open for non-BTC/non-ETH view types.
Security signals we found
Removal of custom protobuf-based QR transaction paths reduces attack surface
Explicit rejection of ur:bytes for Bitcoin-family and Ethereum transactions
Legacy handlers used unwrap() and raw protobuf deserialization on untrusted QR input
XRP legacy signing derived a child xpub and built a JSON transaction from protobuf fields with multiple unwrap() calls
Ethereum legacy signing decoded a protobuf payload, extracted a legacy transaction, signed it, and returned a protobuf result
Evidence from the diff
The patch deletes the legacy ‘Keystone bytes’ protobuf-based handlers for Ethereum and XRP (eth_sign_tx_bytes, eth_parse_bytes_data, eth_check_ur_bytes, xrp_sign_tx_bytes, xrp_parse_bytes_tx, xrp_check_tx_bytes, is_keystone_xrp_tx) and removes XRP from the generic Keystone-bytes view-type inference. For Bitcoin-family coins it adds explicit guards in utxo_parse_keystone, utxo_sign_keystone, and utxo_check_keystone that reject QRCodeType::Bytes. The generic bytes inference now returns NotSupportURTypeError for Bitcoin-family and Ethereum transactions, while still allowing other chains. The C UI code no longer branches on urType == Bytes for BTC, ETH, or XRP.
Changed components
rust/rust_c/src/bitcoin/legacy.rsrust/rust_c/src/common/ur_ext.rsrust/rust_c/src/ethereum/mod.rsrust/rust_c/src/xrp/mod.rssrc/ui/gui_chain/gui_btc.csrc/ui/gui_chain/multi/web3/gui_eth.csrc/ui/gui_chain/multi/web3/gui_xrp.cInspect captured patch +58 / −506
diff --git a/rust/rust_c/src/bitcoin/legacy.rs b/rust/rust_c/src/bitcoin/legacy.rs
index 9e56acc..7384783 100644
--- a/rust/rust_c/src/bitcoin/legacy.rs
+++ b/rust/rust_c/src/bitcoin/legacy.rs
@@ -7,6 +7,7 @@ use crate::common::types::{PtrBytes, PtrString, PtrT, PtrUR};
use crate::common::ur::{QRCodeType, UREncodeResult};
use crate::extract_array;
use alloc::boxed::Box;
+use alloc::string::ToString;
#[no_mangle]
pub unsafe extern "C" fn utxo_parse_keystone(
@@ -16,6 +17,12 @@ pub unsafe extern "C" fn utxo_parse_keystone(
length: u32,
x_pub: PtrString,
) -> *mut TransactionParseResult<DisplayTx> {
+ if matches!(ur_type, QRCodeType::Bytes) {
+ return TransactionParseResult::from(RustCError::UnsupportedTransaction(
+ "bitcoin-family transactions are not supported via ur:bytes".to_string(),
+ ))
+ .c_ptr();
+ }
if length != 4 {
return TransactionParseResult::from(RustCError::InvalidMasterFingerprint).c_ptr();
}
@@ -51,6 +58,12 @@ pub unsafe extern "C" fn utxo_sign_keystone(
seed: PtrBytes,
seed_len: u32,
) -> *mut UREncodeResult {
+ if matches!(ur_type, QRCodeType::Bytes) {
+ return UREncodeResult::from(RustCError::UnsupportedTransaction(
+ "bitcoin-family transactions are not supported via ur:bytes".to_string(),
+ ))
+ .c_ptr();
+ }
let seed = extract_array!(seed, u8, seed_len as usize);
keystone::sign(
ptr,
@@ -71,5 +84,11 @@ pub unsafe extern "C" fn utxo_check_keystone(
length: u32,
x_pub: PtrString,
) -> PtrT<TransactionCheckResult> {
+ if matches!(ur_type, QRCodeType::Bytes) {
+ return TransactionCheckResult::from(RustCError::UnsupportedTransaction(
+ "bitcoin-family transactions are not supported via ur:bytes".to_string(),
+ ))
+ .c_ptr();
+ }
keystone::check(ptr, ur_type, master_fingerprint, length, x_pub)
}
diff --git a/rust/rust_c/src/common/ur_ext.rs b/rust/rust_c/src/common/ur_ext.rs
index 38c1215..ef9d2fa 100644
--- a/rust/rust_c/src/common/ur_ext.rs
+++ b/rust/rust_c/src/common/ur_ext.rs
@@ -291,8 +291,6 @@ fn get_view_type_from_keystone(bytes: Vec<u8>) -> Result<ViewType, URError> {
ViewType::TronTx
}
}
- #[cfg(feature = "xrp")]
- "XRP" => ViewType::XRPTx,
_ => {
return Err(URError::ProtobufDecodeError(format!(
"invalid coin_code {:?}",
@@ -335,7 +333,23 @@ impl InferViewType for Bytes {
return Err(URError::UrDecodeError("invalid data".to_string()));
}
#[cfg(feature = "multi-coins")]
- Err(_e) => get_view_type_from_keystone(self.get_bytes()),
+ Err(_e) => {
+ let view_type = get_view_type_from_keystone(self.get_bytes())?;
+ match view_type {
+ ViewType::BtcNativeSegwitTx
+ | ViewType::BtcSegwitTx
+ | ViewType::BtcLegacyTx
+ | ViewType::LtcTx
+ | ViewType::DogeTx
+ | ViewType::DashTx
+ | ViewType::BchTx
+ | ViewType::EthTx => Err(URError::NotSupportURTypeError(
+ "bitcoin-family and ethereum transactions are not supported via ur:bytes"
+ .to_string(),
+ )),
+ _ => Ok(view_type),
+ }
+ }
#[cfg(feature = "btc-only")]
Err(_e) => {
if app_bitcoin::multi_sig::wallet::is_valid_xpub_config(&self) {
@@ -344,7 +358,9 @@ impl InferViewType for Bytes {
if app_bitcoin::multi_sig::wallet::is_valid_wallet_config(&self) {
return Ok(ViewType::MultisigWalletImport);
}
- get_view_type_from_keystone(self.get_bytes())
+ Err(URError::NotSupportURTypeError(
+ "bitcoin transactions are not supported via ur:bytes".to_string(),
+ ))
}
#[cfg(not(any(feature = "btc-only", feature = "multi-coins")))]
Err(_e) => Err(URError::UrDecodeError("invalid data".to_string())),
@@ -452,14 +468,13 @@ mod tests {
#[cfg(feature = "ltc")]
#[test]
- fn test_parse_ur_type() {
+ fn test_reject_ltc_keystone_bytes() {
{
//ltc legacy
let crypto = Bytes::new(
Vec::from_hex("1f8b0800000000000003558dbb4a03411846b36be192266baa902a2c8212583233ffdc162ccc0d63349268306837333b2b1875558c0979061fc0c242ec051b0b0b5b0b3bc156b0147d005bd30a1f070e1cf83c379feb9dd7d3d896bae7e9456ad2a3e2a7ebb9794f20d16c36783d7873b3739bfd7a7e9131ce12442124dcaa902a2dc32851101a3086608b2dc4b498293d7e3dddfda2654f5fbbdeeb82ff5e2e66825b27bbaa58a48d564a598cf54c4052a096c4334a42c1320b11610c63c60d5560a5b442c70669a264c239f84e713d5b43444422a20a4b6c1281ad8a88c51a04274c01235672c18d4418255881e1d6628230301dc78831008349e1e5fedb0b72c7151a2d55c85205cd5641e5301b74d6b8185407fbfcb0795c8dc4e660d4dc6ef787b59a386d75d2dde4e0d0ff7cb8720a9920535e99e583eaeede683c9d801e9eb5b6366abd8bbdc664e7723a1df346efa43d4efd9b9f8ff98213e43affcf4acfdd3f9997819c79010000").unwrap()
);
- let view_type = InferViewType::infer(&crypto).unwrap();
- assert_eq!(ViewType::LtcTx, view_type);
+ assert!(InferViewType::infer(&crypto).is_err());
}
}
}
diff --git a/rust/rust_c/src/ethereum/mod.rs b/rust/rust_c/src/ethereum/mod.rs
index c3d0ae1..34c99b2 100644
--- a/rust/rust_c/src/ethereum/mod.rs
+++ b/rust/rust_c/src/ethereum/mod.rs
@@ -2,34 +2,24 @@ use alloc::string::{String, ToString};
use alloc::vec::Vec;
use alloc::{format, slice};
-use app_ethereum::address::derive_address;
use app_ethereum::batch_tx_rules::rule_swap;
use app_ethereum::erc20::{parse_erc20_approval, parse_erc20_transfer};
use app_ethereum::errors::EthereumError;
use app_ethereum::{
parse_fee_market_tx, parse_legacy_tx, parse_personal_message, parse_typed_data_message,
- LegacyTransaction, TransactionSignature,
};
-use cryptoxide::hashing::keccak256;
use keystore::algorithms::secp256k1::derive_public_key;
use ur_registry::ethereum::eth_batch_sign_requests::EthBatchSignRequest;
use ur_registry::ethereum::eth_batch_signature::EthBatchSignature;
use ur_registry::ethereum::eth_sign_request::EthSignRequest;
use ur_registry::ethereum::eth_signature::EthSignature;
-use ur_registry::pb;
-use ur_registry::pb::protoc::base::Content::ColdVersion;
-use ur_registry::pb::protoc::payload::Content;
-use ur_registry::pb::protoc::sign_transaction::Transaction::EthTx;
use ur_registry::traits::RegistryItem;
-use crate::common::errors::{KeystoneError, RustCError};
-use crate::common::keystone::build_payload;
+use crate::common::errors::RustCError;
use crate::common::structs::{Response, TransactionCheckResult, TransactionParseResult};
use crate::common::types::{PtrBytes, PtrString, PtrT, PtrUR};
-use crate::common::ur::{
- QRCodeType, UREncodeResult, FRAGMENT_MAX_LENGTH_DEFAULT, FRAGMENT_UNLIMITED_LENGTH,
-};
+use crate::common::ur::{UREncodeResult, FRAGMENT_MAX_LENGTH_DEFAULT, FRAGMENT_UNLIMITED_LENGTH};
use crate::common::utils::{convert_c_char, recover_c_char};
use crate::common::KEYSTONE;
use crate::{extract_array, extract_array_mut, extract_ptr_with_type};
@@ -44,52 +34,6 @@ pub mod address;
pub mod structs;
pub(crate) mod util;
-unsafe fn extract_sign_tx_from_payload(
- ptr: PtrUR,
-) -> Result<ur_registry::pb::protoc::SignTransaction, KeystoneError> {
- let payload = build_payload(ptr, QRCodeType::Bytes)?;
- let content = payload
- .content
- .ok_or_else(|| KeystoneError::ProtobufError("empty payload content".to_string()))?;
- match content {
- Content::SignTx(sign_tx) => Ok(sign_tx),
- _ => Err(KeystoneError::ProtobufError(
- "Cant get sign tx struct data".to_string(),
- )),
- }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn eth_check_ur_bytes(
- ptr: PtrUR,
- master_fingerprint: PtrBytes,
- length: u32,
- ur_type: QRCodeType,
-) -> PtrT<TransactionCheckResult> {
- if length != 4 {
- return TransactionCheckResult::from(RustCError::InvalidMasterFingerprint).c_ptr();
- }
- let payload = build_payload(ptr, ur_type);
- match payload {
- Ok(payload) => {
- let mfp = extract_array!(master_fingerprint, u8, 4);
- let mfp: [u8; 4] = mfp.to_vec().try_into().unwrap_or_default();
-
- let xfp = payload.xfp;
- let xfp_vec: [u8; 4] = hex::decode(xfp)
- .unwrap_or_default()
- .try_into()
- .unwrap_or_default();
- if mfp == xfp_vec {
- TransactionCheckResult::new().c_ptr()
- } else {
- TransactionCheckResult::from(RustCError::MasterFingerprintMismatch).c_ptr()
- }
- }
- Err(e) => TransactionCheckResult::from(KeystoneError::ProtobufError(e.to_string())).c_ptr(),
- }
-}
-
#[no_mangle]
pub unsafe extern "C" fn eth_check(
ptr: PtrUR,
@@ -125,23 +69,6 @@ pub unsafe extern "C" fn eth_check(
}
}
-#[no_mangle]
-pub unsafe extern "C" fn eth_get_root_path_bytes(ptr: PtrUR) -> PtrString {
- let sign_tx = match extract_sign_tx_from_payload(ptr) {
- Ok(sign_tx) => sign_tx,
- Err(_) => return convert_c_char("".to_string()),
- };
- // convert "M/44'/60'/0'/0/0" to "/44'/60'/0'"
- let root_path = sign_tx
- .hd_path
- .split('/')
- .skip(1)
- .take(3)
- .collect::<Vec<&str>>()
- .join("/");
- convert_c_char(root_path)
-}
-
#[no_mangle]
pub unsafe extern "C" fn eth_get_root_path(ptr: PtrUR) -> PtrString {
let eth_sign_request = extract_ptr_with_type!(ptr, EthSignRequest);
@@ -196,47 +123,6 @@ fn try_get_eth_public_key(
}
}
-#[no_mangle]
-pub unsafe extern "C" fn eth_parse_bytes_data(
- ptr: PtrUR,
- xpub: PtrString,
-) -> PtrT<TransactionParseResult<DisplayETH>> {
- let sign_tx = match extract_sign_tx_from_payload(ptr) {
- Ok(sign_tx) => sign_tx,
- Err(e) => {
- return TransactionParseResult::from(KeystoneError::ProtobufError(e.to_string()))
- .c_ptr();
- }
- };
- let xpub = recover_c_char(xpub);
- let root_path = &sign_tx
- .hd_path
- .split('/')
- .skip(1)
- .take(3)
- .collect::<Vec<&str>>()
- .join("/");
- let address = derive_address(
- sign_tx.hd_path.to_uppercase().trim_start_matches("M/"),
- &xpub,
- root_path,
- )
- .unwrap();
- let tx = sign_tx.transaction.unwrap();
- let eth_tx = match tx {
- EthTx(tx) => tx,
- _ => {
- return TransactionParseResult::from(RustCError::InvalidData(
- "Cant get eth tx struct data".to_string(),
- ))
- .c_ptr();
- }
- };
- let mut display_eth = DisplayETH::try_from(eth_tx).unwrap();
- display_eth = display_eth.set_from_address(address);
- TransactionParseResult::success(display_eth.c_ptr()).c_ptr()
-}
-
#[no_mangle]
pub unsafe extern "C" fn eth_parse(
ptr: PtrUR,
@@ -601,112 +487,6 @@ pub unsafe extern "C" fn eth_sign_tx_dynamic(
}
}
-#[no_mangle]
-pub unsafe extern "C" fn eth_sign_tx_bytes(
- ptr: PtrUR,
- seed: PtrBytes,
- seed_len: u32,
- mfp: PtrBytes,
- mfp_len: u32,
-) -> PtrT<UREncodeResult> {
- let sign_tx = match extract_sign_tx_from_payload(ptr) {
- Ok(sign_tx) => sign_tx,
- Err(e) => {
- return UREncodeResult::from(KeystoneError::ProtobufError(e.to_string())).c_ptr();
- }
- };
- let eth_tx = match sign_tx.transaction {
- Some(EthTx(tx)) => tx,
- _ => {
- return UREncodeResult::from(RustCError::InvalidData(
- "Cant get eth tx struct data".to_string(),
- ))
- .c_ptr();
- }
- };
-
- let legacy_transaction = match LegacyTransaction::try_from(eth_tx) {
- Ok(tx) => tx,
- Err(_) => {
- return UREncodeResult::from(RustCError::InvalidData("invalid eth tx".to_string()))
- .c_ptr();
- }
- };
-
- let mut seed = extract_array_mut!(seed, u8, seed_len as usize);
- let mfp = extract_array!(mfp, u8, mfp_len as usize);
-
- let signature = match app_ethereum::sign_legacy_tx_v2(
- &legacy_transaction.encode_raw(),
- seed,
- &sign_tx.hd_path,
- ) {
- Ok(sig) => sig,
- Err(e) => {
- seed.zeroize();
- return UREncodeResult::from(e).c_ptr();
- }
- };
- seed.zeroize();
- let transaction_signature = match TransactionSignature::try_from(signature) {
- Ok(sig) => sig,
- Err(_) => {
- return UREncodeResult::from(RustCError::InvalidData(
- "invalid transaction signature".to_string(),
- ))
- .c_ptr();
- }
- };
-
- let legacy_tx_with_signature = legacy_transaction.set_signature(transaction_signature);
- // tx_id is transaction hash , you can use this hash to search tx detail on the etherscan.
- let tx_hash = keccak256(&legacy_tx_with_signature.encode_raw());
- let raw_tx = legacy_tx_with_signature.encode_raw();
- // add 0x prefix for tx_id and raw_tx
- let sign_tx_result = ur_registry::pb::protoc::SignTransactionResult {
- sign_id: sign_tx.sign_id,
- tx_id: format!("0x{}", hex::encode(tx_hash)),
- raw_tx: format!("0x{}", hex::encode(raw_tx)),
- };
-
- let content = ur_registry::pb::protoc::payload::Content::SignTxResult(sign_tx_result);
- let payload = ur_registry::pb::protoc::Payload {
- // type is ur_registry::pb::protoc::payload::Type::SignTxResult
- r#type: 9,
- xfp: hex::encode(mfp).to_uppercase(),
- content: Some(content),
- };
- let base = ur_registry::pb::protoc::Base {
- version: 1,
- description: "keystone qrcode".to_string(),
- data: Some(payload),
- device_type: "keystone Pro".to_string(),
- content: Some(ColdVersion(31206)),
- };
- let base_vec = ur_registry::pb::protobuf_parser::serialize_protobuf(base);
- // zip data can reduce the size of the data
- let zip_data = match pb::protobuf_parser::zip(&base_vec) {
- Ok(data) => data,
- Err(e) => {
- return UREncodeResult::from(RustCError::InvalidData(e.to_string())).c_ptr();
- }
- };
- // data --> protobuf --> zip protobuf data --> cbor bytes data
- let bytes = match ur_registry::bytes::Bytes::new(zip_data).try_into() {
- Ok(b) => b,
- Err(e) => {
- return UREncodeResult::from(RustCError::InvalidData("invalid bytes".to_string()))
- .c_ptr();
- }
- };
- UREncodeResult::encode(
- bytes,
- ur_registry::bytes::Bytes::get_registry_type().get_type(),
- FRAGMENT_MAX_LENGTH_DEFAULT,
- )
- .c_ptr()
-}
-
#[no_mangle]
pub unsafe extern "C" fn eth_sign_tx(
ptr: PtrUR,
diff --git a/rust/rust_c/src/xrp/mod.rs b/rust/rust_c/src/xrp/mod.rs
index caec43f..d76405e 100644
--- a/rust/rust_c/src/xrp/mod.rs
+++ b/rust/rust_c/src/xrp/mod.rs
@@ -1,27 +1,17 @@
use alloc::format;
-use alloc::string::ToString;
use alloc::vec::Vec;
use core::slice;
-use core::str::FromStr;
use app_xrp::errors::XRPError;
-use bitcoin::bip32::{DerivationPath, Xpub};
-use bitcoin::secp256k1;
use cty::c_char;
-use serde_json::Value;
use ur_registry::bytes::Bytes;
-use ur_registry::pb;
-use ur_registry::pb::protoc::base::Content::ColdVersion;
-use ur_registry::pb::protoc::payload::Content;
-use ur_registry::pb::protoc::sign_transaction::Transaction::XrpTx;
use ur_registry::traits::RegistryItem;
-use crate::common::errors::{ErrorCodes, KeystoneError, RustCError};
-use crate::common::keystone::build_payload;
+use crate::common::errors::ErrorCodes;
use crate::common::structs::{SimpleResponse, TransactionCheckResult, TransactionParseResult};
use crate::common::types::{PtrBytes, PtrString, PtrT, PtrUR};
-use crate::common::ur::{QRCodeType, UREncodeResult, FRAGMENT_MAX_LENGTH_DEFAULT};
+use crate::common::ur::{UREncodeResult, FRAGMENT_MAX_LENGTH_DEFAULT};
use crate::common::utils::{convert_c_char, recover_c_char};
use crate::extract_array;
use crate::extract_ptr_with_type;
@@ -71,112 +61,6 @@ pub unsafe extern "C" fn xrp_parse_tx(ptr: PtrUR) -> PtrT<TransactionParseResult
}
}
-#[no_mangle]
-pub unsafe extern "C" fn xrp_sign_tx_bytes(
- ptr: PtrUR,
- seed: PtrBytes,
- seed_len: u32,
- mfp: PtrBytes,
- mfp_len: u32,
- root_xpub: PtrString,
-) -> PtrT<UREncodeResult> {
- let seed = extract_array!(seed, u8, seed_len);
- let mfp = extract_array!(mfp, u8, mfp_len);
- let payload = build_payload(ptr, QRCodeType::Bytes).unwrap();
- let content = payload.content.unwrap();
- let sign_tx = match content {
- Content::SignTx(sign_tx) => sign_tx,
- _ => {
- return UREncodeResult::from(RustCError::InvalidData(
- "Cant get sign tx struct data".to_string(),
- ))
- .c_ptr();
- }
- };
- let tx = sign_tx.transaction.unwrap();
- let hd_path = sign_tx.hd_path;
- let xrp_tx = match tx {
- XrpTx(tx) => tx,
- _ => {
- return UREncodeResult::from(RustCError::InvalidData(
- "Cant get xrp tx struct data".to_string(),
- ))
- .c_ptr();
- }
- };
- let root_xpub = recover_c_char(root_xpub);
- let xpub = Xpub::from_str(&root_xpub).unwrap();
- let k1 = secp256k1::Secp256k1::new();
- // M/44'/144'/0'/0/0 -> 0/0
- let split_hd_path: Vec<&str> = hd_path.split('/').collect();
- let derive_hd_path = format!("{}/{}", split_hd_path[4], split_hd_path[5]);
- let five_level_xpub = xpub
- .derive_pub(
- &k1,
- &DerivationPath::from_str(format!("m/{derive_hd_path}").as_str()).unwrap(),
- )
- .unwrap();
- let key = five_level_xpub.public_key.serialize();
- let tx_str = format!(
- r#"{{
- "Account": "{}",
- "Amount": "{}",
- "Destination":"{}",
- "Fee": "{}",
- "Flags": 2147483648,
- "Sequence": {},
- "TransactionType": "Payment",
- "SigningPubKey": "{}",
- "DestinationTag":{}
- }}"#,
- xrp_tx.change_address,
- xrp_tx.amount,
- xrp_tx.to,
- xrp_tx.fee,
- xrp_tx.sequence,
- hex::encode(key).to_uppercase(),
- xrp_tx.tag
- );
-
- let v: Value = serde_json::from_str(tx_str.as_str()).unwrap();
- let input_bytes = v.to_string().into_bytes();
-
- let sign_result = app_xrp::sign_tx(input_bytes.as_slice(), &hd_path, seed);
- let tx_hash = app_xrp::get_tx_hash(input_bytes.as_slice()).unwrap();
- let raw_tx = sign_result.unwrap();
- let raw_tx_hex = hex::encode(raw_tx);
- // generate a qr code
- let sign_tx_result = ur_registry::pb::protoc::SignTransactionResult {
- sign_id: sign_tx.sign_id,
- tx_id: tx_hash.to_uppercase().to_string(),
- raw_tx: raw_tx_hex.clone().to_string(),
- };
- let content = ur_registry::pb::protoc::payload::Content::SignTxResult(sign_tx_result);
- let payload = ur_registry::pb::protoc::Payload {
- // type is ur_registry::pb::protoc::payload::Type::SignTxResult
- r#type: 9,
- xfp: hex::encode(mfp),
- content: Some(content),
- };
- let base = ur_registry::pb::protoc::Base {
- version: 1,
- description: "keystone qrcode".to_string(),
- data: Some(payload),
- device_type: "keystone Pro".to_string(),
- content: Some(ColdVersion(31206)),
- };
- let base_vec = ur_registry::pb::protobuf_parser::serialize_protobuf(base);
- // zip data can reduce the size of the data
- let zip_data = pb::protobuf_parser::zip(&base_vec).unwrap();
- // data --> protobuf --> zip protobuf data --> cbor bytes data
- UREncodeResult::encode(
- ur_registry::bytes::Bytes::new(zip_data).try_into().unwrap(),
- ur_registry::bytes::Bytes::get_registry_type().get_type(),
- FRAGMENT_MAX_LENGTH_DEFAULT,
- )
- .c_ptr()
-}
-
#[no_mangle]
pub unsafe extern "C" fn xrp_sign_tx(
ptr: PtrUR,
@@ -218,68 +102,3 @@ pub unsafe extern "C" fn xrp_check_tx(
Err(e) => TransactionCheckResult::from(e).c_ptr(),
}
}
-
-#[no_mangle]
-pub unsafe extern "C" fn is_keystone_xrp_tx(ur_data_ptr: PtrUR) -> bool {
- // if data can be parsed by protobuf, it is a keyston hot app version2 tx or it is a xrp tx
- let payload = build_payload(ur_data_ptr, QRCodeType::Bytes);
- payload.is_ok()
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn xrp_check_tx_bytes(
- ptr: PtrUR,
- master_fingerprint: PtrBytes,
- length: u32,
- ur_type: QRCodeType,
-) -> PtrT<TransactionCheckResult> {
- if length != 4 {
- return TransactionCheckResult::from(RustCError::InvalidMasterFingerprint).c_ptr();
- }
- let payload = build_payload(ptr, ur_type);
- match payload {
- Ok(payload) => {
- let mfp = extract_array!(master_fingerprint, u8, 4);
- let mfp: [u8; 4] = mfp.to_vec().try_into().unwrap();
-
- let xfp = payload.xfp;
- let xfp_vec: [u8; 4] = hex::decode(xfp).unwrap().try_into().unwrap();
- if mfp == xfp_vec {
- TransactionCheckResult::error(ErrorCodes::Success, "".to_string()).c_ptr()
- } else {
- TransactionCheckResult::from(RustCError::MasterFingerprintMismatch).c_ptr()
- }
- }
- Err(e) => TransactionCheckResult::from(KeystoneError::ProtobufError(e.to_string())).c_ptr(),
- }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn xrp_parse_bytes_tx(
- ptr: PtrUR,
-) -> PtrT<TransactionParseResult<DisplayXrpTx>> {
- let payload = build_payload(ptr, QRCodeType::Bytes).unwrap();
- let content = payload.content.unwrap();
- let sign_tx = match content {
- Content::SignTx(sign_tx) => sign_tx,
- _ => {
- return TransactionParseResult::from(RustCError::InvalidData(
- "Cant get sign tx struct data".to_string(),
- ))
- .c_ptr();
- }
- };
- let tx = sign_tx.transaction.unwrap();
- let xrp_tx = match tx {
- XrpTx(tx) => tx,
- _ => {
- return TransactionParseResult::from(RustCError::InvalidData(
- "Cant get xrp tx struct data".to_string(),
- ))
- .c_ptr();
- }
- };
-
- let display_xrp = DisplayXrpTx::try_from(xrp_tx).unwrap();
- TransactionParseResult::success(display_xrp.c_ptr()).c_ptr()
-}
diff --git a/src/ui/gui_chain/gui_btc.c b/src/ui/gui_chain/gui_btc.c
index 32a31e7..9663a09 100644
--- a/src/ui/gui_chain/gui_btc.c
+++ b/src/ui/gui_chain/gui_btc.c
@@ -55,9 +55,9 @@ static UtxoViewToChain_t g_UtxoViewToChainMap[] = {
};
#ifdef WEB3_VERSION
-#define CHECK_UR_TYPE() (urType == Bytes || urType == KeystoneSignRequest)
+#define CHECK_UR_TYPE() (urType == KeystoneSignRequest)
#else
-#define CHECK_UR_TYPE() (urType == Bytes)
+#define CHECK_UR_TYPE() (false)
#endif
#endif
@@ -205,7 +205,7 @@ static bool SupportSignPsbtFromSDCard(void)
static bool SupportSignLegacyKeystoneTransactions(QRCodeType urType)
{
#ifdef WEB3_VERSION
- return (urType == Bytes || urType == KeystoneSignRequest);
+ return (urType == KeystoneSignRequest);
#else
return false;
#endif
diff --git a/src/ui/gui_chain/multi/web3/gui_eth.c b/src/ui/gui_chain/multi/web3/gui_eth.c
index ed55431..ea94cd8 100644
--- a/src/ui/gui_chain/multi/web3/gui_eth.c
+++ b/src/ui/gui_chain/multi/web3/gui_eth.c
@@ -684,34 +684,14 @@ static UREncodeResult *GetEthSignDataDynamic(bool isUnlimited)
SetLockScreen(false);
UREncodeResult *encodeResult;
void *data = g_isMulti ? g_urMultiResult->data : g_urResult->data;
- // get the urType
- enum QRCodeType urType = URTypeUnKnown;
- if (g_isMulti) {
- urType = g_urMultiResult->ur_type;
- } else {
- urType = g_urResult->ur_type;
- }
do {
uint8_t seed[64];
int len = GetMnemonicType() == MNEMONIC_TYPE_BIP39 ? sizeof(seed) : GetCurrentAccountEntropyLen();
GetAccountSeed(GetCurrentAccountIndex(), seed, SecretCacheGetPassword());
if (isUnlimited) {
- if (urType == Bytes) {
- uint8_t mfp[4] = {0};
- GetMasterFingerPrint(mfp);
- // sign the bytes from keystone hot wallet
- encodeResult = eth_sign_tx_bytes(data, seed, len, mfp, sizeof(mfp));
- } else {
- encodeResult = eth_sign_tx_unlimited(data, seed, len);
- }
+ encodeResult = eth_sign_tx_unlimited(data, seed, len);
} else {
- if (urType == Bytes) {
- uint8_t mfp[4] = {0};
- GetMasterFingerPrint(mfp);
- encodeResult = eth_sign_tx_bytes(data, seed, len, mfp, sizeof(mfp));
- } else {
- encodeResult = eth_sign_tx(data, seed, len);
- }
+ encodeResult = eth_sign_tx(data, seed, len);
}
ClearSecretCache();
CHECK_CHAIN_BREAK(encodeResult);
@@ -1089,36 +1069,18 @@ void *GuiGetEthData(void)
g_contractDataExist = false;
g_erc20Name = NULL;
CHECK_FREE_PARSE_RESULT(g_parseResult);
- uint8_t mfp[4];
void *data = g_isMulti ? g_urMultiResult->data : g_urResult->data;
- enum ViewType viewType = ViewTypeUnKnown;
- enum QRCodeType urType = URTypeUnKnown;
- if (g_isMulti) {
- urType = g_urMultiResult->ur_type;
- viewType = g_urMultiResult->t;
- } else {
- urType = g_urResult->ur_type;
- }
char *rootPath = NULL;
- if (urType == Bytes) {
- rootPath = eth_get_root_path_bytes(data);
- } else {
- rootPath = eth_get_root_path(data);
- }
+ rootPath = eth_get_root_path(data);
char *ethXpub = "";
ChainType chainType = GetEthPublickeyIndex(rootPath);
if (chainType != 0xFF) {
ethXpub = GetCurrentAccountPublicKey(chainType);
}
- GetMasterFingerPrint(mfp);
PtrT_TransactionParseResult_DisplayETH parseResult = NULL;
do {
- if (urType == Bytes) {
- parseResult = eth_parse_bytes_data(data, ethXpub);
- } else {
- parseResult = eth_parse(data, ethXpub);
- }
+ parseResult = eth_parse(data, ethXpub);
CHECK_CHAIN_BREAK(parseResult);
g_parseResult = (void *)parseResult;
if (parseResult->data->overview->from != NULL) {
@@ -1137,22 +1099,8 @@ PtrT_TransactionCheckResult GuiGetEthCheckResult(void)
{
uint8_t mfp[4];
void *data = g_isMulti ? g_urMultiResult->data : g_urResult->data;
- enum QRCodeType urType = URTypeUnKnown;
- void *crypto = NULL;
- if (g_isMulti) {
- crypto = g_urMultiResult->data;
- urType = g_urMultiResult->ur_type;
- } else {
- crypto = g_urResult->data;
- urType = g_urResult->ur_type;
- }
GetMasterFingerPrint(mfp);
- // get the urType
- if (urType == Bytes) {
- return eth_check_ur_bytes(data, mfp, sizeof(mfp), urType);
- } else {
- return eth_check(data, mfp, sizeof(mfp));
- }
+ return eth_check(data, mfp, sizeof(mfp));
}
void GetEthTransType(void *indata, void *param, uint32_t maxLen)
@@ -1770,4 +1718,4 @@ void FreeEthMemory(void)
FreeContractData();
GUI_DEL_OBJ(g_contractRawDataHintbox);
g_isPermitSingle = false;
-}
\ No newline at end of file
+}
diff --git a/src/ui/gui_chain/multi/web3/gui_xrp.c b/src/ui/gui_chain/multi/web3/gui_xrp.c
index 4d11a41..d1c3743 100644
--- a/src/ui/gui_chain/multi/web3/gui_xrp.c
+++ b/src/ui/gui_chain/multi/web3/gui_xrp.c
@@ -65,11 +65,7 @@ void *GuiGetXrpData(void)
PtrT_TransactionParseResult_DisplayXrpTx parseResult = NULL;
do {
- if (is_keystone_xrp_tx(data)) {
- parseResult = xrp_parse_bytes_tx(data);
- } else {
- parseResult = xrp_parse_tx(data);
- }
+ parseResult = xrp_parse_tx(data);
CHECK_CHAIN_BREAK(parseResult);
g_parseResult = (void *)parseResult;
@@ -85,21 +81,7 @@ PtrT_TransactionCheckResult GuiGetXrpCheckResult(void)
if (g_cachedPubkey[GetCurrentAccountIndex()] != NULL) {
strcpy_s(pubkey, XPUB_KEY_LEN, g_cachedPubkey[GetCurrentAccountIndex()]);
}
- enum QRCodeType urType = URTypeUnKnown;
- if (g_isMulti) {
- urType = g_urMultiResult->ur_type;
- } else {
- urType = g_urResult->ur_type;
- }
- // keystone hot wallet use urType Bytes
- uint8_t mfp[4];
- GetMasterFingerPrint(mfp);
- if (is_keystone_xrp_tx(data)) {
- result = xrp_check_tx_bytes(data, mfp, sizeof(mfp), urType);
- return result;
- } else {
- result = xrp_check_tx(data, GetCurrentAccountPublicKey(XPUB_TYPE_XRP), pubkey);
- }
+ result = xrp_check_tx(data, GetCurrentAccountPublicKey(XPUB_TYPE_XRP), pubkey);
if (result != NULL && result->error_code == 0 && strlen(result->error_message) > 0) {
if (g_cachedPubkey[GetCurrentAccountIndex()] != NULL) {
SRAM_FREE(g_cachedPubkey[GetCurrentAccountIndex()]);
@@ -162,21 +144,10 @@ UREncodeResult *GuiGetXrpSignQrCodeData(void)
uint8_t seed[64];
GetAccountSeed(GetCurrentAccountIndex(), seed, SecretCacheGetPassword());
int len = GetMnemonicType() == MNEMONIC_TYPE_BIP39 ? sizeof(seed) : GetCurrentAccountEntropyLen();
- if (is_keystone_xrp_tx(data)) {
- uint8_t mfp[4] = {0};
- GetMasterFingerPrint(mfp);
- // sign the bytes from keystone hot wallet
- char pubkey[XPUB_KEY_LEN] = {0};
- if (g_cachedPubkey[GetCurrentAccountIndex()] != NULL) {
- strcpy_s(pubkey, XPUB_KEY_LEN, g_cachedPubkey[GetCurrentAccountIndex()]);
- }
- encodeResult = xrp_sign_tx_bytes(data, seed, len, mfp, sizeof(mfp), GetCurrentAccountPublicKey(XPUB_TYPE_XRP));
- } else {
- encodeResult = xrp_sign_tx(data, g_hdPath, seed, len);
- }
+ encodeResult = xrp_sign_tx(data, g_hdPath, seed, len);
ClearSecretCache();
CHECK_CHAIN_BREAK(encodeResult);
} while (0);
SetLockScreen(enable);
return encodeResult;
-}
\ No newline at end of file
+}
Why this scored 57/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.