Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

func type decoding errors? #348

Closed
lastmjs opened this issue May 10, 2022 · 1 comment
Closed

func type decoding errors? #348

lastmjs opened this issue May 10, 2022 · 1 comment
Labels
enhancement New feature or request

Comments

@lastmjs
Copy link
Contributor

lastmjs commented May 10, 2022

I'm a bit confused with some errors I am running into with decoding of func types, and I am wondering if this might be a problem with the Candid implementation in Rust. Here's more info in the forum: https://forum.dfinity.org/t/candid-func-types-as-parameters/12857

It seems like the Rust func types don't have enough information to serialize/deserialize correctly. If I just give the Rust func struct a principal and a method name, how can it handle func types with parameters and return types? It seems there is a mismatch somewhere in the Candid serialization/deserialization process where my funcs are of type func () -> () even though my Candid file (the file I generate my Rust types from) has parameters and return types.

Example Candid:

type GetBlocksArgs = record {
    "start": nat64;
    "length": nat64;
};

type TransferArgs = record {
    "memo": nat64;
    "amount": Tokens;
    "fee": Tokens;
    "from_subaccount": opt vec nat8;
    "to": vec nat8;
    "created_at_time": opt TimeStamp;
};

type AccountBalanceArgs = record {
    "account": vec nat8;
};

type TransferFeeArg = record {
    
};

type Tokens = record {
    "e8s": nat64;
};

type TransferFee = record {
    "transfer_fee": Tokens;
};

type QueryBlocksResponse = record {
    "chain_length": nat64;
    "certificate": opt vec nat8;
    "blocks": vec Block;
    "first_block_index": nat64;
    "archived_blocks": vec record { "start": nat64; "length": nat64; "callback": QueryArchiveFn; };
};

type SymbolResult = record {
    "symbol": text;
};

type NameResult = record {
    "name": text;
};

type DecimalsResult = record {
    "decimals": nat32;
};

type Archives = record {
    "archives": vec Archive;
};

type TimeStamp = record {
    "timestamp_nanos": nat64;
};

type Block = record {
    "parent_hash": opt vec nat8;
    "transaction": Transaction;
    "timestamp": TimeStamp;
};

type Transaction = record {
    "memo": nat64;
    "operation": opt Operation;
    "created_at_time": TimeStamp;
};

type Archive = record {
    "canister_id": principal;
};

type BlockRange = record {
    "blocks": vec Block;
};

type ExecuteTransferResult = variant { "ok": TransferResult; "err": text };

type GetAccountBalanceResult = variant { "ok": Tokens; "err": text };

type GetTransferFeeResult = variant { "ok": TransferFee; "err": text };

type GetBlocksResult = variant { "ok": QueryBlocksResponse; "err": text };

type GetSymbolResult = variant { "ok": text; "err": text };

type GetNameResult = variant { "ok": text; "err": text };

type GetDecimalsResult = variant { "ok": nat32; "err": text };

type GetArchivesResult = variant { "ok": Archives; "err": text };

type TransferResult = variant { "Ok": nat64; "Err": TransferError };

type QueryArchiveResult = variant { "Ok": BlockRange; "Err": QueryArchiveError };

type TransferError = variant { "BadFee": record { "expected_fee": Tokens; }; "InsufficientFunds": record { "balance": Tokens; }; "TxTooOld": record { "allowed_window_nanos": nat64; }; "TxCreatedInFuture": null; "TxDuplicate": record { "duplicate_of": nat64; } };

type Operation = variant { "Mint": record { "to": vec nat8; "amount": Tokens; }; "Burn": record { "from": vec nat8; "amount": Tokens; }; "Transfer": record { "from": vec nat8; "to": vec nat8; "amount": Tokens; "fee": Tokens; } };

type QueryArchiveError = variant { "BadFirstBlockIndex": record { "requested_index": nat64; "first_valid_index": nat64; }; "Other": record { "error_code": nat64; "error_message": text; } };

type QueryArchiveFn = func (GetBlocksArgs) -> (QueryArchiveResult) query;

service: {
    "execute_transfer": (text, nat64, nat64, opt nat64) -> (ExecuteTransferResult);
    "get_account_balance": (text) -> (GetAccountBalanceResult);
    "get_transfer_fee": () -> (GetTransferFeeResult);
    "get_blocks": (GetBlocksArgs) -> (GetBlocksResult);
    "get_symbol": () -> (GetSymbolResult);
    "get_name": () -> (GetNameResult);
    "get_decimals": () -> (GetDecimalsResult);
    "get_archives": () -> (GetArchivesResult);
}

When calling get_blocks I get this error:

 test get_blocks failed Error: Call was rejected:en Completed in 2ms
  Request ID: 11e5e1bf1c1156a4ea9a32ba0b301a731bf01da8dd37d10d4f9ed082ba5ee6ee
  Reject code: 5
  Reject text: Canister rrkah-fqaaa-aaaaa-aaaaq-cai trapped explicitly: Custom(Fail to decode argument 0 from table0 to record {
  certificate : opt vec nat8;
  blocks : vec record {
    transaction : record {
      memo : nat64;
      operation : opt variant {
        Burn : record { from : vec nat8; amount : record { e8s : nat64 } };
        Mint : record { to : vec nat8; amount : record { e8s : nat64 } };
        Transfer : record {
          to : vec nat8;
          fee : record { e8s : nat64 };
          from : vec nat8;
          amount : record { e8s : nat64 };
        };
      };
      created_at_time : record { timestamp_nanos : nat64 };
    };
    timestamp : record { timestamp_nanos : nat64 };
    parent_hash : opt vec nat8;
  };
  chain_length : nat64;
  first_block_index : nat64;
  archived_blocks : vec record {
    callback : func () -> ();
    start : nat64;
    length : nat64;
  };
}

Caused by:
    0: input: 4449444c156c0597928bda010186dda8bf0a03a4c7a8ce0c7891fb95920d7883f4f4c40f0c6e026d7b6d046c03dec389dc0405d6a9bbae0a0bc39c99ad0f016c03ba89e5c20478a78882820a0682f3f3910c0b6b03ef80e5df0207c2f5d5990309cbd6fda00b0a6c02eaca8a9e0402d8a38ca80d086c01e0a9b302786c02fbca0102d8a38ca80d086c04fbca0102c6fcb60208eaca8a9e0402d8a38ca80d086c01d6f68e8001786d0d6c03c5b39af8070ee2e8ada00878e6a99ef809786a010f011001016c02e2e8ada00878e6a99ef809786b02bc8a0111c5fed201126c0186dda8bf0a036b02b0ad8cd40413b0ad8fcd0c146c02c1a482a6057880d5dbdd05786c0290c6c1960571c498b1b50d780100_000100000000000000000120082ecf2e3f647ac600f43f38a68342fba5b8e68b085f02592b77f39808a8d2b500e8764817000000766ea381dad1ed16766ea381dad1ed16000100000000000000000000000000000000
       table: type table0 = record {
         457_361_687 : table1;
         2_817_142_406 : table3;
         3_385_467_812 : nat64;
         3_527_769_489 : nat64;
         4_171_053_571 : table12;
       }
       type table1 = opt table2
       type table10 = record {
         25_979 : table2;
         5_094_982 : table8;
         1_136_829_802 : table2;
         3_573_748_184 : table8;
       }
       type table11 = record { 268_680_022 : nat64 }
       type table12 = vec table13
       type table13 = record { 2_131_139_013 : table14; 2_215_343_202 : nat64; 2_668_074_214 : nat64 }
       type table14 = func (table15) -> (table16) query
       type table15 = record { 2_215_343_202 : nat64; 2_668_074_214 : nat64 }
       type table16 = variant { 17_724 : table17; 3_456_837 : table18 }
       type table17 = record { 2_817_142_406 : table3 }
       type table18 = variant { 1_250_105_008 : table19; 3_382_957_744 : table20 }
       type table19 = record { 1_421_906_497 : nat64; 1_538_714_240 : nat64 }
       type table2 = vec nat8
       type table20 = record { 1_389_388_560 : text; 3_601_615_940 : nat64 }
       type table3 = vec table4
       type table4 = record {
         1_266_835_934 : table5;
         2_781_795_542 : table11;
         4_121_316_931 : table1;
       }
       type table5 = record {
         1_213_809_850 : nat64;
         2_688_582_695 : table6;
         3_258_775_938 : table11;
       }
       type table6 = variant { 737_755_247 : table7; 859_142_850 : table9; 3_021_957_963 : table10 }
       type table7 = record { 1_136_829_802 : table2; 3_573_748_184 : table8 }
       type table8 = record { 5_035_232 : nat64 }
       type table9 = record { 25_979 : table2; 3_573_748_184 : table8 }
       wire_type: table0, expect_type: record {
         certificate : opt vec nat8;
         blocks : vec record {
           transaction : record {
             memo : nat64;
             operation : opt variant {
               Burn : record { from : vec nat8; amount : record { e8s : nat64 } };
               Mint : record { to : vec nat8; amount : record { e8s : nat64 } };
               Transfer : record {
                 to : vec nat8;
                 fee : record { e8s : nat64 };
                 from : vec nat8;
                 amount : record { e8s : nat64 };
               };
             };
             created_at_time : record { timestamp_nanos : nat64 };
           };
           timestamp : record { timestamp_nanos : nat64 };
           parent_hash : opt vec nat8;
         };
         chain_length : nat64;
         first_block_index : nat64;
         archived_blocks : vec record {
           callback : func () -> ();
           start : nat64;
           length : nat64;
         };
       }
    1: table0 is not a subtype of record {
         certificate : opt vec nat8;
         blocks : vec record {
           transaction : record {
             memo : nat64;
             operation : opt variant {
               Burn : record { from : vec nat8; amount : record { e8s : nat64 } };
               Mint : record { to : vec nat8; amount : record { e8s : nat64 } };
               Transfer : record {
                 to : vec nat8;
                 fee : record { e8s : nat64 };
                 from : vec nat8;
                 amount : record { e8s : nat64 };
               };
             };
             created_at_time : record { timestamp_nanos : nat64 };
           };
           timestamp : record { timestamp_nanos : nat64 };
           parent_hash : opt vec nat8;
         };
         chain_length : nat64;
         first_block_index : nat64;
         archived_blocks : vec record {
           callback : func () -> ();
           start : nat64;
           length : nat64;
         };
       }
    2: Record field archived_blocks: table12 is not a subtype of vec record { callback : func () -> (); start : nat64; length : nat64 }
    3: Record field callback: table14 is not a subtype of func () -> ()
    4: Function mode mismatch)

Notice that archived_blocks.callback is just func () -> ()...why doesn't it have the correct type information?

@chenyan-dfinity
Copy link
Contributor

Duplicate of #273

@chenyan-dfinity chenyan-dfinity marked this as a duplicate of #273 May 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants