New and Improved Rust CDK: First-class support for Rust Canister Development

Ahoy IC devs!

I would like to take the time to introduce Linwei Shang (@lwshang). Linwei has been working on the SDK team for a while now, more importantly he has been working to improve the Rust Canister developer experience.

The most notable changes are:

  • dfx now recognize “rust” type canisters
  • dfx new --type=rust to start new project with Rust canister

For more details, please check out the following links:

I encourage folks to ping this thread or create new ones for any Rust developer experience questions. @lwshang is here to help.

14 Likes

Hi all, I’m Linwei, a software engineer in the SDK team.
It’s my pleasure to support IC developers around the world, especially those who want to develop IC dapps in Rust.
Let me know if you have any questions or advices about Rust Canister Development.

11 Likes

I’m really excited for an even better Rust CDK, which has been fantastic to work with already.

I could really use some help or guidance on this thread post: Condvar wait not supported

and this issue: Get return values from `ic_cdk::block_on` · Issue #7 · dfinity/cdk-rs · GitHub

I need to figure out how to perform an asynchronous operation from within a function that is not async. I have a dependency that has an API that requires a synchronous function. From within that synchronous function I need to call asynchronous functions such as to do a cross-canister call. This doesn’t work and I really need to find a workaround.

Really if this issue could get resolved somehow that would do it: Get return values from `ic_cdk::block_on` · Issue #7 · dfinity/cdk-rs · GitHub

I’m afraid I’m going to have to do some crazy engineering to get around this, I would love some help.

3 Likes

See this comment as well: Condvar wait not supported - #3 by lastmjs

I seem to run into a lot of issues with Rust futures when trying to get already-existing Rust libraries to run on the IC. Async code doesn’t just work, and I wish it would.

1 Like

It’s certainly nice to have this option, but I feel the rust projects / workflows still need some love. Unfortunately the default binary coming out of dfx new --type rust + deploy can’t be handled by the live IC out of the box. That’s frustrating for the newcomers, especially since the tutorials and quick start guides are a bit incomplete on these issues.

Rick (from DSCVR) has shared some startup scripts, where they use the size optimization tool, and others already had the flow running from past versions of dfx, but I think it’s a bit disappointing for new-comers to start a new project (with defaults) and be met by an error right out of the gate.

I’d suggest either promoting the “ic-cdk-optimizer” tool to the default install, or updating the docs with clear instructions highlighting that this would be a required step, or work with the team to support larger uploads on the replica, out of the box.

6 Likes

Hi @lastmjs, those two issues are realized by our team. We are considering them together with other upcoming improvements in Rust CDK. We want to provide a consistent develop experience.

2 Likes

Hi @GLdev, thanks for the advice.
When build a Rust type canister, dfx will suggest the user to install ic-cdk-optimizer if it is not installed.

2 Likes

Common feedback is the DID file is not generated, is this possible? I saw a fleek example of them generating it but can’t recall the github repo.

Rick

3 Likes

@lastmjs, one workaround could be to model your effects as data.

That way, you would return a value from the synchronous function that represents the asynchronous operation you want to perform. You would then interpret the value in an asynchronous context to run it.

I think I get what you’re saying but unfortunately I don’t think that will work. I have a very specific API that I must adhere to, boa the JavaScript engine provides me a way to basically hook up an FFI so that I can expose a Rust function as a JavaScript function.

The Rust function must be asynchronous because that is what the API expects. I basically give boa a Rust function and a name, and then from a JavaScript environment I can call that name and have the Rust function execute.

It seems like either boa needs to accept an async function, or the IC needs to allow me to resolve a future from within a synchronous function.

1 Like

@lastmjs I don’t want to derail the thread but I’m interested in this problem and trying to help you out.

If you could provide the link to the specific boa function you’re trying to work with, I’d like to take a look.

Outside of this thread is probably best :slightly_smiling_face:

2 Likes

One more thing on DID generation, when Im browsing a repo, reading the DID lets me know what an application is trying to achieve. So the fact that rust devs need to write their DID means it will be part of the repository, so I would like to keep this as a feature. Next, I believe these DID files + comments will be used to generate documentation for your IC projects. So if Motoko could by default drop the DID to the repo it would be nice.

3 Likes

I appreciate the help! I’ve DMd you as you know.

For anyone else, I’ve created a very small example where you can try to tackle the issue. Just clone the repo and you can try to get it to work: GitHub - lastmjs/test-ic-boa-async

1 Like

I agree, having it checked in is awesome, but generating it would be really nice. I plan to do this with Azle (TypeScript) and I don’t foresee any issues with generating the Candid, so not sure why Rust wouldn’t be able to do it as well.

2 Likes

Wait, I thought more people knew about generating Candid from Rust code. You can see it in this thread: Automatically generate candid from rust sources - #3 by senior.joinu

and I set up auto-generation on my IC Canvas project because I cannot be bothered to hand-code a candid declaration. If you tag your methods, you can use the export_service() pattern to auto-generate: canvas/api.rs at main · krpeacock/canvas · GitHub

We definitely need to document this flow and add it to our Rust examples

5 Likes

I think we want to support both. A developer can choose to start with writing the did file and then generating the types and methods in the host language (similar to protobuf). Or they can start with writing the methods in the host language and then generating the did file.

2 Likes

I agree, I really don’t mind writing my own did file. It really doesn’t add that much work.

Can we lift the binary size limit? I believe it’s 2MB right now. That’s really small. It’s becoming a problem for the users of Sudograph, as once their GraphQL schema reaches a certain size they simply can’t deploy their database anymore.

2 Likes

@lwshang thought you may have an idea… or if a constraint set at lower layers (i suspect it is a constraint at lower layer… but one you can communicate down the stack)

1 Like

It’s good news for Rust developer. thank you. can we add function which generating candid file while cargo-candid build? I think we can add new utility cargo-candid. @diegop @lwshang