Skip to main content

Substrate Integration

GitHub Repository

The Acurast Receiver Pallet allows a Substrate based chain to integrate the Acurast functionality to be able to securely receive real world data posted by the Acurast Processors.

Introduction

The Acurast Fulfillment Receiver Pallet, in combination with the Acurast P256 crypto package, allows a Substrate (Polkadot SDK) enabled chain to accept direct fulfillments from Acurast Processors.

The Pallet exposes one extrinsic.

fulfill

Allows to post the [Fulfillment] of a job. The fulfillment structure consists of:

  • The ipfs url of the script executed.
  • The payload bytes representing the output of the script.

Substrate Integration

Implement pallet_acurast_fulfillment_receiver::Config for your Runtime and add the Pallet:

frame_support::construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>} = 0,
AcurastFulfillmentReceiver: crate::{Pallet, Call, Event<T>}
}
);

impl pallet_acurast_fulfillment_receiver::Config for Runtime {
type Event = Event;
type OnFulfillment = FulfillmentHandler;
type WeightInfo = ();
}

pub struct FulfillmentHandler;
impl OnFulfillment<Runtime> for FulfillmentHandler {
fn on_fulfillment(
from: <Runtime as frame_system::Config>::AccountId,
fulfillment: pallet_acurast_fulfillment_receiver::Fulfillment,
) -> sp_runtime::DispatchResultWithInfo<frame_support::weights::PostDispatchInfo> {
/// check if origin is a valid Acurast Processor AccountId
if !is_valid(&from) {
return Err(DispatchError::BadOrigin.into());
}
/// if valid, then fulfillment can be used
Ok(().into())
}
}

Provide an implementation of OnFulfillment to handle the received fulfillment. The implementation should check that the fulfillment is from a known Acurast Processor account id.

For example, if the job calling the fulfill extrisic has the following script:

httpGET(
"https://api.binance.com/api/v3/ticker/price?symbol=AAVEBUSD",
{},
(response, _certificate) => {
const price = JSON.parse(response)["price"] * 10 ** 18;
const payload = _STD_.chains.substrate.codec.encodeUnsignedNumber(price, 128);
_STD_.chains.substrate.fulfill(
"<URL_TO_YOUR_SUBSTRATE_NODE>", // replace with your substrate node URL
payload,
{
callIndex: '0x4100', // replace with the call index for the 'fulfill' extrinsic of the pallet-acurast-fulfillment-receiver pallet.
},
(opHash) => {
print("Succeeded: " + opHash)
},
(err) => {
print("Failed fulfill: " + err)
},
)
},
(err) => {
print("Failed get price: " + err)
}
);

The script above will produce a fulfill extrinsic call to the pallet at the specified call index with the payload being the SCALE encoded number representing a price. The following snipped shows how to decode the payload into a number on the receiving side:

pub struct FulfillmentHandler;
impl OnFulfillment<Runtime> for FulfillmentHandler {
fn on_fulfillment(
from: <Runtime as frame_system::Config>::AccountId,
fulfillment: pallet_acurast_fulfillment_receiver::Fulfillment,
) -> sp_runtime::DispatchResultWithInfo<frame_support::weights::PostDispatchInfo> {
/// check if origin is a valid Acurast Processor AccountId
if !is_valid(&from) {
return Err(DispatchError::BadOrigin.into());
}
// parse payload
let price: u128 = codec::decode_from_bytes(fulfillment.payload.into());
// do something with price
Ok(().into())
}
}

P256 crypto

GitHub Repository

This crate provides types that allow to add P256 (a.k.a secp256r1) signature verification support to Substrate (Polkadot SDK) based chains.

Setup

Add the following dependency to your Cargo manifest:

[dependencies]
acurast-p256-crypto = { git = "https://github.com/Acurast/acurast-core.git" }

Integration

Use the acurast_p256_crypto::MultiSignature as your Substrate Signature type:

use acurast_p256_crypto::MultiSignature;

pub type Signature = MultiSignature;
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
...

impl frame_system::Config for Runtime {
type AccountId = AccountId;
...
}