1+ use candid:: Principal ;
12use walrus:: ir:: * ;
23use walrus:: * ;
34
@@ -295,6 +296,58 @@ fn make_grow64_func(m: &mut Module, limit: i64) -> FunctionId {
295296 ) ;
296297 builder. finish ( vec ! [ requested] , & mut m. funcs )
297298}
299+ fn check_list (
300+ memory : MemoryId ,
301+ checks : & mut InstrSeqBuilder ,
302+ no_redirect : LocalId ,
303+ size : LocalId ,
304+ src : LocalId ,
305+ is_rename : Option < LocalId > ,
306+ list : & Vec < & [ u8 ] > ,
307+ ) {
308+ let checks_id = checks. id ( ) ;
309+ for bytes in list {
310+ checks. block ( None , |list_check| {
311+ let list_check_id = list_check. id ( ) ;
312+ // Check the length
313+ list_check
314+ . local_get ( size)
315+ . i32_const ( bytes. len ( ) as i32 )
316+ . binop ( BinaryOp :: I32Ne )
317+ . br_if ( list_check_id) ;
318+ // Load bytes at src onto the stack
319+ for i in 0 ..bytes. len ( ) {
320+ list_check. local_get ( src) . load (
321+ memory,
322+ LoadKind :: I32_8 {
323+ kind : ExtendedLoad :: ZeroExtend ,
324+ } ,
325+ MemArg {
326+ offset : i as u32 ,
327+ align : 1 ,
328+ } ,
329+ ) ;
330+ }
331+ for byte in bytes. iter ( ) . rev ( ) {
332+ list_check
333+ . i32_const ( * byte as i32 )
334+ . binop ( BinaryOp :: I32Ne )
335+ . br_if ( list_check_id) ;
336+ }
337+ // names were equal, so skip all remaining checks and redirect
338+ if let Some ( is_rename) = is_rename {
339+ if bytes == b"http_request" {
340+ list_check. i32_const ( 1 ) . local_set ( is_rename) ;
341+ } else {
342+ list_check. i32_const ( 0 ) . local_set ( is_rename) ;
343+ }
344+ }
345+ list_check. i32_const ( 0 ) . local_set ( no_redirect) . br ( checks_id) ;
346+ } ) ;
347+ }
348+ // None matched
349+ checks. i32_const ( 1 ) . local_set ( no_redirect) ;
350+ }
298351fn make_redirect_call_new ( m : & mut Module , redirect_id : & [ u8 ] ) -> FunctionId {
299352 // Specify the same args as `call_new` so that WASM will correctly check mismatching args
300353 let callee_src = m. locals . add ( ValType :: I32 ) ;
@@ -316,9 +369,14 @@ fn make_redirect_call_new(m: &mut Module, redirect_id: &[u8]) -> FunctionId {
316369 for _ in 0 ..redirect_id. len ( ) {
317370 memory_backup. push ( m. locals . add ( ValType :: I32 ) ) ;
318371 }
372+ let redirect_canisters = [
373+ Principal :: from_slice ( & [ ] ) ,
374+ Principal :: from_text ( "7hfb6-caaaa-aaaar-qadga-cai" ) . unwrap ( ) ,
375+ ] ;
319376
320- // All management canister functions that require controller permissions
321- // The following wasm code assumes that this list is non-empty
377+ // All functions that require controller permissions or cycles.
378+ // For simplicity, We mingle all canister methods in a single list.
379+ // Method names shouldn't overlap.
322380 let controller_function_names = [
323381 "create_canister" ,
324382 "update_settings" ,
@@ -333,8 +391,18 @@ fn make_redirect_call_new(m: &mut Module, redirect_id: &[u8]) -> FunctionId {
333391 "load_canister_snapshot" ,
334392 "delete_canister_snapshot" ,
335393 // These functions doesn't require controller permissions, but needs cycles
394+ "sign_with_ecdsa" ,
336395 "http_request" , // Will be renamed to "_ttp_request", because the name conflicts with the http serving endpoint.
337396 "_ttp_request" , // need to redirect renamed function as well, because the second time we see this function, it's already renamed in memory
397+ // methods from evm canister
398+ "eth_call" ,
399+ "eth_feeHistory" ,
400+ "eth_getBlockByNumber" ,
401+ "eth_getLogs" ,
402+ "eth_getTransactionCount" ,
403+ "eth_getTransactionReceipt" ,
404+ "eth_sendRawTransaction" ,
405+ "request" ,
338406 ] ;
339407
340408 let mut builder = FunctionBuilder :: new (
@@ -356,57 +424,37 @@ fn make_redirect_call_new(m: &mut Module, redirect_id: &[u8]) -> FunctionId {
356424 . func_body ( )
357425 . block ( None , |checks| {
358426 let checks_id = checks. id ( ) ;
359-
360- // Check that callee address is empty
427+ // Check if callee address is from redirect_canisters
361428 checks
362- . local_get ( callee_size)
363- . i32_const ( 0 )
364- . binop ( BinaryOp :: I32Ne )
365- . local_tee ( no_redirect)
429+ . block ( None , |id_check| {
430+ check_list (
431+ memory,
432+ id_check,
433+ no_redirect,
434+ callee_size,
435+ callee_src,
436+ None ,
437+ & redirect_canisters
438+ . iter ( )
439+ . map ( |p| p. as_slice ( ) )
440+ . collect :: < Vec < _ > > ( ) ,
441+ ) ;
442+ } )
443+ . local_get ( no_redirect)
366444 . br_if ( checks_id) ;
367-
368- // Check if the function name is any of the ones to be redirected
369- for func_name in controller_function_names {
370- checks. block ( None , |name_check| {
371- let name_check_id = name_check. id ( ) ;
372- name_check
373- // Check that name_size is the same length as the function name
374- . local_get ( name_size)
375- . i32_const ( func_name. len ( ) as i32 )
376- . binop ( BinaryOp :: I32Ne )
377- . br_if ( name_check_id) ;
378-
379- // Load the string at name_src onto the stack and compare it to the function name
380- for i in 0 ..func_name. len ( ) {
381- name_check. local_get ( name_src) . load (
382- memory,
383- LoadKind :: I32_8 {
384- kind : ExtendedLoad :: SignExtend ,
385- } ,
386- MemArg {
387- offset : i as u32 ,
388- align : 1 ,
389- } ,
390- ) ;
391- }
392- for c in func_name. chars ( ) . rev ( ) {
393- name_check
394- . i32_const ( c as i32 )
395- . binop ( BinaryOp :: I32Ne )
396- . br_if ( name_check_id) ;
397- }
398- // Function names were equal, so skip all remaining checks and redirect
399- if func_name == "http_request" {
400- name_check. i32_const ( 1 ) . local_set ( is_rename) ;
401- } else {
402- name_check. i32_const ( 0 ) . local_set ( is_rename) ;
403- }
404- name_check. i32_const ( 0 ) . local_set ( no_redirect) . br ( checks_id) ;
405- } ) ;
406- }
407-
408- // None of the function names matched
409- checks. i32_const ( 1 ) . local_set ( no_redirect) ;
445+ // Callee address matches, check method name is in the list
446+ check_list (
447+ memory,
448+ checks,
449+ no_redirect,
450+ name_size,
451+ name_src,
452+ Some ( is_rename) ,
453+ & controller_function_names
454+ . iter ( )
455+ . map ( |s| s. as_bytes ( ) )
456+ . collect :: < Vec < _ > > ( ) ,
457+ ) ;
410458 } )
411459 . local_get ( no_redirect)
412460 . if_else (
@@ -432,7 +480,7 @@ fn make_redirect_call_new(m: &mut Module, redirect_id: &[u8]) -> FunctionId {
432480 . load (
433481 memory,
434482 LoadKind :: I32_8 {
435- kind : ExtendedLoad :: SignExtend ,
483+ kind : ExtendedLoad :: ZeroExtend ,
436484 } ,
437485 MemArg {
438486 offset : 0 ,
0 commit comments