Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Oracle pallet and precompile #853

Merged
merged 44 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
3f7dd29
Merge branch 'main' of github.com:tangle-network/tangle into feat/evm…
1xstj Dec 10, 2024
b7644b8
chore : switch to asset-id evm
1xstj Dec 10, 2024
ce7effe
cleanup
1xstj Dec 11, 2024
cf47bec
bump subxt
1xstj Dec 11, 2024
663f374
clean slate
1xstj Dec 12, 2024
f65f735
Merge branch 'main' of github.com:tangle-network/tangle into feat/evm…
1xstj Dec 12, 2024
5a677c8
use common exports
1xstj Dec 12, 2024
5e53247
use common exports
1xstj Dec 12, 2024
87181bb
wip
1xstj Dec 12, 2024
fadb9f6
wip
1xstj Dec 13, 2024
4d6b596
wip
1xstj Dec 13, 2024
c214aca
fix compile
1xstj Dec 13, 2024
a704da2
cleanup
1xstj Dec 13, 2024
6b51c97
compiling
1xstj Dec 14, 2024
4cc8780
precompiles fixes
1xstj Dec 16, 2024
b1719ee
Merge branch 'main' of github.com:tangle-network/tangle into feat/evm…
1xstj Dec 16, 2024
4a2a2a8
runtimes building
1xstj Dec 16, 2024
35f9394
update mocks
1xstj Dec 16, 2024
42a56fe
cleanup tests
1xstj Dec 16, 2024
145ff94
update js types
1xstj Dec 16, 2024
0c400ac
update subxt
1xstj Dec 16, 2024
c179e4c
cleanup clippy
1xstj Dec 16, 2024
8c58a05
use nightly fmt
1xstj Dec 16, 2024
130955c
use stable fmt
1xstj Dec 16, 2024
59b2375
cleanup clippy
1xstj Dec 16, 2024
f59c794
cleanup tests
1xstj Dec 16, 2024
0e72e74
cleanup tests
1xstj Dec 16, 2024
ec34241
cleanup fmt
1xstj Dec 16, 2024
99c6b08
more tests passing
1xstj Dec 17, 2024
eeb5487
cleanup clippy
1xstj Dec 17, 2024
44500a5
clipyy fixes
1xstj Dec 17, 2024
b2815d3
cleanup clippy
1xstj Dec 17, 2024
e7c6dbe
import oracle pallet
1xstj Dec 17, 2024
ebe8b6a
update traits
1xstj Dec 17, 2024
7adf9e6
update precompile
1xstj Dec 17, 2024
c9754bb
cleanup mock
1xstj Dec 17, 2024
6956d90
Merge branch 'main' of github.com:tangle-network/tangle into oracle-p…
1xstj Dec 18, 2024
fce9401
fix
1xstj Dec 18, 2024
eca9612
updates to tests
1xstj Dec 19, 2024
b265547
Merge branch 'main' of github.com:tangle-network/tangle into oracle-p…
1xstj Dec 20, 2024
4a1008b
update precompile
1xstj Dec 20, 2024
53fb139
update docs
1xstj Dec 20, 2024
8f58e92
update interface
1xstj Dec 20, 2024
5c48492
fix tests
1xstj Dec 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ pallet-services-rpc-runtime-api = { path = "pallets/services/rpc/runtime-api", d
pallet-services-rpc = { path = "pallets/services/rpc" }
pallet-multi-asset-delegation = { path = "pallets/multi-asset-delegation", default-features = false }
pallet-tangle-lst-benchmarking = { path = "pallets/tangle-lst/benchmarking", default-features = false }
pallet-oracle = { path = "pallets/oracle", default-features = false }

k256 = { version = "0.13.3", default-features = false }
p256 = { version = "0.13.2", default-features = false }
Expand Down
2 changes: 0 additions & 2 deletions client/evm-tracing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ ethereum-types = { workspace = true, features = [ "std" ] }
hex = { workspace = true, features = [ "serde" ] }
serde = { workspace = true, features = [ "derive", "std" ] }
serde_json = { workspace = true }

# Moonbeam
evm-tracing-events = { workspace = true, features = [ "std" ] }
rpc-primitives-debug = { workspace = true, features = [ "std" ] }

Expand Down
2 changes: 1 addition & 1 deletion client/rpc/debug/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ hex-literal = { workspace = true }
jsonrpsee = { workspace = true, features = ["macros", "server"] }
tokio = { workspace = true, features = ["sync", "time"] }

# Moonbeam

client-evm-tracing = { workspace = true }
rpc-core-debug = { workspace = true }
rpc-core-types = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion client/rpc/trace/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ substrate-prometheus-endpoint = { workspace = true }
tokio = { workspace = true, features = ["sync", "time"] }
tracing = { workspace = true }

# Moonbeam

client-evm-tracing = { workspace = true }
rpc-core-trace = { workspace = true }
rpc-core-types = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion client/rpc/txpool/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jsonrpsee = { workspace = true, features = ["macros", "server"] }
serde = { workspace = true, features = ["derive"] }
sha3 = { workspace = true }

# Moonbeam

rpc-core-txpool = { workspace = true }
rpc-primitives-txpool = { workspace = true, features = ["std"] }

Expand Down
2 changes: 1 addition & 1 deletion evm-tracer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ license = "GPL-3.0-only"
repository = { workspace = true }

[dependencies]
# Moonbeam

evm-tracing-events = { workspace = true, features = ["evm-tracing"] }
primitives-ext = { workspace = true }

Expand Down
3 changes: 2 additions & 1 deletion pallets/claims/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ use sp_io::{
crypto::{secp256k1_ecdsa_recover, sr25519_verify},
hashing::keccak_256,
};
use sp_runtime::Saturating;
use sp_runtime::{
traits::{CheckedSub, Zero},
transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction},
Expand Down Expand Up @@ -334,7 +335,7 @@ pub mod pallet {
) -> DispatchResult {
ensure_root(origin)?;

<Total<T>>::mutate(|t| *t += value);
<Total<T>>::mutate(|t| *t = t.saturating_add(value));
<Claims<T>>::insert(who.clone(), value);
if let Some(vs) = vesting_schedule {
<Vesting<T>>::insert(who.clone(), vs);
Expand Down
52 changes: 52 additions & 0 deletions pallets/oracle/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[package]
name = "pallet-oracle"
description = "Oracle module that makes off-chain data available on-chain."
repository = "https://github.com/open-web3-stack/open-runtime-module-library/tree/master/oracle"
license = "Apache-2.0"
version = "1.1.0"
authors = ["Laminar Developers <[email protected]>"]
edition = "2021"

[dependencies]
parity-scale-codec = { workspace = true }
scale-info = { workspace = true }
serde = { workspace = true, optional = true }

frame-support = { workspace = true }
frame-system = { workspace = true }
sp-application-crypto = { workspace = true }
sp-io = { workspace = true }
sp-runtime = { workspace = true }
sp-std = { workspace = true }
frame-benchmarking = { workspace = true, optional = true }
tangle-primitives = { workspace = true }

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

[features]
default = [ "std" ]
std = [
"frame-benchmarking?/std",
"frame-support/std",
"frame-system/std",
"tangle-primitives/std",
"parity-scale-codec/std",
"scale-info/std",
"serde",
"sp-application-crypto/std",
"sp-io/std",
"sp-runtime/std",
"sp-std/std",
]
try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
"sp-runtime/try-runtime",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
8 changes: 8 additions & 0 deletions pallets/oracle/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Oracle module

### Overview

This module exposes capabilities for oracle operators to feed external offchain data.
The raw values can be combined to provide an aggregated value.

The data is valid only if feeded by an authorized operator. This module implements `frame_support::traits::InitializeMembers` and `frame_support::traits::ChangeMembers`, to provide a way to manage operators membership. Typically it could be leveraged to `pallet_membership` in FRAME.
17 changes: 17 additions & 0 deletions pallets/oracle/runtime-api/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "pallet-oracle-runtime-api"
version = "1.1.0"
authors = ["Laminar Developers <[email protected]>"]
edition = "2021"
license = "Apache-2.0"
description = "Runtime API module for pallet-oracle."
repository = "https://github.com/open-web3-stack/open-runtime-module-library"

[dependencies]
parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] }
sp-api = { workspace = true }
sp-std = { workspace = true }

[features]
default = [ "std" ]
std = [ "parity-scale-codec/std", "sp-api/std", "sp-std/std" ]
21 changes: 21 additions & 0 deletions pallets/oracle/runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//! Runtime API definition for oracle module.

#![cfg_attr(not(feature = "std"), no_std)]
// The `too_many_arguments` warning originates from `decl_runtime_apis` macro.
#![allow(clippy::too_many_arguments)]
// The `unnecessary_mut_passed` warning originates from `decl_runtime_apis` macro.
#![allow(clippy::unnecessary_mut_passed)]

use parity_scale_codec::Codec;
use sp_std::prelude::Vec;

sp_api::decl_runtime_apis! {
pub trait OracleApi<ProviderId, Key, Value> where
ProviderId: Codec,
Key: Codec,
Value: Codec,
{
fn get_value(provider_id: ProviderId, key: Key) -> Option<Value>;
fn get_all_values(provider_id: ProviderId) -> Vec<(Key, Option<Value>)>;
}
}
56 changes: 56 additions & 0 deletions pallets/oracle/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use super::*;
use crate::Pallet as Oracle;

use frame_benchmarking::v2::*;

use frame_support::assert_ok;
use frame_system::{Pallet as System, RawOrigin};

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

#[benchmark]
fn feed_values(
x: Linear<0, { T::BenchmarkHelper::get_currency_id_value_pairs().len() as u32 }>,
) {
// Register the caller
let caller: T::AccountId = whitelisted_caller();
T::Members::add(&caller);

let values = T::BenchmarkHelper::get_currency_id_value_pairs()[..x as usize]
.to_vec()
.try_into()
.expect("Must succeed since at worst the length remained the same.");

#[extrinsic_call]
_(RawOrigin::Signed(caller.clone()), values);

assert!(HasDispatched::<T, I>::get().contains(&caller));
}

#[benchmark]
fn on_finalize() {
// Register the caller
let caller: T::AccountId = whitelisted_caller();
T::Members::add(&caller);

// Feed some values before running `on_finalize` hook
System::<T>::set_block_number(1u32.into());
let values = T::BenchmarkHelper::get_currency_id_value_pairs();
assert_ok!(Oracle::<T, I>::feed_values(RawOrigin::Signed(caller).into(), values));

#[block]
{
Oracle::<T, I>::on_finalize(System::<T>::block_number());
}

assert!(!HasDispatched::<T, I>::exists());
}

impl_benchmark_test_suite! {
Oracle,
crate::mock::new_test_ext(),
crate::mock::Test,
}
}
44 changes: 44 additions & 0 deletions pallets/oracle/src/default_combine_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use crate::{Config, MomentOf, TimestampedValueOf};
use frame_support::traits::{Get, Time};
use sp_runtime::traits::Saturating;
use sp_std::{marker, prelude::*};
use tangle_primitives::CombineData;

/// Sort by value and returns median timestamped value.
/// Returns prev_value if not enough valid values.
pub struct DefaultCombineData<T, MinimumCount, ExpiresIn, I = ()>(
marker::PhantomData<(T, I, MinimumCount, ExpiresIn)>,
);

impl<T, I, MinimumCount, ExpiresIn>
CombineData<<T as Config<I>>::OracleKey, TimestampedValueOf<T, I>>
for DefaultCombineData<T, MinimumCount, ExpiresIn, I>
where
T: Config<I>,
I: 'static,
MinimumCount: Get<u32>,
ExpiresIn: Get<MomentOf<T, I>>,
{
fn combine_data(
_key: &<T as Config<I>>::OracleKey,
mut values: Vec<TimestampedValueOf<T, I>>,
prev_value: Option<TimestampedValueOf<T, I>>,
) -> Option<TimestampedValueOf<T, I>> {
let expires_in = ExpiresIn::get();
let now = T::Time::now();

values.retain(|x| x.timestamp.saturating_add(expires_in) > now);

let count = values.len() as u32;
let minimum_count = MinimumCount::get();
if count < minimum_count || count == 0 {
return prev_value;
}

let mid_index = count / 2;
// Won't panic as `values` ensured not empty.
let (_, value, _) =
values.select_nth_unstable_by(mid_index as usize, |a, b| a.value.cmp(&b.value));
Some(value.clone())
}
}
Loading
Loading