⚠️ This repository has been archived to reiterate on the value proposition and design goals of the tech. Feel free to fork and make it your own or improve or just to play around with it.
This framework allows for an IC canister to be piggybacked on IoT devices for:
- additional compute off-chain where reasonable or just
- to provide a bridge between the IoT device and the IC.
🚧 No security is done in any part of the project. Still in PoC state.
Release notes and unreleased changes can be found in the CHANGELOG.
- Rust toolchain. You can install it using rustup. To compile the application.
- The dfx tool. To create a local network and deploy the canister.
- Ngrok. To allow your harness node to be accessible on the public internet. You can get started here.
This sample code can be found here.
This is the whole application:
use candid::{Decode, Encode};
use harness_cdk::prelude::*;
#[harness]
fn hello(msg: String) -> String {
format!("Hello, {msg}!")
}
harness_export!();
There is no cli tool yet and none is planned atm. You can use the following script to build your canister, here We run the build script:
chmod +x ./build.sh #This should allow the script to be executable
./build.sh
The next step will be to start our node, in another tab:
cd harness-node
HARNESS_PORT='8080' cargo run
Now we can server our harness node to the public internet using ngrok:
ngrok http 8080
Now that everything is set up, we can start interacting with our system.
-
First we can check the health of our system:
curl http://localhost:8080/hello
-
We can then register our harness node to the canister:
dfx canister call <canister_id> register_device '("http://<ngrok-url>")'
-
Next we need to pull the harness code from the canister for our server to load.
curl --header "Content-Type: application/json" \ --request POST \ --data '{"canister_id":"<canister_id>","program_id":"hello","url":"<icp_replica_url>"}' \ http://localhost:8080/program
-
Finally we can call out canister, which will arbiter the call to the harness node.
dfx canister call <canister_id> hello '("World")'
Below is the diagrammatic representation of the Harness system:
graph TD;
A[Caller from the Internet] <-->|Canister query| B((ICP Canister))
subgraph B[ICP Canister]
E[Static App Binary]
end
B <--> |httpOutcall| C[Harness Node]
subgraph C[Harness Node]
D[Loaded App Binary]
F[IO] <-->|waPC call| D
end
Below is the sequence diagram of the Harness system:
sequenceDiagram
participant C as Harness Node
participant B as ICP Canister
participant E as Static App Binary
participant D as Loaded App Binary
participant A as Caller from the Internet
C ->> B: Query Canister to load Application Binary
B ->> E: Access Static App Binary
B ->> C: Return Application Binary
C ->> D: Load Application Binary
C ->> B: Provide URL of Harness Node
A ->> B: Canister query
B ->> C: httpOutcall to Harness Node
C ->> D: Invoke the Binary(waPC call)
D ->> C: Invocation Result(waPC response)
C ->> B: httpOutcall response
B ->> A: Response to Caller