forked from moondance-labs/tanssi
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
1,240 additions
and
6 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
[package] | ||
name = "pallet-status-aggregator" | ||
description = "Pallet for determining worker status aggregated from oracle feed" | ||
version = "0.1.0" | ||
edition = "2021" | ||
publish = false | ||
|
||
[package.metadata.docs.rs] | ||
targets = ["x86_64-unknown-linux-gnu"] | ||
|
||
[dependencies] | ||
codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ | ||
"derive", | ||
] } | ||
scale-info = { version = "2.11.1", default-features = false, features = [ | ||
"derive", | ||
] } | ||
|
||
log = { workspace = true } | ||
orml-traits = { workspace = true } | ||
orml-oracle = { workspace = true } | ||
pallet-edge-connect = { workspace = true } | ||
cyborg-primitives = { workspace = true } | ||
pallet-timestamp = { workspace = true } | ||
|
||
# frame deps | ||
frame-benchmarking = { workspace = true, default-features = false, optional = true } | ||
frame-support = { workspace = true, default-features = false } | ||
frame-system = { workspace = true, default-features = false } | ||
|
||
sp-std = { workspace = true, default-features = false } | ||
|
||
[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 = [ | ||
"codec/std", | ||
"orml-traits/std", | ||
"frame-benchmarking?/std", | ||
"frame-support/std", | ||
"frame-system/std", | ||
"scale-info/std", | ||
] | ||
try-runtime = [ | ||
"frame-support/try-runtime", | ||
"frame-system/try-runtime", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Status Feed Aggregator | ||
|
||
This pallet serves as a support pallet to the oracle. It processes feed data utilizing the `T::OnNewData` trait from the oracle pallet onto this pallet. The pallet keeps aggregated data and entries up to a block interval defined by `MaxBlockRangePeriod` in the pallet config. | ||
|
||
## Usage Overview | ||
|
||
First an oracle data feeder must be register onto the `OracleMembership` pallet to gain `Oracle` feeder access. Afterwards, the feeder can call the `feed_value()` extrinsic on the `Oracle` pallet. | ||
|
||
The `feed_value()` extrinsic takes in a value type of `BoundedVec<(T::OracleKey, T::OracleValue), T::MaxFeedValues> | ||
|
||
- `T::MaxFeedValues` limits how many values a feeder can enter in each entry | ||
- `T::OracleKey`: identifies the specific worker to enter information for | ||
- `T::OracleValue`: represents any data we assign to the worker which will be processesed by this aggregator pallet | ||
|
||
From here, the status feed aggregator handles all the heavy lifting to process data for each worker based on the values entered. | ||
|
||
## Pallet Logic | ||
|
||
Data first arrives into this pallet from the `T::OnNewData` trait implementation. It checks whether an oracle feeder provided information for a specfic worker yet via `SubmittedPerPeriod`. If not, `WorkerStatusEntriesPerPeriod` updates by pushing this data along with the current block number onto a bounded vector for a given worker. | ||
|
||
After each `MaxBlockRangePeriod` interval, the `on_finalize()` hook calculates all data in `WorkerStatusEntriesPerPeriod` via `derive_status_percentages_for_period()`. Afterwards, storage resets for `SubmittedPerPeriod`, `WorkerStatusEntriesPerPeriod`, and `LastClearedBlock` updates. | ||
|
||
The results of each calulation per period can be accessed from `ResultingWorkerStatusPercentages` and `ResultingWorkerStatus`. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
#![cfg(feature = "runtime-benchmarks")] // Ensures this code is only compiled when benchmarking is enabled | ||
|
||
use super::*; | ||
pub use cyborg_primitives::{oracle::ProcessStatus, worker::WorkerId}; | ||
use frame_benchmarking::v2::*; | ||
|
||
#[benchmarks] | ||
mod benchmarks { | ||
use super::*; | ||
|
||
#[benchmark] | ||
fn derive_status_percentages_for_period() { | ||
// Constant defining the maximum number of feed values to generate. | ||
const MAX_FEED_VALUES: u32 = 12; | ||
let max_limit = MAX_FEED_VALUES - 2; | ||
|
||
// Loop to generate pseudo-random account IDs and worker IDs | ||
// and simulate inserting data into the system for benchmarking. | ||
for seed in 0..max_limit { | ||
// Generate a pseudo-random account ID using the `account` helper function | ||
let account_id: T::AccountId = account("benchmark_account", 0, seed); | ||
// Generate a pseudo-random worker ID | ||
let worker_id: WorkerId = (seed as u64) * 12345; | ||
// Create a ProcessStatus struct with random online/available status | ||
let process_status = ProcessStatus { | ||
online: seed % 2 == 0, | ||
available: seed % 3 == 0, | ||
}; | ||
|
||
// Call the `on_new_data` function of the pallet with generated data | ||
Pallet::<T>::on_new_data( | ||
&account_id.clone(), | ||
&(account_id.clone(), worker_id), | ||
&process_status, | ||
); | ||
} | ||
|
||
// Benchmark block to measure performance of `derive_status_percentages_for_period`. | ||
#[block] | ||
{ | ||
Pallet::<T>::benchmark_derive_status_percentages_for_period(); | ||
} | ||
|
||
// Set up a test account and worker ID for validation after data insertion | ||
let test_account_id: T::AccountId = account("benchmark_account", 0, 1); | ||
let test_worker_id: WorkerId = (1 as u64) * 12345; | ||
|
||
// Assert that WorkerStatusPercentage for the test account and worker ID exists in the | ||
// ResultingWorkerStatusPercentages storage. | ||
assert!( | ||
ResultingWorkerStatusPercentages::<T>::contains_key(( | ||
test_account_id.clone(), | ||
test_worker_id | ||
)), | ||
"WorkerStatusPercentage not found in storage" | ||
); | ||
|
||
// Assert that WorkerStatus for the test account and worker ID exists in the | ||
// ResultingWorkerStatus storage. | ||
assert!( | ||
ResultingWorkerStatus::<T>::contains_key((test_account_id.clone(), test_worker_id)), | ||
"WorkerStatus not found in storage" | ||
); | ||
} | ||
|
||
#[benchmark] | ||
fn on_new_data() { | ||
// Constant defining the max number of feed values | ||
const MAX_FEED_VALUES: u32 = 12; | ||
|
||
// Benchmark block to measure performance of `on_new_data`. | ||
#[block] | ||
{ | ||
let max_limit = MAX_FEED_VALUES - 2; | ||
|
||
// Loop to generate and insert mock data for benchmarking | ||
for seed in 0..max_limit { | ||
// Generate a pseudo-random account ID using the `account` helper function | ||
let account_id: T::AccountId = account("benchmark_account", 0, seed); | ||
// Generate a pseudo-random worker ID | ||
let worker_id: WorkerId = (seed as u64) * 12345; | ||
// Create a ProcessStatus struct with random online/available status | ||
let process_status = ProcessStatus { | ||
online: seed % 2 == 0, | ||
available: seed % 3 == 0, | ||
}; | ||
|
||
// Call the `on_new_data` function of the pallet with generated data | ||
Pallet::<T>::on_new_data( | ||
&account_id.clone(), | ||
&(account_id.clone(), worker_id), | ||
&process_status, | ||
); | ||
} | ||
} | ||
|
||
// Set up a test account and worker ID for validation after data insertion | ||
let test_account_id: T::AccountId = account("benchmark_account", 0, 1); | ||
let test_worker_id: WorkerId = (1 as u64) * 12345; | ||
|
||
// Assert that submission exists for the given account and worker ID in SubmittedPerPeriod | ||
assert!( | ||
SubmittedPerPeriod::<T>::get(( | ||
test_account_id.clone(), | ||
(test_account_id.clone(), test_worker_id) | ||
)), | ||
"Submission not found" | ||
); | ||
|
||
// Assert that key exists in WorkerStatusEntriesPerPeriod for the test account and worker ID | ||
assert!( | ||
WorkerStatusEntriesPerPeriod::<T>::contains_key((test_account_id.clone(), test_worker_id)), | ||
"Entry key does not exists in WorkerStatusEntriesPerPeriod" | ||
); | ||
} | ||
|
||
// Defines the benchmark test suite, linking it to the pallet and mock runtime | ||
impl_benchmark_test_suite!( | ||
Pallet, | ||
crate::benchmarking::test::new_test_ext(), | ||
crate::mock::Test, | ||
); | ||
} |
Oops, something went wrong.