Skip to content

Commit

Permalink
Merge pull request #3 from Cyborg-Network/edge-task-upgrade
Browse files Browse the repository at this point in the history
Edge task upgrade
  • Loading branch information
ZCalz authored Oct 8, 2024
2 parents 46a9df2 + f2ee7b1 commit 8322657
Show file tree
Hide file tree
Showing 18 changed files with 4,062 additions and 1,517 deletions.
Binary file not shown.
3,812 changes: 2,296 additions & 1,516 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions container-chains/runtime-templates/simple/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ pallet-cc-authorities-noting = { workspace = true }
runtime-common = { workspace = true }
pallet-worker-registration = { verson = "0.1.0", default-features = false, path = "../../../pallets/worker-registration" }
pallet-faucet = { verson = "1.0.3", default-features = false, path = "../../../pallets/faucet" }
pallet-edge-connect = { verson = "0.1.0", default-features = false, path = "../../../pallets/edge-connect" }
pallet-task-management = { verson = "0.1.0", default-features = false, path = "../../../pallets/task-management" }

# Moonkit
async-backing-primitives = { workspace = true }
Expand Down
17 changes: 16 additions & 1 deletion container-chains/runtime-templates/simple/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ use {

pub use pallet_worker_registration;
pub use pallet_faucet;
pub use pallet_edge_connect;
pub use pallet_task_management;

pub mod xcm_config;

Expand Down Expand Up @@ -221,7 +223,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("container-chain-template"),
impl_name: create_runtime_str!("container-chain-template"),
authoring_version: 1,
spec_version: 701,
spec_version: 704,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
Expand Down Expand Up @@ -665,6 +667,16 @@ impl pallet_faucet::Config for Runtime {
type WeightInfo = pallet_faucet::weights::SubstrateWeight<Runtime>;
}

impl pallet_edge_connect::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = ();
}

impl pallet_task_management::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = ();
}

// implement `CreateSignedTransaction` to allow `create_transaction` of offchain worker for runtime
impl<LocalCall> frame_system::offchain::CreateSignedTransaction<LocalCall> for Runtime
where
Expand Down Expand Up @@ -767,6 +779,9 @@ construct_runtime!(
// Cyborg Core
WorkerRegistration: pallet_worker_registration = 120,

EdgeConnect: pallet_edge_connect = 122,
TaskManagement: pallet_task_management = 123,

// Testing
Faucet: pallet_faucet::{Pallet, Call, Storage, Event<T>} = 200,
}
Expand Down
48 changes: 48 additions & 0 deletions pallets/edge-connect/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
[package]
name = "pallet-edge-connect"
description = "Pallet for managing connected workers"
version = "0.1.0"
authors.workspace = true
repository.workspace = true
edition = "2021"
publish = false

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

[dependencies]
parity-scale-codec = { workspace = true, default-features = false, features = [
"derive",
] }
scale-info = { workspace = true , default-features = false, features = ["derive"] }

# frame deps
frame-benchmarking = { vworkspace = true, optional = true }
frame-support = { workspace = true }
frame-system = { workspace = true }

sp-std = { workspace = true }

[dev-dependencies]
sp-core = { workspace = true }
sp-io = { workspace = true }
sp-runtime = { workspace = true }

[features]
default = ["std"]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
]
std = [
"parity-scale-codec/std",
"frame-benchmarking?/std",
"frame-support/std",
"frame-system/std",
"scale-info/std",
]
try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
]
75 changes: 75 additions & 0 deletions pallets/edge-connect/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//! Benchmarking setup for pallet-template
#![cfg(feature = "runtime-benchmarks")]
use super::*;

#[allow(unused)]
use crate::Pallet as edgeConnectPallet;
use frame_benchmarking::v2::*;
use frame_system::RawOrigin;
use frame_support::sp_runtime::traits::One;
use frame_support::BoundedVec;
use frame_support::sp_runtime::traits::ConstU32;

#[benchmarks]
mod benchmarks {
use super::*;

#[benchmark]
fn register_worker() {
let caller: T::AccountId = whitelisted_caller();

let domain_str = "https://some_api_domain.com";
let domain_vec = domain_str.as_bytes().to_vec();
let domain: BoundedVec<u8, ConstU32<128>> = BoundedVec::try_from(domain_vec).unwrap();

let api_info = WorkerAPI {
ip: None,
domain: Some(domain)
};

let worker = Worker {
id: 0,
owner: caller.clone(),
start_block: One::one(),
status: WorkerStatusType::Inactive,
api: api_info.clone()
};

#[extrinsic_call]
register_worker(RawOrigin::Signed(caller.clone()), api_info.ip, api_info.domain);

assert_eq!(edgeConnectPallet::<T>::get_worker_clusters((caller.clone(),0)), Some(worker));
}

#[benchmark]
fn remove_worker() {
let caller: T::AccountId = whitelisted_caller();

// First, register a worker to ensure there is one to remove
let api_info = WorkerAPI {
ip: Some(Ip { ipv4: Some(125), ipv6: None, port: 123}),
domain: None
};

let worker = Worker {
id: 0,
owner: caller.clone(),
start_block: <frame_system::Pallet<T>>::block_number(),
status: WorkerStatusType::Inactive,
api: api_info.clone()
};

edgeConnectPallet::<T>::register_worker(
RawOrigin::Signed(caller.clone()).into(),
api_info.ip,
api_info.domain,
).unwrap();

#[extrinsic_call]
remove_worker(RawOrigin::Signed(caller.clone()), 0);

assert_eq!(edgeConnectPallet::<T>::get_worker_clusters((caller.clone(), 0)), None);
}

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

pub use pallet::*;

#[cfg(test)]
mod mock;

#[cfg(test)]
mod tests;

pub mod weights;
pub use weights::*;

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

pub mod types;

pub use types::*;

#[frame_support::pallet]
pub mod pallet {
use frame_support::{dispatch::DispatchResultWithPostInfo, pallet_prelude::*};
use frame_system::{WeightInfo, pallet_prelude::*};
use scale_info::prelude::vec::Vec;
use super::*;

/// 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.
/// <https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html>
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;

/// A type representing the weights required by the dispatchables of this pallet.
type WeightInfo: WeightInfo;
}

#[pallet::pallet]
pub struct Pallet<T>(_);

#[pallet::type_value]
pub fn WorkerCountDefault() -> WorkerId {
0
}

/// Keeps track of workerIds per account if any
#[pallet::storage]
#[pallet::getter(fn account_workers)]
pub type AccountWorkers<T: Config> =
StorageMap<_, Twox64Concat, T::AccountId, WorkerId, OptionQuery>;

/// Worker Cluster information
#[pallet::storage]
#[pallet::getter(fn get_worker_clusters)]
pub type WorkerClusters<T: Config> =
StorageMap<_, Twox64Concat, (T::AccountId, WorkerId), Worker<T::AccountId, BlockNumberFor<T>>, OptionQuery>;

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
WorkerRegistered{ creator: T::AccountId },
WorkerRemoved{ creator: T::AccountId, worker_id: WorkerId },
}

/// Pallet Errors
#[pallet::error]
pub enum Error<T> {
WorkerRegisterMissingIpOrDomain,
WorkerExists,
WorkerDoesNotExist,
}

#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}

/// Registers a Worker with either a domain or ip and initialize it with an inactive status.
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
// #[pallet::weight(T::WeightInfo::register_worker())]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))]
pub fn register_worker(
origin: OriginFor<T>,
ip: Option<Ip>,
domain: Option<Domain>,
) -> DispatchResultWithPostInfo {
let creator = ensure_signed(origin)?;

// check ip or domain exists
ensure!(ip.clone().and_then(|ip| ip.ipv4).is_some() || ip.clone().and_then(|ip| ip.ipv6).is_some() || domain.is_some(), Error::<T>::WorkerRegisterMissingIpOrDomain);

let api = WorkerAPI {
ip, domain
};
let worker_keys = AccountWorkers::<T>::get(creator.clone());

match worker_keys {
Some(keys) => {
for id in 0..=keys {
// Get the Worker associated with the creator and worker_id
if let Some(worker) = WorkerClusters::<T>::get((creator.clone(), id)) {
// Check if the API matches and throw an error if it does
ensure!(api != worker.api, Error::<T>::WorkerExists);
}
}
},
None => {}
}

let worker_id: WorkerId = match AccountWorkers::<T>::get(creator.clone()) {
Some(id) => {
AccountWorkers::<T>::insert(creator.clone(), id + 1);
id + 1
},
None => {
AccountWorkers::<T>::insert(creator.clone(), 0);
0
}
};

let worker = Worker {
id: worker_id.clone(),
owner: creator.clone(),
start_block: <frame_system::Pallet<T>>::block_number(),
status: WorkerStatusType::Inactive,
api: api,
};

// update storage
AccountWorkers::<T>::insert(creator.clone(), worker_id.clone());
WorkerClusters::<T>::insert((creator.clone(), worker_id.clone()), worker);

// Emit an event.
Self::deposit_event(Event::WorkerRegistered { creator });

// Return a successful DispatchResultWithPostInfo
Ok(().into())
}

/// Remove Worker from storage
#[pallet::call_index(1)]
// #[pallet::weight(T::WeightInfo::remove_worker())]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))]
pub fn remove_worker(
origin: OriginFor<T>,
worker_id: WorkerId,
) -> DispatchResultWithPostInfo {
let creator = ensure_signed(origin)?;

ensure!(WorkerClusters::<T>::get((creator.clone(), worker_id)) != None,
Error::<T>::WorkerDoesNotExist);

// update storage
WorkerClusters::<T>::remove((creator.clone(), worker_id));

// Emit an event.
Self::deposit_event(Event::WorkerRemoved { creator, worker_id });


// Return a successful DispatchResultWithPostInfo
Ok(().into())
}
}

impl<T: Config> Pallet<T> {
pub fn get_active_workers() -> Option<Vec<((T::AccountId, WorkerId),Worker<T::AccountId, BlockNumberFor<T>>)>> {
let workers = WorkerClusters::<T>::iter()
.filter(|&(_, ref worker)| worker.status == WorkerStatusType::Active)
.collect::<Vec<_>>();

if workers.is_empty() {
None
} else {
Some(workers)
}
}
}
}
Loading

0 comments on commit 8322657

Please sign in to comment.