dfinity / cdk-rs

Rust canister development kit for the Internet Computer.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cross Canister Calls Not Serialising Principal Correctly

blutooth opened this issue · comments

commented

counter.rs

#[derive(CandidType, Deserialize)]
struct OwnerResult {
    canister_id: candid::Principal,
}

#[query]
fn owner() -> OwnerResult{
    unsafe {
        OwnerResult{
            canister_id: candid::Principal::management_canister()
        }
    }
}
service : {
  "owner": () -> (OwnerResult) query;
}

In another file, I can't just return CounterCanister::owner().await.0.canister_id:
It's expecting principal to be a vec of bytes, rather than a principal. The following code below compiles but then returns an error at runtime...


service : {
  "owner": () -> (principal) query;
}

#[import(canister = "counter_rs")]
struct CounterCanister;

#[query]
async fn owner() ->  candid::Principal {
    
        let b = CounterCanister::owner().await.0;
        let (a,): (candid::Principal,) = decode_args(&b.canister_id).unwrap();
        a
    
}



Are there any workarounds currently?

I believe the root cause of the error is that you're trying to interpret bytes of a Principal as if it was a Candid message containing a single value: a principal. This sounds like the same thing, but it's not: a candid message has additional structure (type table, number of items in the message, etc.), principal is just bytes.

I'm not sure what the exact type of CounterCanister::owner().await.0 in your case, but calling Principal::from_slice should solve your problem, something like

let a = candid::Principal::from_slice(&b.canister_id);

@blutooth, I'm closing this issue, for now. Please reopen it if my advice above didn't help you.