Cover photo

Bringing transparency to DePIN token incentives

A Proof of Concept with IoTeX's W3bstream and WeatherXM for enabling transparent contributor token reward calculations

WeatherXM, Textile, and IoTeX have teamed up to create a joint proof of concept (PoC) that showcases a workflow for enabling transparent contributor token reward calculations built on decentralized infrastructure. At the heart of decentralization is the promise of mechanisms that ensure value creators are fairly rewarded for their contributions.

In the Decentralized Physical Infrastructure Networks (”DePIN”) space, early contributors often invest in hardware and take the time to capture and contribute data to an ecosystem in exchange for token rewards. However, most DePINs are still calculating and distributing token incentive payouts in a centralized, opaque manner, making it difficult for contributors or investors to know if they’re receiving the correct amount of tokens for their contribution. With this PoC, we’ve demonstrated what a more transparent, decentralized, and trustless future could look like for DePINs and their token incentive payouts to their contributors.

Background

WeatherXM has been designing its protocol and ecosystem to lead from a place of transparency, sharing the many intricacies that makeup quality of data (QoD) scores for reward payouts and continually experimenting with decentralized back-end infrastructure to open up access to and collaboration over their data. Their input and feedback have been invaluable to us as we design Basin, a Data Availability (”DA”) and Long-Term Storage (”LTS”) layer, to unlock new data use cases for DePINs. Namely, data is immediately available with the Basin hot cache layer while being replicated to Filecoin for long-term persistence. We’ve also been working closely with the IoTeX team on their new compute protocol W3bstream, which, in turn, supports Risc0’s newly released zkVM. Ultimately, a DA/LTS layer should be modular and part of a DePIN’s middleware stack, so we all collaborated on a proof-of-concept that leveraged all three protocols.

If you want to dive straight into the POC, check out the source code here: https://github.com/machinefi/WeatherXM-IoTeX-Textile-POC

To provide a bit more context, here’s a quick overview of what each protocol does:

  • W3bstream: compute protocol built for DePINs that allows for off-chain, verifiable computing on data (with zero knowledge proofs) and can trigger smart contracts on any blockchain, facilitating the creation of circular token economies.

  • Risc0: a zero-knowledge verifiable general computing platform based on zk-STARKs and the RISC-V microarchitecture.

  • WeatherXM: DePIN network that's powered by community-owned weather stations (devices), purpose-built by WeatherXM for weather data collection and incentivized to share data.

  • Basin: a DA/LTS storage layer that provides hot/cold decentralized storage for large datasets with hot cache + Filecoin…sorta like a “data L2.”

How does it work?

WeatherXM pushes station/device data to Basin on a daily basis. Separately, the network runs a Quality of Data (”QoD”) algorithm that gets incorporated into the token rewarding mechanism. The IoTeX team built on top of the WeatherXM dataset stored on Basin, while also demonstrating how the QoD pipeline could work within a decentralized compute network. Namely, W3sbtream could run the QoD algorithm daily over the WeatherXM data and then also store those results in Basin, along with zk proofs.

You can think of this process in three steps:

  • Ingest: WeatherXM pushes data to a Textile Basin on a daily basis as a Parquet file.

  • Compute: The daily QoD score per station is calculated for the entire network, with a zk proof by W3bstream.

  • Visualizations: Access to the data & reward proofs is provided through a simple dashboard (here).

Data flows from WeatherXM to Basin to W3bstream …and back to Basin for storing W3bstream data, too.

How is it built?

In the POC, the first step in the process is already accounted for without additional effort because WeatherXM is already sending station data to Basin. The second step requires W3bstream to pull data from Basin and run QoD calculations. Luckily, the QoD algorithm is open source and comes ready to go with a Docker setup: here. You can generate the QoD scores with that repo using the following commands, which include the station/device ID and time ranges to generate the QoD scores:

> docker build -t wxm-qod:local .
> docker run \
  -v /datasets:/datasets \
  wxm-qod:local obc_sqc.iface.file_model_inference \
  --device_id <device_id> \ # unique WeatherXM device ID
  --date <date> \ # the QoD score for that day
  --day1 <yesterday> \ # the data at the start time
  --day2 <today> \ # the data at the end time
  --output_file_path results.json

For example, W3bstream nodes could run this QoD algorithm daily to generate the dataset on-machine. The next step is the verifiability component; you must prepare the prover code to compute the average QoD scores with the W3bstream zk engine. A reference example is located in methods.rs (here) that defines how to generate a risc0 proof. The actual implementation looks like this, which risc0-zkvm and those custom methods that define a ZK_ELF, ZK_ID, and ZK_PATH:

use zk_methods::ZK_ELF;
use risc0_zkvm::{
    default_prover,
    serde::{from_slice, to_vec},
    ExecutorEnv, Receipt,
};

// Compare them inside the ZKP
pub fn avg(a: String) -> (Receipt, String) {
    let env = ExecutorEnv::builder()
        .write_slice(&to_vec(&a).unwrap())
        .build()
        .unwrap();

    // Obtain the default prover.
    let prover = default_prover();

    // Produce a receipt by proving the specified ELF binary.
    let receipt = prover.prove(env, ZK_ELF).unwrap();
    println!("{:?}", receipt);

    // Extract journal of receipt (i.e. output c, where c = a + b)
    let c: String = from_slice(&receipt.journal.bytes).expect(
        "Journal output should deserialize into the same types (& order)",
    );
    println!("{}", c);

    (receipt, c)
}

Then, generating the actual proof uses the avg function above (for averaging QoD scores):

use zk::avg;
use zk_methods::ZK_ID;

fn main() {
	// An example of a single WeatherXm device ID, its QoD, 
    // and the proof type as a stored variable / string
    let json_str = "[
        \"{\\\"data\\\":\\\"[{\\\\\\\"device_id\\\\\\\":\\\\\\\"e1f8a900-1dfb-11ed-9972-4f669f2d96bd\\\\\\\",\\\\\\\"qod_score\\\\\\\":0.9644833333333332},\\\"receipt_type\\\":\\\"Stark\\\"}\"
        ]";

    let (receipt, _) = avg(json_str.to_owned());
    // Verify receipt (and error if there's an issue)
    receipt.verify(ZK_ID).expect(
        "code you have proven should successfully verify",
    );
}

How to use it?

Once the prover code (methods.rs) is defined, you can then use the W3bstream network to run proofs over the data by using the W3bstream Sandbox. Start by providing the prover code and where the QoD/proof data is to be written (i.e., to Basin) before submitting the request to the network:

Alternatively, this can be performed programmatically with the IoTeX CLI (ioctl). It’ll run through similar steps and log the results:

{
  "messageID": "c4a2be1c-def3-463f-813a-12efc7e46856",
  "states": [
    {
      "state": "received",
      "time": "2024-03-22T19:05:36.661Z",
      "comment": ""
    },
    {
      "state": "packed",
      "time": "2024-03-22T19:05:40.2937Z",
      "comment": ""
    },
    {
      "state": "dispatched",
      "time": "2024-03-22T19:19:08.268849Z",
      "comment": ""
    },
    {
      "state": "proved",
      "time": "2024-03-22T19:24:53.339793Z",
      "comment": ""
    },
    {
      "state": "outputted",
      "time": "2024-03-22T19:24:57.587218Z",
      "comment": ""
    }
  ]
}

All of the data is made available on Basin, so you can inspect the CID to see what the proof looks like—here’s an example: bafybeigcwwx67s27str46u45grpk7xn3brqe2fqezgogaiycscjs53xhqm

Build open data pipelines

Reach out to Tableland, IoTeX, or WeatherXM if you found this PoC useful! There are so many ways you can build on what this demonstration showed, such as using:

  • WeatherXM’s weather station data in a compute or visualization workflow. Explore data on index.weatherxm.network or use their client API.

  • W3bstream to run verifiable computation over arbitrary data (e.g., DePIN device data) with zk proofs (including to automate your token incentive streams and build contributor trust in your reward calculations).

  • Basin for data availability and storage (e.g, DePIN device data or compute results/proofs).

  • Risc0 to significantly speed up your development, and build a Rust program, whose execution can be proven by zero-knowledge technology.

This post was co-authored by: Textile (Dan Buchholz, @dtbuchholz) & IoTeX (Giuseppe De Luca, @iotex_dev)

Textile Blog & Newsletter logo
Subscribe to Textile Blog & Newsletter and never miss a post.
#iotex#weatherxm#textile#data availability#zk#zero knowledge#weather#web3