Skynet Substrate SDK
Substrate allows developers to create specialized, application-specific blockchains with extreme freedom and flexibility, which can seamlessly connect to Polkadot or Kusama or run independently as solo chains.
Substrate is a highly modular framework and allows for nodes to run “off-chain workers” outside of the rigid time constraints of block production. Our Skynet Substrate SDK allows for the easy creation of Off-chain Worker Pallets that nodes can call directly for off-chain storage.
skynet-substratecontains the code necessary to do the following Skynet behavior in an off-chain worker:
- Download & Upload Skyfiles
- Read & Write from the Registry
- Update Resolver Skylinks
- Repin existing Skylinks
- Set a URL for specific portal interaction
Using Skynet, your Substrate runtime can do things like auto-pin NFT data, publish pieces of application state for access without a centralized API, or communicate cross-chain using a robust, decentralized, off-chain data layer.
Using Substrate, you can also extend the functionality of Skynet! You could build applications that allow groups to control a resolver skylink or even allow users to announce their MySky UserID and let the runtime build and publish social graphs for your application.
In this section, I’ll walk through the behavior of the pallet code. It is an off-chain worker that is triggered after every block. Each header will show a Skynet interaction and break down the behavior of the off-chain worker.
This example node interacts with a “historical height” from Skynet to calculate an “average block height” — a weighted average of the current block height with a the previously calculated average written to Skynet.
This is a useless piece of data, but shows that we can grab data off-chain, modify it with information from our current block, and then persist the result off-chain for use by the runtime or by a browser client reading from Skynet, fully unaware of the blockchain.
Files on Skynet are immutable and referenced by a skylink. Resolver Skylinks are a special data type that can be updated and that point to other skylinks. We do this to know where data has previously been written by the runtime.
Next, we call a helper function that downloads the data that the resolver skylink is pointing to. The data in this example is the “historical block height” of our chain. Starting in L177, we handle what to do if we get an error, but if the resolver skylink exists, we’ll decode the data as a number (L190) and return the value. If not, we’ll return
Then, in L116-126, we use the returned value for calculating a new “average height” — if the skylink doesn’t exist, we’ll seed the value with the current block height, otherwise, we’ll take a weighted average of the current block height and the value we got from Skynet.
Finally, we encode the result as bytes before uploading the value to Skynet.
Starting in L132, we’re creating a skyfile by uploading a collection of bytes to Skynet (L132). The data in this file is our
&average_height_bytes(L133) and we’ll name the file after our
DATA_KEY(L134). In Line 135, we can supply a timeout time, but could supply a number of UploadOptions. The result, if successful, should be a skylink in byte form.
To update a resolver skylink, we need to provide a private key to sign the update, the data key that lets us “tweak” the lookup (and have many resolver skylinks for a single public key), and the skylink we want the resolver skylink to point to. Now, the next time the off-chain worker goes to read the resolver skylink, the Skynet portal will return the value of the skyfile uploaded in the previous section.
The front-end example differs from most substrate projects, in that it doesn’t use polkadot-js (or even skynet-js!). This shows that the client, if aware of a skylink where data is published, only needs to interact with a simple HTTP request to pull data published by our node.
Much more complex interactions are possible with Skynet, including using websockets to subscribe to information updates, but this example’s code simply fetches the skylink in the input box (L59) and then decodes the value from the byte format written by the node.
This example tries to illustrate the major interactions with Skynet in a trivial example. We’re incredibly interested to see what functionality developers can build to extend Skynet’s functionality.
Some possible applications could be:
- 1.Handling multi-signature updates of resolver skylinks
- 2.Cooperative NFT data pinning by nodes or uploads of procedurally generated NFTs for off-chain storage
- 3.Pay-to-View Skylinks by encrypting skyfiles client-side, then selecting trusted nodes to share proxy re-encryption keys with that can be converted to another key for specific users to de-crypt files from Skynet.
If you’re building with Substrate and have any questions or feedback, please reach out! We’d love to hear about what you’re building.
Project supported by web3 foundation grants program