OpenChat: A Truly Decentralized Alternative to WhatsApp

OpenChat
https://twitter.com/OpenChat

OpenChat: A Truly Decentralized Alternative to WhatsApp

1 Like

How thousands of canisters were created during this weekend?

  • Is it dfx canister create command?
  • Is it canisters created programmatically using Actor interface?
2 Likes

I’m guessing they were created programmatically, as AFAIK OpenChat v2 creates a new canister per user.

If so - it is very interesting to see how they managed to upgrade code in child canisters…

Anyone from Openchat team - can you comment this technical question?

Also it is very interesting - how those canisters will be monitored (in terms of memory or cycles)

2 Likes

@hpeebles are you able to share anything?

1 Like

Hey! I’m one of the OpenChat devs (there are 3 of us).

Each time a new user registers an account, an update command is sent to our ‘user_index’ canister.

That canister creates the user a new canister, installs the latest version of the user canister wasm, and initialises it, passing in the new user’s principal in the init args.

To upgrade the user canisters, we push the new canister wasm to the user_index canister, which then upgrades each of the user canisters using ‘heartbeat’.

We also have a group_index canister which works in the same way but for groups.

10 Likes

To upgrade the user canisters, we push the new canister wasm to the user_index canister, which then upgrades each of the user canisters using ‘heartbeat’.

Interesting! Why even bother with heartbeat? Why not upgrade all of the user canisters in one shot in the same method that stores the new canister wasm?

1 Like

To upgrade the user canisters, we push the new canister wasm to the user_index canister

Is it something like this?

  1. Make an update call to user_index canister to pass (upload) wasm file of the child canister.
  2. I guess wasm file is stored in Buffer stable variable as raw byte array?

Also - how did you managed to create separate wasm file for child canister?

We pull 5 canisters from the queue and upgrade them on each heartbeat.

As we grow we will potentially have 10s or even 100s of thousands of canisters, so we can’t kick them all off at the same time as that would cause the system to become overloaded and unresponsive, so instead we opted for gradual rolling upgrades.

@alexeychirkov yes exactly, we call the ‘upgrade_user_canister_wasm’ method on our user_index canister. This canister then holds that new wasm in a normal Rust struct. But if the user_index gets upgraded that struct will get serialized to stable memory and then deserialized back into the struct so that it can be used again after the upgrade has completed.

This is our generate_wasm.sh file -

#!/bin/sh

echo Building package $1
cargo build --target wasm32-unknown-unknown --release --package $1

echo Optimising wasm
wasm-opt target/wasm32-unknown-unknown/release/$1.wasm --strip-debug -Oz -o target/wasm32-unknown-unknown/release/$1-opt.wasm

This creates the wasm, we then have another executable which calls into the user_index passing in that wasm as an arg. You can’t pass in wasm files as arguments using dfx (or at least, you couldn’t in the past when we were trying).

5 Likes

Mind sharing the script that passes the wasm as an arg? :slight_smile:

1 Like

We run a Rust program to install / upgrade canisters.

Good timing though… we’ve just this second made the OpenStorage repo public!

This is the system we use to store files sent in OpenChat and we install / upgrade canisters using essentially the same technique here as in OpenChat.

See here - open-storage/utils.rs at main · open-ic/open-storage · GitHub

7 Likes