Skip to content

Commit

Permalink
Implement gadget-core, webb-gadget, and zk-gadget (skeleton)
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas Braun committed Nov 1, 2023
1 parent 15dfca6 commit b542210
Show file tree
Hide file tree
Showing 21 changed files with 2,421 additions and 2 deletions.
57 changes: 57 additions & 0 deletions .github/workflows/validate_pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Validate PR

on:
pull_request:
branches: [main]

concurrency:
group: rust-validation-${{ github.head_ref }}
cancel-in-progress: true

jobs:
formatting:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2

- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: rustfmt

- name: Check Formatting
run: cargo fmt -- --check

linting:
name: Clippy
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2

- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: clippy

- name: Run Clippy
run: cargo clippy --tests -- -D warnings

testing:
name: Cargo Test
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2

- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable

- name: Run Tests
run: cargo test --features=substrate
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,9 @@ Cargo.lock

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb


# Added by cargo

/target
.idea
24 changes: 24 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[workspace]
members = [
"gadget-core",
"webb-gadget",
"zk-gadget"
]

[workspace.dependencies]
gadget-core = { path = "./gadget-core" }
webb-gadget = { path = "./webb-gadget" }
zk-gadget = { path = "./zk-gadget" }

sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0", default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0", default-features = false }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0", default-features = false }

mpc-net = { git = "https://github.com/webb-tools/zk-SaaS/" }
tokio-rustls = "0.24.1"
tokio = "1.32.0"
bincode2 = "2"
futures-util = "0.3.28"
serde = "1.0.188"
async-trait = "0.1.73"
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
# gadget
A common repository for gadgets
# Gadget

## Design


![](./resources/gadget.png)

The core library is `gadget-core`. The core library allows gadgets to hold standardization of use across different blockchains. The core library is the base of all gadgets, and expects to receive `FinalityNotifications` and `BlockImportNotifications`.

Once such blockchain is a substrate blockchain. This is where `webb-gadget` comes into play. The `webb-gadget` is the `core-gadget` endowed with a connection to a substrate blockchain, a networking layer to communicate with other gadgets, and a `WebbGadgetModule` that has application-specific logic.

Since `webb-gadget` allows varying connections to a substrate blockchain and differing network layers, we can thus design above it the `zk-gadget` and `tss-gadget`. These gadgets are endowed with the same functionalities as the `webb-gadget` but with a (potentially) different blockchain connection, networking layer, and application-specific logic.
28 changes: 28 additions & 0 deletions gadget-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "gadget-core"
version = "0.0.1"
authors = ["Thomas P Braun"]
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
edition = "2021"

[features]
substrate = [
"sp-runtime",
"sc-client-api",
"sp-api",
"futures"
]

[dependencies]
sync_wrapper = "0.1.2"
parking_lot = "0.12.1"
tokio = { workspace = true, features = ["sync", "time", "macros", "rt"] }
hex = "0.4.3"
async-trait = "0.1.73"

sp-runtime = { optional = true, workspace = true, default-features = false }
sc-client-api = { optional = true, workspace = true, default-features = false }
sp-api = { optional = true, workspace = true, default-features = false }
futures = { optional = true, version = "0.3.28" }

[dev-dependencies]
114 changes: 114 additions & 0 deletions gadget-core/src/gadget/manager.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use async_trait::async_trait;
use std::error::Error;
use std::future::Future;
use std::pin::Pin;

pub struct GadgetManager<'a> {
gadget: Pin<Box<dyn Future<Output = Result<(), GadgetError>> + 'a>>,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum GadgetError {
FinalityNotificationStreamEnded,
BlockImportNotificationStreamEnded,
ProtocolMessageStreamEnded,
}

#[async_trait]
pub trait AbstractGadget: Send {
type FinalityNotification: Send;
type BlockImportNotification: Send;
type ProtocolMessage: Send;
type Error: Error;

async fn get_next_finality_notification(&self) -> Option<Self::FinalityNotification>;
async fn get_next_block_import_notification(&self) -> Option<Self::BlockImportNotification>;
async fn get_next_protocol_message(&self) -> Option<Self::ProtocolMessage>;

async fn process_finality_notification(
&self,
notification: Self::FinalityNotification,
) -> Result<(), Self::Error>;
async fn process_block_import_notification(
&self,
notification: Self::BlockImportNotification,
) -> Result<(), Self::Error>;
async fn process_protocol_message(
&self,
message: Self::ProtocolMessage,
) -> Result<(), Self::Error>;

async fn process_error(&self, error: Self::Error);
}

impl<'a> GadgetManager<'a> {
pub fn new<T: AbstractGadget + 'a>(gadget: T) -> Self {
let gadget_task = async move {
let gadget = &gadget;

let finality_notification_task = async move {
loop {
if let Some(notification) = gadget.get_next_finality_notification().await {
if let Err(err) = gadget.process_finality_notification(notification).await {
gadget.process_error(err).await;
}
} else {
return Err(GadgetError::FinalityNotificationStreamEnded);
}
}
};

let block_import_notification_task = async move {
loop {
if let Some(notification) = gadget.get_next_block_import_notification().await {
if let Err(err) =
gadget.process_block_import_notification(notification).await
{
gadget.process_error(err).await;
}
} else {
return Err(GadgetError::BlockImportNotificationStreamEnded);
}
}
};

let protocol_message_task = async move {
loop {
if let Some(message) = gadget.get_next_protocol_message().await {
if let Err(err) = gadget.process_protocol_message(message).await {
gadget.process_error(err).await;
}
} else {
return Err(GadgetError::ProtocolMessageStreamEnded);
}
}
};

tokio::select! {
res0 = finality_notification_task => res0,
res1 = block_import_notification_task => res1,
res2 = protocol_message_task => res2
}
};

Self {
gadget: Box::pin(gadget_task),
}
}
}

impl Future for GadgetManager<'_> {
type Output = Result<(), GadgetError>;
fn poll(
mut self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
self.gadget.as_mut().poll(cx)
}
}

impl<'a, T: AbstractGadget + 'a> From<T> for GadgetManager<'a> {
fn from(gadget: T) -> Self {
Self::new(gadget)
}
}
3 changes: 3 additions & 0 deletions gadget-core/src/gadget/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod manager;
#[cfg(feature = "substrate")]
pub mod substrate;
Loading

0 comments on commit b542210

Please sign in to comment.