pub fn malicious_intercanister_calls(handle: IcHandle, ctx: &ic_fondue::pot::Context) {
    let mut rng = ctx.rng.clone();
    let rt = tokio::runtime::Runtime::new().expect("Could not create tokio runtime.");
    let canister_b_wasm = wabt::wat2wasm(
        r#"(module
            (import "ic0" "msg_arg_data_copy" (func $ic0_msg_arg_data_copy (param i32) (param i32) (param i32)))
            (import "ic0" "msg_reply" (func $msg_reply))
            (import "ic0" "msg_reply_data_append" (func $msg_reply_data_append (param i32 i32)))
            (func $echo
              (call $ic0_msg_arg_data_copy (i32.const 0) (i32.const 0) (i32.const 4))
              (call $msg_reply_data_append (i32.const 0) (i32.const 4))
              (call $msg_reply))
            (memory $memory 1)
            (export "memory" (memory $memory))
            (export "canister_query echo" (func $echo)))"#,
    ).unwrap();

    rt.block_on(async move {
        let endpoint = get_random_application_node_endpoint(&handle, &mut rng);
        endpoint.assert_ready(ctx).await;
        let agent = assert_create_agent(endpoint.url.as_str()).await;
        let canister_b = create_and_install(&agent, &canister_b_wasm).await;

        let canister_a_wasm = wabt::wat2wasm(format!(
            r#"(module
            (import "ic0" "msg_arg_data_copy" (func $ic0_msg_arg_data_copy (param i32) (param i32) (param i32)))
            (import "ic0" "msg_reply" (func $msg_reply))
            (import "ic0" "msg_reply_data_append" (func $msg_reply_data_append (param i32 i32)))
            (import "ic0" "debug_print" (func $debug_print (param i32) (param i32)))
            (import "ic0" "call_new"
                (func $ic0_call_new
                (param i32 i32)
                (param $method_name_src i32)    (param $method_name_len i32)
                (param $reply_fun i32)          (param $reply_env i32)
                (param $reject_fun i32)         (param $reject_env i32)
            ))
            (import "ic0" "call_data_append" (func $ic0_call_data_append (param $src i32) (param $size i32)))
            (import "ic0" "call_cycles_add" (func $ic0_call_cycles_add (param $amount i64)))
            (import "ic0" "call_perform" (func $ic0_call_perform (result i32)))
            (import "ic0" "canister_cycle_balance" (func $canister_cycle_balance (result i64)))
            (import "ic0" "msg_method_name_size" (func $msg_method_name_size (result i32)))

            ;; This call doesn't trap and models a successful API call
            (func $proxy
              (call $ic0_msg_arg_data_copy (i32.const 10) (i32.const 0) (i32.const 4))
              ;; Call B
              (call $ic0_call_new
                (i32.const 100) (i32.const {})  ;; 100 represents heap address, the size is populated by format func
                (i32.const 0) (i32.const 4)     ;; refers to "echo" on the heap
                (i32.const 0) (i32.const 0)     ;; on_reply closure
                (i32.const 1) (i32.const 0)     ;; on_reject closure
              )
              (call $ic0_call_data_append
                (i32.const 10) (i32.const 4)    ;; refers to byte copied from the payload
              )
              (call $ic0_call_perform)
              drop
              ;; Some additional work is done
              (i32.store (i32.const 80) (i32.const 0))
              (i32.store (i32.const 90) (i32.const 10000))
              (block
	            (loop
		          (i32.store (i32.const 80) (i32.add (i32.load (i32.const 80)) (i32.const 1)))
		          (br_if 1 (i32.eq (i32.load (i32.const 80)) (i32.load (i32.const 90))))
		          (br 0)
	            )
              )
            )

            ;; This function as opposite to the previous funct traps by calling some system API
            ;; that shouldn't work in this context
            (func $proxy_err
              (call $ic0_msg_arg_data_copy (i32.const 10) (i32.const 0) (i32.const 4))
              ;; Call B
              (call $ic0_call_new
                (i32.const 100) (i32.const {})  ;; 100 represents heap address, the size is populated by format func
                (i32.const 0) (i32.const 4)     ;; refers to "echo" on the heap
                (i32.const 0) (i32.const 0)     ;; on_reply closure
                (i32.const 1) (i32.const 0)     ;; on_reject closure
              )
              (call $ic0_call_data_append
                (i32.const 10) (i32.const 4)    ;; refers to byte copied from the payload
              )
              (call $ic0_call_perform)
              drop
              ;; Triggers trap
              (call $msg_method_name_size)
              drop
              ;; Some additional work is done
              (i32.store (i32.const 80) (i32.const 0))
              (i32.store (i32.const 90) (i32.const 10000))
              (block
	            (loop
		          (i32.store (i32.const 80) (i32.add (i32.load (i32.const 80)) (i32.const 1)))
		          (br_if 1 (i32.eq (i32.load (i32.const 80)) (i32.load (i32.const 90))))
		          (br 0)
	            )
              )
            )

            ;; The reply callback is executed upon successful completion of the inter-canister
            ;; method call
            (func $on_reply (param $env i32)
              (call $ic0_msg_arg_data_copy (i32.const 60) (i32.const 0) (i32.const 4))
              (i32.store (i32.const 64) (i32.const 1))
              (call $msg_reply_data_append (i32.const 60) (i32.const 5))
              (call $msg_reply)
            )

            ;; The reject callback is executed if the method call fails asynchronously or
            ;; the other canister explicitly rejects the call
            (func $on_reject (param $env i32)
              (call $msg_reply_data_append (i32.const 10) (i32.const 5))
              (call $msg_reply)
            )

            ;; Reads the wasm buffer and returns the content
            (func $read
              (call $msg_reply_data_append (i32.const 60) (i32.const 5))
              (call $msg_reply)
            )

            (func $num_cycles
              (i64.store (i32.const 40) (call $canister_cycle_balance))
            )

            (func $read_cycles
              (i64.store (i32.const 40) (call $canister_cycle_balance))
              (call $msg_reply_data_append (i32.const 40) (i32.const 8))
              (call $msg_reply)
            )

            (table funcref (elem $on_reply $on_reject))
            ;; wasm heap 1 page = 64 KB
            (memory $memory 1)
            (data (i32.const 0) "echo")
            (data (i32.const 100) "{}")
            (export "canister_update proxy" (func $proxy))
            (export "canister_update proxy_err" (func $proxy_err))
            (export "canister_query read" (func $read))
            (export "canister_query read_cycles" (func $read_cycles))
            (export "memory" (memory $memory)))"#,
            canister_b.as_slice().len(),
            canister_b.as_slice().len(),
            escape_for_wat(&canister_b))).unwrap();
        let canister_a = create_and_install(&agent, &canister_a_wasm).await;

        let ret_val = agent.query(&canister_a, "read_cycles").call().await;
        let num_cycles_before = print_validate_num_cycles(ctx, &ret_val, "Before calling proxy()");

        let ret_val = agent.update(&canister_a, "proxy").with_arg(vec![1; 4]).call().await;
        assert!(ret_val.is_ok());

        const NR_SLEEPS: usize = 3;
        for _ in 0..NR_SLEEPS {
            // Wait for few seconds before reading the data.
            sleep_until(tokio::time::Instant::from_std(Instant::now() + Duration::from_secs(5))).await;
            let ret_val = agent.query(&canister_a, "read").call().await;
            assert!(ret_val.is_ok());
            let result = ret_val.unwrap();
            // Initial value at mem location 60 is [0,0,0,0,0]
            if result.as_slice() != [0,0,0,0,0] {
                // The last (5th) byte having a value of 1 means that the inter-canister response was processed by on_reply
                assert_eq!([1,1,1,1,1], result.as_slice(), "Expected result is [1,1,1,1,1]");
                break;
            }
        }

        let ret_val = agent.query(&canister_a, "read_cycles").call().await;
        let num_cycles_after = print_validate_num_cycles(ctx,&ret_val, "After calling proxy()");
        assert!((num_cycles_after < num_cycles_before), "num_cycles_after is not less than num_cycles_before");
        let cycles_used_proxy = num_cycles_before - num_cycles_after;
        if ENABLE_DEBUG_LOG {
            debug!(ctx.logger, "total cycles used = {}", cycles_used_proxy);
        }

        /* Now make intercanister call proxy_err that throws error  and check the cycles used */
        let ret_val = agent.query(&canister_a, "read_cycles").call().await;
        let num_cycles_before = print_validate_num_cycles(ctx, &ret_val, "Before calling proxy_err()");

        let ret_val = agent.update(&canister_a, "proxy_err").with_arg(vec![2; 4]).call().await;
        assert!(ret_val.is_ok());

        // Wait for few seconds before reading the data.
        for _ in 0..NR_SLEEPS {
            sleep_until(tokio::time::Instant::from_std(Instant::now() + Duration::from_secs(5))).await;
            let ret_val = agent.query(&canister_a, "read").call().await;
            assert!(ret_val.is_ok());
            let result = ret_val.unwrap();
            // The initial value is [1,1,1,1,1] because of the previous call that succeeded and copies [1,1,1,1,1] to mem location 60
            if result.as_slice() != [1,1,1,1,1] {
                // The last (5th) byte having a value of 1 means that the inter-canister response was processed by on_reply
                assert_eq!([2,2,2,2,1], result.as_slice(), "Expected result is [2,2,2,2,1]");
                break;
            }
        }

        let ret_val = agent.query(&canister_a, "read_cycles").call().await;
        let num_cycles_after = print_validate_num_cycles(ctx,&ret_val, "After calling proxy_err()");
        assert!((num_cycles_after < num_cycles_before), "num_cycles_after is not less than num_cycles_before");
        let cycles_used_proxy_err = num_cycles_before - num_cycles_after;
        if ENABLE_DEBUG_LOG {
            debug!(ctx.logger, "total cycles used = {}", cycles_used_proxy_err);
        }
        assert!(cycles_used_proxy > cycles_used_proxy_err);

    });
}
/*
   This test has two canister's A and B. Canister A is the one that will interfaced
   by the client and canister B is called by Canister A. The intent is to test malicious
   inter-canister calls
*/
This test has two canister's A and B. Canister A is the one that will interfaced
by the client and canister B is called by Canister A. The intent is to test malicious
inter-canister calls
This test has two canister ' s A and B . Canister A is the one that will interfaced by the client and canister B is called by Canister A . The intent is to test malicious inter - canister calls
pub fn malicious_intercanister_calls(handle: IcHandle, ctx: &ic_fondue::pot::Context) {
    let mut rng = ctx.rng.clone();
    let rt = tokio::runtime::Runtime::new().expect("Could not create tokio runtime.");
    let canister_b_wasm = wabt::wat2wasm(
        r#"(module
            (import "ic0" "msg_arg_data_copy" (func $ic0_msg_arg_data_copy (param i32) (param i32) (param i32)))
            (import "ic0" "msg_reply" (func $msg_reply))
            (import "ic0" "msg_reply_data_append" (func $msg_reply_data_append (param i32 i32)))
            (func $echo
              (call $ic0_msg_arg_data_copy (i32.const 0) (i32.const 0) (i32.const 4))
              (call $msg_reply_data_append (i32.const 0) (i32.const 4))
              (call $msg_reply))
            (memory $memory 1)
            (export "memory" (memory $memory))
            (export "canister_query echo" (func $echo)))"#,
    ).unwrap();
    rt.block_on(async move {
        let endpoint = get_random_application_node_endpoint(&handle, &mut rng);
        endpoint.assert_ready(ctx).await;
        let agent = assert_create_agent(endpoint.url.as_str()).await;
        let canister_b = create_and_install(&agent, &canister_b_wasm).await;
        let canister_a_wasm = wabt::wat2wasm(format!(
            r#"(module
            (import "ic0" "msg_arg_data_copy" (func $ic0_msg_arg_data_copy (param i32) (param i32) (param i32)))
            (import "ic0" "msg_reply" (func $msg_reply))
            (import "ic0" "msg_reply_data_append" (func $msg_reply_data_append (param i32 i32)))
            (import "ic0" "debug_print" (func $debug_print (param i32) (param i32)))
            (import "ic0" "call_new"
                (func $ic0_call_new
                (param i32 i32)
                (param $method_name_src i32)    (param $method_name_len i32)
                (param $reply_fun i32)          (param $reply_env i32)
                (param $reject_fun i32)         (param $reject_env i32)
            ))
            (import "ic0" "call_data_append" (func $ic0_call_data_append (param $src i32) (param $size i32)))
            (import "ic0" "call_cycles_add" (func $ic0_call_cycles_add (param $amount i64)))
            (import "ic0" "call_perform" (func $ic0_call_perform (result i32)))
            (import "ic0" "canister_cycle_balance" (func $canister_cycle_balance (result i64)))
            (import "ic0" "msg_method_name_size" (func $msg_method_name_size (result i32)))
            ;; This call doesn't trap and models a successful API call
            (func $proxy
              (call $ic0_msg_arg_data_copy (i32.const 10) (i32.const 0) (i32.const 4))
              ;; Call B
              (call $ic0_call_new
                (i32.const 100) (i32.const {})  ;; 100 represents heap address, the size is populated by format func
                (i32.const 0) (i32.const 4)     ;; refers to "echo" on the heap
                (i32.const 0) (i32.const 0)     ;; on_reply closure
                (i32.const 1) (i32.const 0)     ;; on_reject closure
              )
              (call $ic0_call_data_append
                (i32.const 10) (i32.const 4)    ;; refers to byte copied from the payload
              )
              (call $ic0_call_perform)
              drop
              ;; Some additional work is done
              (i32.store (i32.const 80) (i32.const 0))
              (i32.store (i32.const 90) (i32.const 10000))
              (block
	            (loop
		          (i32.store (i32.const 80) (i32.add (i32.load (i32.const 80)) (i32.const 1)))
		          (br_if 1 (i32.eq (i32.load (i32.const 80)) (i32.load (i32.const 90))))
		          (br 0)
	            )
              )
            )
            ;; This function as opposite to the previous funct traps by calling some system API
            ;; that shouldn't work in this context
            (func $proxy_err
              (call $ic0_msg_arg_data_copy (i32.const 10) (i32.const 0) (i32.const 4))
              ;; Call B
              (call $ic0_call_new
                (i32.const 100) (i32.const {})  ;; 100 represents heap address, the size is populated by format func
                (i32.const 0) (i32.const 4)     ;; refers to "echo" on the heap
                (i32.const 0) (i32.const 0)     ;; on_reply closure
                (i32.const 1) (i32.const 0)     ;; on_reject closure
              )
              (call $ic0_call_data_append
                (i32.const 10) (i32.const 4)    ;; refers to byte copied from the payload
              )
              (call $ic0_call_perform)
              drop
              ;; Triggers trap
              (call $msg_method_name_size)
              drop
              ;; Some additional work is done
              (i32.store (i32.const 80) (i32.const 0))
              (i32.store (i32.const 90) (i32.const 10000))
              (block
	            (loop
		          (i32.store (i32.const 80) (i32.add (i32.load (i32.const 80)) (i32.const 1)))
		          (br_if 1 (i32.eq (i32.load (i32.const 80)) (i32.load (i32.const 90))))
		          (br 0)
	            )
              )
            )
            ;; The reply callback is executed upon successful completion of the inter-canister
            ;; method call
            (func $on_reply (param $env i32)
              (call $ic0_msg_arg_data_copy (i32.const 60) (i32.const 0) (i32.const 4))
              (i32.store (i32.const 64) (i32.const 1))
              (call $msg_reply_data_append (i32.const 60) (i32.const 5))
              (call $msg_reply)
            )
            ;; The reject callback is executed if the method call fails asynchronously or
            ;; the other canister explicitly rejects the call
            (func $on_reject (param $env i32)
              (call $msg_reply_data_append (i32.const 10) (i32.const 5))
              (call $msg_reply)
            )
            ;; Reads the wasm buffer and returns the content
            (func $read
              (call $msg_reply_data_append (i32.const 60) (i32.const 5))
              (call $msg_reply)
            )
            (func $num_cycles
              (i64.store (i32.const 40) (call $canister_cycle_balance))
            )
            (func $read_cycles
              (i64.store (i32.const 40) (call $canister_cycle_balance))
              (call $msg_reply_data_append (i32.const 40) (i32.const 8))
              (call $msg_reply)
            )
            (table funcref (elem $on_reply $on_reject))
            ;; wasm heap 1 page = 64 KB
            (memory $memory 1)
            (data (i32.const 0) "echo")
            (data (i32.const 100) "{}")
            (export "canister_update proxy" (func $proxy))
            (export "canister_update proxy_err" (func $proxy_err))
            (export "canister_query read" (func $read))
            (export "canister_query read_cycles" (func $read_cycles))
            (export "memory" (memory $memory)))"#,
            canister_b.as_slice().len(),
            canister_b.as_slice().len(),
            escape_for_wat(&canister_b))).unwrap();
        let canister_a = create_and_install(&agent, &canister_a_wasm).await;
        let ret_val = agent.query(&canister_a, "read_cycles").call().await;
        let num_cycles_before = print_validate_num_cycles(ctx, &ret_val, "Before calling proxy()");
        let ret_val = agent.update(&canister_a, "proxy").with_arg(vec![1; 4]).call().await;
        assert!(ret_val.is_ok());
        const NR_SLEEPS: usize = 3;
        for _ in 0..NR_SLEEPS {
            // Wait for few seconds before reading the data.
            sleep_until(tokio::time::Instant::from_std(Instant::now() + Duration::from_secs(5))).await;
            let ret_val = agent.query(&canister_a, "read").call().await;
            assert!(ret_val.is_ok());
            let result = ret_val.unwrap();
            // Initial value at mem location 60 is [0,0,0,0,0]
            if result.as_slice() != [0,0,0,0,0] {
                // The last (5th) byte having a value of 1 means that the inter-canister response was processed by on_reply
                assert_eq!([1,1,1,1,1], result.as_slice(), "Expected result is [1,1,1,1,1]");
                break;
            }
        }
        let ret_val = agent.query(&canister_a, "read_cycles").call().await;
        let num_cycles_after = print_validate_num_cycles(ctx,&ret_val, "After calling proxy()");
        assert!((num_cycles_after < num_cycles_before), "num_cycles_after is not less than num_cycles_before");
        let cycles_used_proxy = num_cycles_before - num_cycles_after;
        if ENABLE_DEBUG_LOG {
            debug!(ctx.logger, "total cycles used = {}", cycles_used_proxy);
        }
        /* Now make intercanister call proxy_err that throws error  and check the cycles used */
        let ret_val = agent.query(&canister_a, "read_cycles").call().await;
        let num_cycles_before = print_validate_num_cycles(ctx, &ret_val, "Before calling proxy_err()");
        let ret_val = agent.update(&canister_a, "proxy_err").with_arg(vec![2; 4]).call().await;
        assert!(ret_val.is_ok());
        // Wait for few seconds before reading the data.
        for _ in 0..NR_SLEEPS {
            sleep_until(tokio::time::Instant::from_std(Instant::now() + Duration::from_secs(5))).await;
            let ret_val = agent.query(&canister_a, "read").call().await;
            assert!(ret_val.is_ok());
            let result = ret_val.unwrap();
            // The initial value is [1,1,1,1,1] because of the previous call that succeeded and copies [1,1,1,1,1] to mem location 60
            if result.as_slice() != [1,1,1,1,1] {
                // The last (5th) byte having a value of 1 means that the inter-canister response was processed by on_reply
                assert_eq!([2,2,2,2,1], result.as_slice(), "Expected result is [2,2,2,2,1]");
                break;
            }
        }
        let ret_val = agent.query(&canister_a, "read_cycles").call().await;
        let num_cycles_after = print_validate_num_cycles(ctx,&ret_val, "After calling proxy_err()");
        assert!((num_cycles_after < num_cycles_before), "num_cycles_after is not less than num_cycles_before");
        let cycles_used_proxy_err = num_cycles_before - num_cycles_after;
        if ENABLE_DEBUG_LOG {
            debug!(ctx.logger, "total cycles used = {}", cycles_used_proxy_err);
        }
        assert!(cycles_used_proxy > cycles_used_proxy_err);
    });
}
pub fn malicious_intercanister_calls ( handle : IcHandle , ctx : & ic_fondue :: pot :: Context ) { let mut rng = ctx . rng . clone ( ) ; let rt = tokio :: runtime :: Runtime :: new ( ) . expect ( " " ) ; let canister_b_wasm = wabt :: wat2wasm ( r#"(module
            (import "ic0" "msg_arg_data_copy" (func $ic0_msg_arg_data_copy (param i32) (param i32) (param i32)))
            (import "ic0" "msg_reply" (func $msg_reply))
            (import "ic0" "msg_reply_data_append" (func $msg_reply_data_append (param i32 i32)))
            (func $echo
              (call $ic0_msg_arg_data_copy (i32.const 0) (i32.const 0) (i32.const 4))
              (call $msg_reply_data_append (i32.const 0) (i32.const 4))
              (call $msg_reply))
            (memory $memory 1)
            (export "memory" (memory $memory))
            (export "canister_query echo" (func $echo)))"# , ) . unwrap ( ) ; rt . block_on ( async move { let endpoint = get_random_application_node_endpoint ( & handle , & mut rng ) ; endpoint . assert_ready ( ctx ) . await ; let agent = assert_create_agent ( endpoint . url . as_str ( ) ) . await ; let canister_b = create_and_install ( & agent , & canister_b_wasm ) . await ; let canister_a_wasm = wabt :: wat2wasm ( format ! ( r#"(module
            (import "ic0" "msg_arg_data_copy" (func $ic0_msg_arg_data_copy (param i32) (param i32) (param i32)))
            (import "ic0" "msg_reply" (func $msg_reply))
            (import "ic0" "msg_reply_data_append" (func $msg_reply_data_append (param i32 i32)))
            (import "ic0" "debug_print" (func $debug_print (param i32) (param i32)))
            (import "ic0" "call_new"
                (func $ic0_call_new
                (param i32 i32)
                (param $method_name_src i32)    (param $method_name_len i32)
                (param $reply_fun i32)          (param $reply_env i32)
                (param $reject_fun i32)         (param $reject_env i32)
            ))
            (import "ic0" "call_data_append" (func $ic0_call_data_append (param $src i32) (param $size i32)))
            (import "ic0" "call_cycles_add" (func $ic0_call_cycles_add (param $amount i64)))
            (import "ic0" "call_perform" (func $ic0_call_perform (result i32)))
            (import "ic0" "canister_cycle_balance" (func $canister_cycle_balance (result i64)))
            (import "ic0" "msg_method_name_size" (func $msg_method_name_size (result i32)))

            ;; This call doesn't trap and models a successful API call
            (func $proxy
              (call $ic0_msg_arg_data_copy (i32.const 10) (i32.const 0) (i32.const 4))
              ;; Call B
              (call $ic0_call_new
                (i32.const 100) (i32.const {})  ;; 100 represents heap address, the size is populated by format func
                (i32.const 0) (i32.const 4)     ;; refers to "echo" on the heap
                (i32.const 0) (i32.const 0)     ;; on_reply closure
                (i32.const 1) (i32.const 0)     ;; on_reject closure
              )
              (call $ic0_call_data_append
                (i32.const 10) (i32.const 4)    ;; refers to byte copied from the payload
              )
              (call $ic0_call_perform)
              drop
              ;; Some additional work is done
              (i32.store (i32.const 80) (i32.const 0))
              (i32.store (i32.const 90) (i32.const 10000))
              (block
	            (loop
		          (i32.store (i32.const 80) (i32.add (i32.load (i32.const 80)) (i32.const 1)))
		          (br_if 1 (i32.eq (i32.load (i32.const 80)) (i32.load (i32.const 90))))
		          (br 0)
	            )
              )
            )

            ;; This function as opposite to the previous funct traps by calling some system API
            ;; that shouldn't work in this context
            (func $proxy_err
              (call $ic0_msg_arg_data_copy (i32.const 10) (i32.const 0) (i32.const 4))
              ;; Call B
              (call $ic0_call_new
                (i32.const 100) (i32.const {})  ;; 100 represents heap address, the size is populated by format func
                (i32.const 0) (i32.const 4)     ;; refers to "echo" on the heap
                (i32.const 0) (i32.const 0)     ;; on_reply closure
                (i32.const 1) (i32.const 0)     ;; on_reject closure
              )
              (call $ic0_call_data_append
                (i32.const 10) (i32.const 4)    ;; refers to byte copied from the payload
              )
              (call $ic0_call_perform)
              drop
              ;; Triggers trap
              (call $msg_method_name_size)
              drop
              ;; Some additional work is done
              (i32.store (i32.const 80) (i32.const 0))
              (i32.store (i32.const 90) (i32.const 10000))
              (block
	            (loop
		          (i32.store (i32.const 80) (i32.add (i32.load (i32.const 80)) (i32.const 1)))
		          (br_if 1 (i32.eq (i32.load (i32.const 80)) (i32.load (i32.const 90))))
		          (br 0)
	            )
              )
            )

            ;; The reply callback is executed upon successful completion of the inter-canister
            ;; method call
            (func $on_reply (param $env i32)
              (call $ic0_msg_arg_data_copy (i32.const 60) (i32.const 0) (i32.const 4))
              (i32.store (i32.const 64) (i32.const 1))
              (call $msg_reply_data_append (i32.const 60) (i32.const 5))
              (call $msg_reply)
            )

            ;; The reject callback is executed if the method call fails asynchronously or
            ;; the other canister explicitly rejects the call
            (func $on_reject (param $env i32)
              (call $msg_reply_data_append (i32.const 10) (i32.const 5))
              (call $msg_reply)
            )

            ;; Reads the wasm buffer and returns the content
            (func $read
              (call $msg_reply_data_append (i32.const 60) (i32.const 5))
              (call $msg_reply)
            )

            (func $num_cycles
              (i64.store (i32.const 40) (call $canister_cycle_balance))
            )

            (func $read_cycles
              (i64.store (i32.const 40) (call $canister_cycle_balance))
              (call $msg_reply_data_append (i32.const 40) (i32.const 8))
              (call $msg_reply)
            )

            (table funcref (elem $on_reply $on_reject))
            ;; wasm heap 1 page = 64 KB
            (memory $memory 1)
            (data (i32.const 0) "echo")
            (data (i32.const 100) "{}")
            (export "canister_update proxy" (func $proxy))
            (export "canister_update proxy_err" (func $proxy_err))
            (export "canister_query read" (func $read))
            (export "canister_query read_cycles" (func $read_cycles))
            (export "memory" (memory $memory)))"# canister_b as_slice ( ) len ( ) canister_b as_slice ( ) len ( ) escape_for_wat ( canister_b ) ) ) . unwrap ( ) ; let canister_a = create_and_install ( & agent , & canister_a_wasm ) . await ; let ret_val = agent . query ( & canister_a , " " ) . call ( ) . await ; let num_cycles_before = print_validate_num_cycles ( ctx , & ret_val , " " ) ; let ret_val = agent . update ( & canister_a , " " ) . with_arg ( vec ! [ 1 4 ] ) . call ( ) . await ; assert ! ( ret_val is_ok ( ) ) ; const NR_SLEEPS : usize = 3 ; for _ in 0 .. NR_SLEEPS { // Wait for few seconds before reading the data. sleep_until ( tokio :: time :: Instant :: from_std ( Instant :: now ( ) + Duration :: from_secs ( 5 ) ) ) . await ; let ret_val = agent . query ( & canister_a , " " ) . call ( ) . await ; assert ! ( ret_val is_ok ( ) ) ; let result = ret_val . unwrap ( ) ; // Initial value at mem location 60 is [0,0,0,0,0] if result . as_slice ( ) != [ 0 , 0 , 0 , 0 , 0 ] { // The last (5th) byte having a value of 1 means that the inter-canister response was processed by on_reply assert_eq ! ( [ 1 1 1 1 1 ] result as_slice ( ) " " ) ; break ; } } let ret_val = agent . query ( & canister_a , " " ) . call ( ) . await ; let num_cycles_after = print_validate_num_cycles ( ctx , & ret_val , " " ) ; assert ! ( ( num_cycles_after num_cycles_before ) " " ) ; let cycles_used_proxy = num_cycles_before - num_cycles_after ; if ENABLE_DEBUG_LOG { debug ! ( ctx logger " " cycles_used_proxy ) ; } /* Now make intercanister call proxy_err that throws error  and check the cycles used */ let ret_val = agent . query ( & canister_a , " " ) . call ( ) . await ; let num_cycles_before = print_validate_num_cycles ( ctx , & ret_val , " " ) ; let ret_val = agent . update ( & canister_a , " " ) . with_arg ( vec ! [ 2 4 ] ) . call ( ) . await ; assert ! ( ret_val is_ok ( ) ) ; // Wait for few seconds before reading the data. for _ in 0 .. NR_SLEEPS { sleep_until ( tokio :: time :: Instant :: from_std ( Instant :: now ( ) + Duration :: from_secs ( 5 ) ) ) . await ; let ret_val = agent . query ( & canister_a , " " ) . call ( ) . await ; assert ! ( ret_val is_ok ( ) ) ; let result = ret_val . unwrap ( ) ; // The initial value is [1,1,1,1,1] because of the previous call that succeeded and copies [1,1,1,1,1] to mem location 60 if result . as_slice ( ) != [ 1 , 1 , 1 , 1 , 1 ] { // The last (5th) byte having a value of 1 means that the inter-canister response was processed by on_reply assert_eq ! ( [ 2 2 2 2 1 ] result as_slice ( ) " " ) ; break ; } } let ret_val = agent . query ( & canister_a , " " ) . call ( ) . await ; let num_cycles_after = print_validate_num_cycles ( ctx , & ret_val , " " ) ; assert ! ( ( num_cycles_after num_cycles_before ) " " ) ; let cycles_used_proxy_err = num_cycles_before - num_cycles_after ; if ENABLE_DEBUG_LOG { debug ! ( ctx logger " " cycles_used_proxy_err ) ; } assert ! ( cycles_used_proxy cycles_used_proxy_err ) ; } ) ; }
This test has two canister's A and B. Canister A is the one that will interfaced
by the client and canister B is called by Canister A.
This test has two canister ' s A and B . Canister A is the one that will interfaced by the client and canister B is called by Canister A .
handle
IcHandle
ctx
&ic_fondue::pot::Context
handle
IcHandle
ctx
&ic_fondue::pot::Context