Skip to content

Commit

Permalink
Add sov-modules to monorepo
Browse files Browse the repository at this point in the history
  • Loading branch information
bkolad committed Feb 6, 2023
1 parent 789fe9d commit 4bc11e2
Show file tree
Hide file tree
Showing 33 changed files with 1,006 additions and 7 deletions.
24 changes: 17 additions & 7 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,22 @@ env:

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Build
run: cargo +stable build --verbose
- name: Run tests
run: cargo +stable test --verbose
- uses: actions/checkout@v2
- name: Install latest nightly
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
override: true
components: rustc

- name: Run cargo build
uses: actions-rs/cargo@v1
with:
command: build

- name: Run cargo test
uses: actions-rs/cargo@v1
with:
command: test
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ resolver = "2"
members = [
"sdk",
"jmt",
"sov-modules/sov-modules-api",
"sov-modules/sov-modules-impl",
"sov-modules/sov-modules-macros",
"sov-modules/sov-state",
]


Expand Down
10 changes: 10 additions & 0 deletions sov-modules/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# sov-module

This is a repository containing crates related to the Sovereign module system:

1. `sov-state`: State management.
2. `sov-modules-api`: Api for building a new Sovereign module.
3. `sov-modules-impl`: Implementation of the standard modules.

It is work in progress. The documentation will be provided once the Api stabilizes.

2 changes: 2 additions & 0 deletions sov-modules/sov-modules-api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
/Cargo.lock
9 changes: 9 additions & 0 deletions sov-modules/sov-modules-api/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "sov-modules-api"
version = "0.1.0"
edition = "2021"


[dependencies]
sov-state = { path = "../sov-state" }
sovereign-sdk = { git = "https://github.com/Sovereign-Labs/sovereign-sdk" }
131 changes: 131 additions & 0 deletions sov-modules/sov-modules-api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#![feature(associated_type_defaults)]
use sov_state::Storage;
use sovereign_sdk::{
serial::{Decode, DecodeBorrowed},
stf::Event,
};
use std::{convert::Infallible, io::Read};

// A unique identifier for each state variable in a module.
#[derive(Debug, PartialEq, Eq)]
pub struct Prefix {
storage_name: String,
module_path: String,
module_name: String,
}

impl Prefix {
pub fn new(module_path: String, module_name: String, storage_name: String) -> Self {
Self {
storage_name,
module_path,
module_name,
}
}
}

impl From<Prefix> for sov_state::Prefix {
fn from(_value: Prefix) -> Self {
todo!()
}
}

// Any kind of error during value decoding.
#[derive(Debug)]
pub struct DecodingError {}

impl From<Infallible> for DecodingError {
fn from(_value: Infallible) -> Self {
unreachable!()
}
}

// Context contains types and functionality common for all modules.
pub trait Context {
type Storage: Storage + Clone;
type Signature: Decode;
type PublicKey: Decode + Eq;

// Sender of the transaction.
fn sender(&self) -> Self::PublicKey;
}

// A type that can't be instantiated.
pub enum NonInstantiable {}

impl<'de> DecodeBorrowed<'de> for NonInstantiable {
type Error = DecodingError;

fn decode_from_slice(_: &'de [u8]) -> Result<Self, Self::Error> {
unreachable!()
}
}

impl Decode for NonInstantiable {
type Error = DecodingError;

fn decode<R: Read>(_: &mut R) -> Result<Self, <Self as Decode>::Error> {
unreachable!()
}
}
// Response type for the `Module::call` method.
#[derive(Default)]
pub struct CallResponse {
// Lists of events emitted by a call to a module.
pub events: Vec<Event>,
}

// Response type for the `Module::query` method. The response is returned by the relevant RPC call.
#[derive(Default)]
pub struct QueryResponse {}

// Every module has to implement this trait.
// All the methods have a default implementation that can't be invoked (because they take `NonInstantiable` parameter).
// This allows developers to override only some of the methods in their implementation and safely ignore the others.

pub trait Module {
// Types and functionality common for all modules:
type Context: Context;

// Types and functionality defined per module:

// Module defined argument to the init method.
type InitMessage: Decode = NonInstantiable;

// Module defined argument to the call method.
type CallMessage: Decode = NonInstantiable;

// Module defined argument to the query method.
type QueryMessage: Decode = NonInstantiable;

// Error type for the call method.
type CallError: Into<DecodingError> = Infallible;

// Error type for the query method.
type QueryError: Into<DecodingError> = Infallible;

// Init is called once per module liftime and can be used to set initial state values in the module.
// It takes a module defined type and a context as parameters.
fn init(
&mut self,
_message: Self::InitMessage,
_context: Self::Context,
) -> Result<CallResponse, Self::CallError> {
unreachable!()
}

// Call allows interaction with the module and invokes state changes.
// It takes a module defined type and a context as parameters.
fn call(
&mut self,
_message: Self::CallMessage,
_context: Self::Context,
) -> Result<CallResponse, Self::CallError> {
unreachable!()
}

// Query allows querying the module's state.
fn query(&self, _message: Self::QueryMessage) -> Result<QueryResponse, Self::QueryError> {
unreachable!()
}
}
2 changes: 2 additions & 0 deletions sov-modules/sov-modules-impl/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
/Cargo.lock
13 changes: 13 additions & 0 deletions sov-modules/sov-modules-impl/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "sov-modules-impl"
version = "0.1.0"
edition = "2021"



[dependencies]
sov-modules-api = { path = "../sov-modules-api" }
sov-modules-macros = { path = "../sov-modules-macros" }
sov-state = { path = "../sov-state" }
sovereign-sdk = { git = "https://github.com/Sovereign-Labs/sovereign-sdk" }

27 changes: 27 additions & 0 deletions sov-modules/sov-modules-impl/src/example/call.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use super::{Bank, Delete, Transfer};

impl<C: sov_modules_api::Context> Bank<C> {
pub(crate) fn do_transfer(
&mut self,
transfer: Transfer<C>,
context: C,
) -> Result<sov_modules_api::CallResponse, <Self as sov_modules_api::Module>::CallError> {
if transfer.from != context.sender() {
todo!()
}

Ok(sov_modules_api::CallResponse::default())
}

pub(crate) fn do_delete(
&self,
delete: Delete<C>,
context: C,
) -> Result<sov_modules_api::CallResponse, <Self as sov_modules_api::Module>::CallError> {
if delete.id != context.sender() {
todo!()
}

Ok(sov_modules_api::CallResponse::default())
}
}
80 changes: 80 additions & 0 deletions sov-modules/sov-modules-impl/src/example/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
mod call;
mod query;

use sov_modules_macros::ModuleInfo;
use sovereign_sdk::serial::{Decode, DecodeBorrowed};

pub struct AccountData {}

#[derive(Debug)]
pub struct CustomError {}

// #[derive(Decode)]
pub struct Transfer<C: sov_modules_api::Context> {
from: C::PublicKey,
_to: C::PublicKey,
_amount: u32,
}

// #[derive(Decode)]
pub struct Delete<C: sov_modules_api::Context> {
id: C::PublicKey,
}

// #[call_msg]
pub enum CallMessage<C: sov_modules_api::Context> {
DoTransfer(Transfer<C>),
DoDeleteAccount(Delete<C>),
}

pub enum CallError {}

impl From<CallError> for sov_modules_api::DecodingError {
fn from(_: CallError) -> Self {
todo!()
}
}

#[derive(ModuleInfo)]
pub struct Bank<C: sov_modules_api::Context> {
#[state]
pub accounts: sov_state::StateMap<C::PublicKey, AccountData, C::Storage>,

#[state]
pub accounts2: sov_state::StateMap<C::PublicKey, AccountData, C::Storage>,
}

impl<C: sov_modules_api::Context> sov_modules_api::Module for Bank<C> {
type CallMessage = CallMessage<C>;
type CallError = CallError;
type Context = C;

fn call(
&mut self,
msg: Self::CallMessage,
context: Self::Context,
) -> Result<sov_modules_api::CallResponse, Self::CallError> {
match msg {
CallMessage::DoTransfer(t) => self.do_transfer(t, context),
CallMessage::DoDeleteAccount(d) => self.do_delete(d, context),
}
}
}

// Generated
impl<'de, C: sov_modules_api::Context> DecodeBorrowed<'de> for CallMessage<C> {
type Error = CustomError;

fn decode_from_slice(_: &'de [u8]) -> Result<Self, Self::Error> {
todo!()
}
}

// Generated
impl<C: sov_modules_api::Context> Decode for CallMessage<C> {
type Error = CustomError;

fn decode<R: std::io::Read>(_: &mut R) -> Result<Self, <Self as Decode>::Error> {
todo!()
}
}
1 change: 1 addition & 0 deletions sov-modules/sov-modules-impl/src/example/query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

50 changes: 50 additions & 0 deletions sov-modules/sov-modules-impl/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use sov_modules_api::Module;

mod example;

pub struct Transaction<C: sov_modules_api::Context> {
pub message: _GenModuleEnumCall<C>,
pub sender: C::PublicKey,
pub signature: C::Signature,
}

// Generated
pub enum _GenModuleEnumCall<C: sov_modules_api::Context> {
_Bank(<example::Bank<C> as Module>::CallMessage),
}

// Generated
pub enum _GenModuleEnumQuery<C: sov_modules_api::Context> {
_Bank(<example::Bank<C> as Module>::QueryMessage),
}

// Generated
impl<C: sov_modules_api::Context> _GenModuleEnumCall<C> {
pub fn dispatch_call(
self,
storage: C::Storage,
context: C,
) -> Result<sov_modules_api::CallResponse, sov_modules_api::DecodingError> {
match self {
_GenModuleEnumCall::_Bank(call_msg) => {
let mut bank = example::Bank::<C>::_new(storage);
Ok(bank.call(call_msg, context)?)
}
}
}
}

// Generated
impl<C: sov_modules_api::Context> _GenModuleEnumQuery<C> {
pub fn dispatch_query(
self,
storage: C::Storage,
) -> Result<sov_modules_api::QueryResponse, sov_modules_api::DecodingError> {
match self {
_GenModuleEnumQuery::_Bank(query_msg) => {
let bank = example::Bank::<C>::_new(storage);
Ok(bank.query(query_msg)?)
}
}
}
}
Loading

0 comments on commit 4bc11e2

Please sign in to comment.