Issue with decoding response in PocketIC integration tests

Hi,

I’m finally trying PocketIC for the first time and I’m encountering an issue in my integration tests: Candid stuff :slight_smile:

I want to test the following function:

fn schnorr_public_key(arg: SchnorrPublicKey) -> SchnorrPublicKeyReply {}

and do the following in my test:

let reply: Result<SignWithSchnorrReply, String> = update(&pic, my_principal,  canister_id, "sign_with_schnorr", encode_one(&payload).unwrap());

pub fn update<T: CandidType + for<'de> Deserialize<'de>>(
    ic: &PocketIc,
    sender: Principal,
    receiver: Principal,
    method: &str,
    args: Vec<u8>,
) -> Result<T, String> {
    match ic.update_call(receiver, sender, method, args) {
        Ok(WasmResult::Reply(data)) => decode_one(&data).unwrap(),
        Ok(WasmResult::Reject(error_message)) => Err(error_message.to_string()),
        Err(user_error) => Err(user_error.to_string()),
    }
}

However, the tests fail at decoding the reply:

Feb 06 09:12:28.662 WARN s:/n:/ic_state_manager/ic_state_manager No state available with certification.
thread 'test_sign_with_schnorr' panicked at tests/tests.rs:60:58:
called `Result::unwrap()` on an `Err` value: Custom(input: 4449444c026c01f8c5aeab01016d7b0100_40d0e65fdb6cb0baf7c3cd285d268910233a3c175f2ca9ffbd812fed5bd6d9411cca2541b337bc2d33787059e2958515af11cf600369bb5919d4b011282e9444ba
table: type table0 = record { 359_375_608 : table1 }
type table1 = vec nat8
wire_type: record { 359_375_608 : table1 }, expect_type: variant { Ok : record { signature : vec nat8 }; Err : text }

Caused by:
    0: Fail to decode argument 0 from table0 to variant { Ok : record { signature : vec nat8 }; Err : text }
    1: Subtyping error: Type mismatch at ...src/index.crates.io-6f17d22bba15001f/candid-0.9.11/src/de.rs:877)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
test test_sign_with_schnorr ... FAILED

Complete code is here: GitHub - domwoe/schnorr_canister: Canister to create schnorr signatures on the Internet Computer.

Hi @domwoe, it looks like the bug does not come from PocketIC but rather from supplying a different candid format than what the function expects. In the error message, it looks like the canister expects a variant, but a record was supplied.

(signature hashes to 359_375_608, so they’re equivalent)

Basically the thing you’re trying to decode Ok(thing) but you receive thing.

Looking at your code you have

pub struct SignWithSchnorrReply {
    pub signature: Vec<u8>,
}

#[ic_cdk::update]
fn sign_with_schnorr(arg: SignWithSchnorr) -> SignWithSchnorrReply {

So your function returns only thing while in your test you try to decode to Ok(thing)

Ah, thanks @Vivienne !

(signature hashes to 359_375_608 , so they’re equivalent)

How does one arrive at this value/what hash function are you using here? :slight_smile:

I’m using didc hash "signature". No clue what algorithm is behind that :slightly_smiling_face: You can download didc in the candid repo

Thanks! Somewhat unrelated, but I’ve always wondered why candid does not just tell you in plaintext what it wants. Why does it show these signatures only?

A string costs a lot more bytes than a hash. And if you have the interface definition it is easy to reverse