Skip to content
This repository has been archived by the owner on Sep 13, 2022. It is now read-only.

Commit

Permalink
feat(service)!: add authorization service for mempool (#320)
Browse files Browse the repository at this point in the history
* feat: add authorization service

* feat: mempool check authorization by service

* add set admin function

* tmp

* feat: verify signature when new authorization

* feat: register multi_signature

* encode json twice

* fix

* refactor executor

* test: update muta sdk version for checking multi sig with mempool changes

* fix unit test

* cargo fmt

* fix decode may panic

* cargo clippy

* change verify signature api

* test(e2e): add multi signature testcase

Co-authored-by: homura <[email protected]>
Co-authored-by: zero.qn <[email protected]>
  • Loading branch information
3 people authored Jun 24, 2020
1 parent f8f16cd commit a3c3433
Show file tree
Hide file tree
Showing 27 changed files with 622 additions and 241 deletions.
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ futures-timer="3.0"

[dev-dependencies]
asset = { path = "built-in-services/asset" }
metadata = { path = "built-in-services/metadata" }
util = { path = "built-in-services/util" }
multi-signature = { path = "built-in-services/multi-signature" }
authorization = { path = "built-in-services/authorization" }
metadata = { path = "built-in-services/metadata"}
util = { path = "built-in-services/util"}
rand = "0.7"
cita_trie = "2.0"
core-network = { path = "./core/network", features = ["diagnostic"] }
Expand All @@ -68,6 +69,7 @@ members = [
"built-in-services/asset",
"built-in-services/metadata",
"built-in-services/multi-signature",
"built-in-services/authorization",

"protocol",
]
Expand Down
2 changes: 1 addition & 1 deletion built-in-services/asset/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rlp = "0.4"
bytes = "0.5"
derive_more = "0.15"
derive_more = "0.99"
byteorder = "1.3"
muta-codec-derive = "0.2"

Expand Down
4 changes: 1 addition & 3 deletions built-in-services/asset/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ pub mod types;

use std::collections::BTreeMap;

use bytes::Bytes;

use binding_macro::{cycles, genesis, service};
use protocol::traits::{ExecutorParams, ServiceResponse, ServiceSDK, StoreMap};
use protocol::types::{Address, Hash, ServiceContext};
use protocol::types::{Address, Bytes, Hash, ServiceContext};

use crate::types::{
ApproveEvent, ApprovePayload, Asset, AssetBalance, CreateAssetPayload, GetAllowancePayload,
Expand Down
25 changes: 25 additions & 0 deletions built-in-services/authorization/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[package]
name = "authorization"
version = "0.1.0"
authors = ["Muta Dev <[email protected]>"]
edition = "2018"
repository = "https://github.com/nervosnetwork/muta"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
binding-macro = { path = "../../binding-macro" }
protocol = { path = "../../protocol", package = "muta-protocol" }

serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rlp = "0.4"
bytes = "0.5"
derive_more = "0.99"
byteorder = "1.3"
muta-codec-derive = "0.2"

[dev-dependencies]
cita_trie = "2.0"
async-trait = "0.1"
framework = { path = "../../framework" }
127 changes: 127 additions & 0 deletions built-in-services/authorization/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
mod types;

use binding_macro::{cycles, genesis, service};
use protocol::traits::{ExecutorParams, ServiceResponse, ServiceSDK, StoreMap};
use protocol::types::{Address, ServiceContext};

use crate::types::{
AddVerifiedItemPayload, InitGenesisPayload, RemoveVerifiedItemPayload, SetAdminPayload,
};

const AUTHORIZATION_ADMIN_KEY: &str = "authotization_admin";
const MULTI_SIG_SERVICE: &str = "multi_signature";
const MULTI_SIG_METHOD: &str = "verify_signature";

pub struct AuthorizationService<SDK> {
sdk: SDK,
verified_map: Box<dyn StoreMap<String, String>>,
}

#[service]
impl<SDK: ServiceSDK> AuthorizationService<SDK> {
pub fn new(mut sdk: SDK) -> Self {
let mut verified_map: Box<dyn StoreMap<String, String>> =
sdk.alloc_or_recover_map("authotization");

verified_map.insert(MULTI_SIG_SERVICE.to_owned(), MULTI_SIG_METHOD.to_owned());

Self { sdk, verified_map }
}

#[genesis]
fn init_genesis(&mut self, payload: InitGenesisPayload) {
let service_names = payload.register_service_names;
let function_names = payload.verified_method_names;
assert!(service_names.len() == function_names.len());

self.sdk
.set_value(AUTHORIZATION_ADMIN_KEY.to_string(), payload.admin);

for item in service_names.into_iter().zip(function_names.into_iter()) {
self.verified_map.insert(item.0, item.1);
}
}

#[cycles(210_00)]
#[read]
fn check_authorization(&self, ctx: ServiceContext, payload: String) -> ServiceResponse<()> {
for (service_name, mathod_name) in self.verified_map.iter() {
let resp = self._do_verify(&ctx, &service_name, &mathod_name, &payload);
if resp.is_error() {
return ServiceResponse::<()>::from_error(
102,
format!(
"verify transaction {:?} error {:?}",
mathod_name, resp.error_message
),
);
}
}

ServiceResponse::from_succeed(())
}

#[cycles(210_00)]
#[write]
fn add_verified_item(
&mut self,
ctx: ServiceContext,
payload: AddVerifiedItemPayload,
) -> ServiceResponse<()> {
if !self._is_admin(&ctx) {
return ServiceResponse::<()>::from_error(103, "Invalid caller".to_owned());
}

self.verified_map
.insert(payload.service_name, payload.method_name);
ServiceResponse::from_succeed(())
}

#[cycles(210_00)]
#[write]
fn remove_verified_item(
&mut self,
ctx: ServiceContext,
payload: RemoveVerifiedItemPayload,
) -> ServiceResponse<()> {
if !self._is_admin(&ctx) {
return ServiceResponse::<()>::from_error(103, "Invalid caller".to_owned());
}

self.verified_map.remove(&payload.service_name);
ServiceResponse::from_succeed(())
}

#[cycles(210_00)]
#[write]
fn set_admin(&mut self, ctx: ServiceContext, payload: SetAdminPayload) -> ServiceResponse<()> {
if !self._is_admin(&ctx) {
return ServiceResponse::<()>::from_error(103, "Invalid caller".to_owned());
}

self.sdk
.set_value(AUTHORIZATION_ADMIN_KEY.to_string(), payload.new_admin);

ServiceResponse::from_succeed(())
}

fn _do_verify(
&self,
ctx: &ServiceContext,
service_name: &str,
method_name: &str,
payload_json: &str,
) -> ServiceResponse<String> {
self.sdk
.read(&ctx, None, service_name, method_name, &payload_json)
}

fn _is_admin(&self, ctx: &ServiceContext) -> bool {
let admin: Address = self
.sdk
.get_value(&AUTHORIZATION_ADMIN_KEY.to_string())
.expect("must have an admin");

ctx.get_caller() == admin
}
}
29 changes: 29 additions & 0 deletions built-in-services/authorization/src/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use muta_codec_derive::RlpFixedCodec;
use serde::{Deserialize, Serialize};

use protocol::fixed_codec::{FixedCodec, FixedCodecError};
use protocol::types::{Address, Bytes};
use protocol::ProtocolResult;

#[derive(RlpFixedCodec, Deserialize, Serialize, Clone, Debug)]
pub struct InitGenesisPayload {
pub admin: Address,
pub register_service_names: Vec<String>,
pub verified_method_names: Vec<String>,
}

#[derive(RlpFixedCodec, Deserialize, Serialize, Clone, Debug)]
pub struct AddVerifiedItemPayload {
pub service_name: String,
pub method_name: String,
}

#[derive(RlpFixedCodec, Deserialize, Serialize, Clone, Debug)]
pub struct RemoveVerifiedItemPayload {
pub service_name: String,
}

#[derive(RlpFixedCodec, Deserialize, Serialize, Clone, Debug)]
pub struct SetAdminPayload {
pub new_admin: Address,
}
Loading

0 comments on commit a3c3433

Please sign in to comment.