Skip to content
This repository has been archived by the owner on Feb 21, 2024. It is now read-only.

Commit

Permalink
feat(acurast-receiver): adds pallet that allows target parachains to …
Browse files Browse the repository at this point in the history
…receive fulfillments from acurast
  • Loading branch information
RomarQ committed Oct 14, 2022
1 parent b5d10d2 commit 9b35410
Show file tree
Hide file tree
Showing 7 changed files with 258 additions and 0 deletions.
45 changes: 45 additions & 0 deletions pallets/acurast-receiver/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
[package]
name = "pallet-acurast-receiver"
authors = ["Papers AG"]
description = "Pallet for defining the receiving logic from acurast parachain."
version = "0.0.1"
license = "Unlicense"
homepage = "https://docs.acurast.com/"
edition = "2021"
publish = false
repository = "https://github.com/acurast/"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [
"derive",
] }

# Benchmarks
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.29", optional = true, default-features = false }

# Substrate
frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.29", default-features = false }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.29", default-features = false }
scale-info = { version = "2.0", default-features = false, features = [ "derive" ] }

[dev-dependencies]
sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.29", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.29", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.29", default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.29", default-features = false }

[features]
default = ["std"]
std = [
"codec/std",
"scale-info/std",
"frame-support/std",
"frame-system/std",
"frame-benchmarking/std",
]

runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"]
try-runtime = ["frame-support/try-runtime"]
13 changes: 13 additions & 0 deletions pallets/acurast-receiver/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Acurast Receiver Pallet

## 🚧🚧🚧 The project is still a work in progress 🚧🚧🚧

## Introduction

The `pallet-acurast-receiver` allows the Acurast parachain to send fulfillments to the requester's parachain.

The Pallet exposes the following extrinsics.

### fulfill

Allows to post the fulfillment of a registered job. The `fulfill` call will fail if the job was not previously assigned to the origin. The fulfillment structure consists of:
13 changes: 13 additions & 0 deletions pallets/acurast-receiver/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//! Benchmarking setup for pallet-template
use super::*;

#[allow(unused)]
use frame_benchmarking::{benchmarks, whitelisted_caller};
use frame_system::RawOrigin;

benchmarks! {
// TODO: add benchmarks

impl_benchmark_test_suite!(crate::Pallet, crate::mock::new_test_ext(), crate::mock::Test);
}
85 changes: 85 additions & 0 deletions pallets/acurast-receiver/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#![cfg_attr(not(feature = "std"), no_std)]

pub use pallet::*;

pub mod traits;

#[cfg(test)]
mod mock;

#[cfg(test)]
mod tests;

#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;

#[frame_support::pallet]
pub mod pallet {
use crate::traits::*;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;

/// Configure the pallet by specifying the parameters and types on which it depends.
#[pallet::config]
pub trait Config: frame_system::Config {
/// Because this pallet emits events, it depends on the runtime's definition of an event.
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
/// The fulfillment payload.
type Payload: Parameter
+ Member
+ MaxEncodedLen
+ Clone
+ Into<frame_support::inherent::Vec<u8>>;
/// Handler to notify the runtime when a new fulfillment is received.
type OnFulfillment: OnFulfillment<Self>;
}

#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);

/// TODO: We may want to add a storage for job identifiers, allowing acurast parachain to send
/// the (job identifer + payload). The requester address would be indexed by job identifier.
// Pallets use events to inform users when important changes are made.
// https://docs.substrate.io/v3/runtime/events-and-errors
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// Event documentation should end with an array that provides descriptive names for event
/// parameters. [fulfillment, who]
FulfillReceived(T::Payload, T::AccountId),
}

// Errors inform users that something went wrong.
#[pallet::error]
pub enum Error<T> {}

#[pallet::call]
impl<T: Config> Pallet<T> {
/// Dispatchable function that notifies the runtime about a fulfilment coming from acurast parachain.
#[pallet::weight(T::DbWeight::get().writes(1))]
pub fn fulfill(origin: OriginFor<T>, payload: T::Payload) -> DispatchResult {
// Check that the extrinsic was signed and get the signer.
// This function will return an error if the extrinsic is not signed.
// https://docs.substrate.io/v3/runtime/origins
let who = ensure_signed(origin.clone())?;

// TODO(Rodrigo): Validate acurast source

// Notify the runtime about the fulfillment.
match T::OnFulfillment::fulfill(&payload.clone().into()) {
Err(err) => Err(err.error),
Ok(_) => {
// TODO: handle ok result

// Emit events
Self::deposit_event(Event::FulfillReceived(payload, who));

// Return a successful DispatchResultWithPostInfo
Ok(())
}
}
}
}
}
80 changes: 80 additions & 0 deletions pallets/acurast-receiver/src/mock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use crate as pallet_acurast_receiver;
use frame_support::{
traits::{ConstU16, ConstU32, ConstU64},
weights::{Pays, PostDispatchInfo},
BoundedVec,
};
use frame_system as system;
use sp_core::H256;
use sp_runtime::{
testing::Header,
traits::{BlakeTwo256, IdentityLookup},
};

type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;

// Configure a mock runtime to test the pallet.
frame_support::construct_runtime!(
pub enum Test where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
AcurastReceiver: pallet_acurast_receiver::{Pallet, Call, Storage, Event<T>},
}
);

impl system::Config for Test {
type BaseCallFilter = frame_support::traits::Everything;
type BlockWeights = ();
type BlockLength = ();
type DbWeight = ();
type Origin = Origin;
type Call = Call;
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = Event;
type BlockHashCount = ConstU64<250>;
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = ();
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = ConstU16<42>;
type OnSetCode = ();
type MaxConsumers = frame_support::traits::ConstU32<16>;
}

pub struct OnAcurastFulfillment;
impl crate::traits::OnFulfillment<Test> for OnAcurastFulfillment {
fn fulfill(
_payload: &[u8],
) -> frame_support::sp_runtime::DispatchResultWithInfo<PostDispatchInfo> {
Ok(PostDispatchInfo {
actual_weight: Some(1),
pays_fee: Pays::No,
})
}
}

impl pallet_acurast_receiver::Config for Test {
type Event = Event;
type Payload = BoundedVec<u8, ConstU32<128>>;
type OnFulfillment = OnAcurastFulfillment;
}

// Build genesis storage according to the mock runtime.
pub fn new_test_ext() -> sp_io::TestExternalities {
system::GenesisConfig::default()
.build_storage::<Test>()
.unwrap()
.into()
}
13 changes: 13 additions & 0 deletions pallets/acurast-receiver/src/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use crate::mock::*;
use frame_support::assert_ok;

#[test]
fn fulfill() {
new_test_ext().execute_with(|| {
// Dispatch fulfill extrinsic.
assert_ok!(AcurastReceiver::fulfill(
Origin::signed(1),
vec![0; 128].try_into().unwrap()
));
});
}
9 changes: 9 additions & 0 deletions pallets/acurast-receiver/src/traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use frame_support::weights::PostDispatchInfo;

use crate::Config;

pub trait OnFulfillment<T: Config> {
fn fulfill(
payload: &[u8],
) -> frame_support::sp_runtime::DispatchResultWithInfo<PostDispatchInfo>;
}

0 comments on commit 9b35410

Please sign in to comment.