Icpp - looking for additional beta testers to build some C++ Smart Contracts

Hi All,

We have entered a 6 week beta period during which we will build more C++ smart contracts and put things to the test. Target production release is July 17.

We just released version 2.4.0, which supports update calls in addition to the already supported query calls.

You can find a counter canister here:

file: counter.cpp

#include "counter.h"
#include <string>
#include "ic_api.h"

uint64_t counter{0};

void inc() {
  IC_API ic_api(false);
  counter += 1;
}

void read() {
  IC_API ic_api(false);
  ic_api.to_wire(CandidTypeNat64{counter});
}

void write() {
  IC_API ic_api(false);
  ic_api.from_wire(CandidTypeNat64{&counter});
}

// Calling a query function does NOT persist between calls. Try it out...
void inc_query() {
  IC_API ic_api(false);
  counter += 1;
}

file: counter.did

service : {
  "inc": () -> ();
  "read": () -> (nat64) query;
  "write": (nat64) -> ();
  "inc_query": () -> () query;
}

file: counter.h

#pragma once

#include "wasm_symbol.h"

void inc() WASM_SYMBOL_EXPORTED("canister_update inc");
void read() WASM_SYMBOL_EXPORTED("canister_query read");
void write() WASM_SYMBOL_EXPORTED("canister_update write");
void inc_query() WASM_SYMBOL_EXPORTED("canister_query inc_query");

The code is pretty much self explanatory, but for details, see the API Reference.

To get started, you can install icpp-free.

During the beta period, we’re also experimenting with some ideas to use the IC’s unique capabilities for a Freemium style software licensing. It is not there yet though, so please just DM me, and I will ship you a .whl for icpp-pro that you can install and get access to all the good stuff that will make you super productive.

If you do not want to code anything up yourself, but have ideas or suggestions for a demo C++ Smart Contract, please comment in this thread, or just open an issue.

Thank you for all the support and feedback.

7 Likes

Really excited about today’s 2.5.0 release.

After a lot of trial & error, we figured out how to get orthogonal persistence to work for all std containers, like vector, list, deque, map, etc.

Still a lot testing to do, but this is a big enabler for the C++ Smart Contracts we’re building.

You can check out an example here, where we control multiple counters using a CandidTypeVecNat64, which maps onto std::vector<uint64_t>.

The hard part in all of this was to figure out what Orthogonal Persistence actually persists, and we found that only data that is globally managed works. So, we provide a set of functions to store & retrieve data from global storage for all the container types. The helper functions are also provided for std::string, in case you want to persist text between calls.

FYI: Initially we thought that it was sufficient to simply store the container objects on the heap, and point to them from a global pointer, and all would be honky dory for orthogonal persistence to do it’s thing. It turned out that this does not work.
The update calls always work, but then during the next call, doesn’t matter if it is a query call or another update call, we get the error “IC0502: Canister trapped: unknown”.
I understand that this is a runtime error on the IC and usually indicates a problem with memory allocation, out-of-bounds access, or null pointer dereference. Perhaps, we’re guessing here, since the container object on the heap is managing it’s own internal dynamic memory, it is de-allocating it’s internal data storage after the call is done, and then during the next call, we get an error that the canister is no longer good if we’re trying to access memory that is no longer there.

2 Likes

Just added an example how to use orthogonal persistence to store data for an authenticated caller (principal). A very common pattern…

You can find it here.

It requires icpp-free 2.6.0, due to a fix for the std::unordered_map that is used.

Finished the capstone project of the grant :partying_face:.

One goal at the start of the project was to be able to write this Motoko smart contract in C++.

Well…, here it is. It requires icpp-free 2.7.0, which was released today.

Got the dApp with this C++ backend deployed to the IC, and I am ready for the final review with the Grant committee tomorrow :crossed_fingers:

2 Likes

Hey! Is icpp open source? I’m looking for the repo. I’d like to open an issue/start a discussion around conventions for some cdk Wasm metadata so that we can track cdk stats live on the IC.

You can see what I’m suggesting here: cdk wasm public metadata · Issue #410 · dfinity/cdk-rs · GitHub

Happy to discuss elsewhere.

1 Like

Hi @lastmjs ,
It is mostly open source under MIT license, and you can find it here.

I will check out your link, but yes, any issue or initiation of discussion in that repo are highly appreciated.

1 Like

Great, I opened this issue: cdk wasm public metadata · Issue #1 · icppWorld/icpp-free · GitHub

1 Like

@lastmjs ,
I had a look a the different ways this could be done, and I believe the only option in my case is to implement it as a post build step, by modifying the wasm file.

There is capability for custom sections at the LLVM level, but not at the C++ frontend level.

So, I want to use a pure python module to do the injection of the custom sections and am currently looking for the best options.

I assume you plan to use a similar approach for Kybra?

If so, have you settled yet on the python package to use for the wasm file manipulation?

Thanks in advance for your guidance!

Yes we already do this using ic-wasm to perform the manipulation during our build process.

But you should probably wait for dfx extensions and/or use the metadata section of dfx.json, see here: gzip and metadata · Issue #1029 · demergent-labs/azle · GitHub

The metadata section makes adding this functionality relatively trivial. dfx extensions will allow you to create an extension for your cdk and produce the dfx.json automatically. We’re probably a few weeks out from a beta that would allow us to test out dfx extensions.

If you do want to see how we have been doing it with ic-wasm then you can check this out: https://github.com/demergent-labs/kybra/blob/main/kybra/__main__.py#L378

Things are up in the air a bit because we’re waiting on dfx extensions and some other things to make this really smooth.

Great! I will check it out!

I want a solution that runs on Windows natively, so dfx is not an option for now, but I will have a closer look at ic-wasm and how you implemented it.