@@ -12,7 +12,7 @@ use crate::common::{
12
12
structs:: { ExtendedPublicKey , SimpleResponse , TransactionCheckResult , TransactionParseResult } ,
13
13
types:: { Ptr , PtrBytes , PtrString , PtrT , PtrUR } ,
14
14
ur:: { UREncodeResult , FRAGMENT_MAX_LENGTH_DEFAULT , FRAGMENT_UNLIMITED_LENGTH } ,
15
- utils:: recover_c_char,
15
+ utils:: { recover_c_array , recover_c_char} ,
16
16
} ;
17
17
use crate :: { extract_ptr_with_type, impl_c_ptr} ;
18
18
use alloc:: {
@@ -31,7 +31,7 @@ use app_avalanche::{
31
31
base_tx:: { avax_base_sign, BaseTx } ,
32
32
export:: ExportTx ,
33
33
import:: ImportTx ,
34
- type_id:: TypeId ,
34
+ type_id:: { self , TypeId } ,
35
35
C_chain :: { evm_export:: ExportTx as CchainExportTx , evm_import:: ImportTx as CchainImportTx } ,
36
36
P_chain :: {
37
37
add_permissionless_delegator:: AddPermissLessionDelegatorTx ,
@@ -49,61 +49,94 @@ use {
49
49
} ,
50
50
} ;
51
51
52
+ const C_CHAIN_PREFIX : & str = "m/44'/60'/0'" ;
53
+ const X_P_CHAIN_PREFIX : & str = "m/44'/9000'/0'" ;
54
+
55
+ #[ derive( Debug , Clone ) ]
56
+ pub struct DerivationPath {
57
+ pub base_path : String ,
58
+ pub full_path : String ,
59
+ }
60
+
52
61
#[ no_mangle]
53
62
pub extern "C" fn avax_parse_transaction (
54
63
ptr : PtrUR ,
55
64
mfp : PtrBytes ,
56
65
mfp_len : u32 ,
57
66
public_keys : PtrT < CSliceFFI < ExtendedPublicKey > > ,
58
67
) -> PtrT < TransactionParseResult < DisplayAvaxTx > > {
59
- let avax_sign_request = extract_ptr_with_type ! ( ptr, AvaxSignRequest ) ;
60
-
61
- match get_avax_tx_type_id ( avax_sign_request. get_tx_data ( ) ) {
62
- Ok ( type_id) => parse_transaction_by_type ( type_id, avax_sign_request. get_tx_data ( ) ) ,
63
- Err ( _) => {
64
- TransactionParseResult :: from ( RustCError :: InvalidData ( "Invalid tx type" . to_string ( ) ) )
65
- . c_ptr ( )
66
- }
67
- }
68
+ parse_transaction_by_type ( extract_ptr_with_type ! ( ptr, AvaxSignRequest ) , public_keys)
68
69
}
70
+ extern crate std;
71
+ use std:: println;
69
72
70
73
fn parse_transaction_by_type (
71
- type_id : TypeId ,
72
- tx_data : Vec < u8 > ,
74
+ sign_request : & mut AvaxSignRequest ,
75
+ public_keys : PtrT < CSliceFFI < ExtendedPublicKey > > ,
73
76
) -> PtrT < TransactionParseResult < DisplayAvaxTx > > {
74
- macro_rules! parse_tx {
75
- ( $tx_type: ty) => {
76
- parse_avax_tx:: <$tx_type>( tx_data)
77
- . map( |parse_data| {
78
- TransactionParseResult :: success( DisplayAvaxTx :: from( parse_data) . c_ptr( ) ) . c_ptr( )
79
- } )
80
- . unwrap_or_else( |_| {
81
- TransactionParseResult :: from( RustCError :: InvalidMasterFingerprint ) . c_ptr( )
82
- } )
83
- } ;
84
- }
77
+ let tx_data = sign_request. get_tx_data ( ) ;
78
+ let type_id = get_avax_tx_type_id ( sign_request. get_tx_data ( ) ) . unwrap ( ) ;
85
79
86
- match type_id {
87
- TypeId :: BaseTx => {
88
- let header = get_avax_tx_header ( tx_data. clone ( ) ) . unwrap ( ) ;
89
- if header. get_blockchain_id ( ) == C_BLOCKCHAIN_ID
90
- || header. get_blockchain_id ( ) == C_TEST_BLOCKCHAIN_ID
91
- {
92
- return parse_tx ! ( CchainImportTx ) ;
93
- } else {
94
- return parse_tx ! ( BaseTx ) ;
80
+ unsafe {
81
+ let path = get_avax_tx_type_id ( sign_request. get_tx_data ( ) )
82
+ . map_err ( |_| AvaxError :: InvalidInput )
83
+ . and_then ( |type_id| {
84
+ determine_derivation_path ( type_id, & sign_request, sign_request. get_wallet_index ( ) )
85
+ } )
86
+ . unwrap ( ) ;
87
+
88
+ let mut address = String :: new ( ) ;
89
+ for key in recover_c_array ( public_keys) . iter ( ) {
90
+ if recover_c_char ( key. path ) == path. base_path {
91
+ address = app_avalanche:: get_address (
92
+ app_avalanche:: network:: Network :: AvaxMainNet ,
93
+ & path. full_path . as_str ( ) ,
94
+ & recover_c_char ( key. xpub ) . as_str ( ) ,
95
+ & path. base_path . as_str ( ) ,
96
+ )
97
+ . unwrap ( ) ;
95
98
}
96
99
}
97
- TypeId :: PchainExportTx | TypeId :: XchainExportTx => parse_tx ! ( ExportTx ) ,
98
- TypeId :: XchainImportTx | TypeId :: PchainImportTx => parse_tx ! ( ImportTx ) ,
99
- TypeId :: CchainExportTx => parse_tx ! ( CchainExportTx ) ,
100
- TypeId :: AddPermissLessionValidator => parse_tx ! ( AddPermissLessionValidatorTx ) ,
101
- TypeId :: AddPermissLessionDelegator => parse_tx ! ( AddPermissLessionDelegatorTx ) ,
102
- _ => TransactionParseResult :: from ( RustCError :: InvalidData ( format ! (
103
- "{:?} not support" ,
104
- type_id
105
- ) ) )
106
- . c_ptr ( ) ,
100
+
101
+ macro_rules! parse_tx {
102
+ ( $tx_type: ty) => {
103
+ parse_avax_tx:: <$tx_type>( tx_data)
104
+ . map( |parse_data| {
105
+ TransactionParseResult :: success(
106
+ DisplayAvaxTx :: from( parse_data)
107
+ . with_from_address( address. to_string( ) , path. full_path. to_string( ) )
108
+ . c_ptr( ) ,
109
+ )
110
+ . c_ptr( )
111
+ } )
112
+ . unwrap_or_else( |_| {
113
+ TransactionParseResult :: from( RustCError :: InvalidMasterFingerprint ) . c_ptr( )
114
+ } )
115
+ } ;
116
+ }
117
+
118
+ match type_id {
119
+ TypeId :: BaseTx => {
120
+ let header = get_avax_tx_header ( tx_data. clone ( ) ) . unwrap ( ) ;
121
+ if header. get_blockchain_id ( ) == C_BLOCKCHAIN_ID
122
+ || header. get_blockchain_id ( ) == C_TEST_BLOCKCHAIN_ID
123
+ {
124
+ return parse_tx ! ( CchainImportTx ) ;
125
+ } else {
126
+ return parse_tx ! ( BaseTx ) ;
127
+ }
128
+ }
129
+ TypeId :: PchainExportTx | TypeId :: XchainExportTx => parse_tx ! ( ExportTx ) ,
130
+ TypeId :: XchainImportTx | TypeId :: PchainImportTx => parse_tx ! ( ImportTx ) ,
131
+ TypeId :: CchainExportTx => parse_tx ! ( CchainExportTx ) ,
132
+ TypeId :: AddPermissLessionValidator => parse_tx ! ( AddPermissLessionValidatorTx ) ,
133
+ TypeId :: AddPermissLessionDelegator => parse_tx ! ( AddPermissLessionDelegatorTx ) ,
134
+ _ => TransactionParseResult :: from ( RustCError :: InvalidData ( format ! (
135
+ "{:?} not support" ,
136
+ type_id
137
+ ) ) )
138
+ . c_ptr ( ) ,
139
+ }
107
140
}
108
141
}
109
142
@@ -135,31 +168,43 @@ fn avax_sign_dynamic(
135
168
)
136
169
}
137
170
138
- fn handle_base_tx_path (
171
+ pub fn determine_derivation_path (
172
+ type_id : TypeId ,
139
173
sign_request : & AvaxSignRequest ,
140
174
wallet_index : u64 ,
141
- ) -> Result < String , AvaxError > {
142
- let blockchain_id = get_avax_tx_header ( sign_request. get_tx_data ( ) ) ?. get_blockchain_id ( ) ;
175
+ ) -> Result < DerivationPath , AvaxError > {
176
+ println ! ( "type_id = {:?}, wallet_index = {}" , type_id, wallet_index) ;
177
+ let wallet_suffix = format ! ( "/0/{}" , wallet_index) ;
178
+
179
+ let ( base_path, full_path) = match type_id {
180
+ TypeId :: CchainExportTx => (
181
+ C_CHAIN_PREFIX ,
182
+ format ! ( "{}{}" , C_CHAIN_PREFIX , wallet_suffix) ,
183
+ ) ,
184
+ TypeId :: BaseTx => {
185
+ let blockchain_id = get_avax_tx_header ( sign_request. get_tx_data ( ) ) ?. get_blockchain_id ( ) ;
143
186
144
- let path = match blockchain_id {
145
- id if id == C_BLOCKCHAIN_ID || id == C_TEST_BLOCKCHAIN_ID => {
146
- format ! ( "m/44'/60'/0'/0/{}" , wallet_index)
187
+ if blockchain_id == C_BLOCKCHAIN_ID || blockchain_id == C_TEST_BLOCKCHAIN_ID {
188
+ (
189
+ C_CHAIN_PREFIX ,
190
+ format ! ( "{}{}" , C_CHAIN_PREFIX , wallet_suffix) ,
191
+ )
192
+ } else {
193
+ (
194
+ X_P_CHAIN_PREFIX ,
195
+ format ! ( "{}{}" , X_P_CHAIN_PREFIX , wallet_suffix) ,
196
+ )
197
+ }
147
198
}
148
- _ => format ! ( "m/44'/9000'/0'/0/{}" , wallet_index) ,
199
+ _ => (
200
+ X_P_CHAIN_PREFIX ,
201
+ format ! ( "{}{}" , X_P_CHAIN_PREFIX , wallet_suffix) ,
202
+ ) ,
149
203
} ;
150
204
151
- Ok ( path)
152
- }
153
-
154
- fn determine_derivation_path (
155
- type_id : TypeId ,
156
- sign_request : & AvaxSignRequest ,
157
- wallet_index : u64 ,
158
- ) -> Result < String , AvaxError > {
159
- Ok ( match type_id {
160
- TypeId :: CchainExportTx => format ! ( "m/44'/60'/0'/0/{}" , wallet_index) ,
161
- TypeId :: BaseTx => handle_base_tx_path ( sign_request, wallet_index) ?,
162
- _ => format ! ( "m/44'/9000'/0'/0/{}" , wallet_index) ,
205
+ Ok ( DerivationPath {
206
+ base_path : base_path. to_string ( ) ,
207
+ full_path : full_path,
163
208
} )
164
209
}
165
210
@@ -170,7 +215,8 @@ fn build_sign_result(ptr: PtrUR, seed: &[u8]) -> Result<AvaxSignature, AvaxError
170
215
. map_err ( |_| AvaxError :: InvalidInput )
171
216
. and_then ( |type_id| {
172
217
determine_derivation_path ( type_id, & sign_request, sign_request. get_wallet_index ( ) )
173
- } ) ?;
218
+ } ) ?
219
+ . full_path ;
174
220
175
221
avax_base_sign ( seed, path, sign_request. get_tx_data ( ) )
176
222
. map ( |signature| AvaxSignature :: new ( sign_request. get_request_id ( ) , signature. to_vec ( ) ) )
0 commit comments