This repository has been archived by the owner on Sep 13, 2022. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(service):add keccak256,verify in util service (#242)
* add keccak256,verify in util service, * fix pr review, add service err return, add test_verify * fix ci check * fix ci test sync because of ci machine performance * modify e2e test, fix timeout bug
- Loading branch information
Showing
8 changed files
with
335 additions
and
29 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
[package] | ||
name = "util" | ||
version = "0.1.0-alpha.0" | ||
authors = ["Muta Dev <muta@nervos.org>"] | ||
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" } | ||
hasher = { version="0.1", features = ["hash-keccak"] } | ||
serde = { version = "1.0", features = ["derive"] } | ||
serde_json = "1.0" | ||
rlp = "0.4" | ||
bytes = "0.5" | ||
derive_more = "0.15" | ||
byteorder = "1.3" | ||
common-crypto = { path = "../../common/crypto" } | ||
hex = "0.4" | ||
rand = "0.7" | ||
|
||
[dev-dependencies] | ||
cita_trie = "2.0" | ||
async-trait = "0.1" | ||
framework = { path = "../../framework" } |
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,81 @@ | ||
use bytes::Bytes; | ||
use hasher::{Hasher, HasherKeccak}; | ||
|
||
use binding_macro::{cycles, service}; | ||
use common_crypto::{Crypto, Secp256k1}; | ||
use protocol::traits::{ExecutorParams, ServiceResponse, ServiceSDK}; | ||
use protocol::types::{Hash, ServiceContext}; | ||
|
||
use crate::types::{KeccakPayload, KeccakResponse, SigVerifyPayload, SigVerifyResponse}; | ||
|
||
#[cfg(test)] | ||
mod tests; | ||
pub mod types; | ||
|
||
pub struct UtilService<SDK> { | ||
_sdk: SDK, | ||
} | ||
|
||
#[service] | ||
impl<SDK: ServiceSDK> UtilService<SDK> { | ||
pub fn new(_sdk: SDK) -> Self { | ||
Self { _sdk } | ||
} | ||
|
||
#[cycles(100_00)] | ||
#[read] | ||
fn keccak256( | ||
&self, | ||
ctx: ServiceContext, | ||
payload: KeccakPayload, | ||
) -> ServiceResponse<KeccakResponse> { | ||
let keccak = HasherKeccak::new(); | ||
let data = hex::decode(payload.hex_str.as_string_trim0x()); | ||
if data.is_err() { | ||
return ServiceResponse::<KeccakResponse>::from_error(107, "data not valid".to_owned()); | ||
} | ||
|
||
let hash_res = keccak.digest(data.unwrap().as_slice()); | ||
let response = KeccakResponse { | ||
result: Hash::from_bytes(Bytes::from(hash_res)).unwrap(), | ||
}; | ||
ServiceResponse::<KeccakResponse>::from_succeed(response) | ||
} | ||
|
||
#[cycles(100_00)] | ||
#[read] | ||
fn verify( | ||
&self, | ||
ctx: ServiceContext, | ||
payload: SigVerifyPayload, | ||
) -> ServiceResponse<SigVerifyResponse> { | ||
let data_sig = hex::decode(payload.sig.as_string_trim0x()); | ||
if data_sig.is_err() { | ||
return ServiceResponse::<SigVerifyResponse>::from_error( | ||
108, | ||
"signature not valid".to_owned(), | ||
); | ||
}; | ||
|
||
let data_pk = hex::decode(payload.pub_key.as_string_trim0x()); | ||
if data_pk.is_err() { | ||
return ServiceResponse::<SigVerifyResponse>::from_error( | ||
109, | ||
"public key not valid".to_owned(), | ||
); | ||
}; | ||
|
||
let data_hash = payload.hash.as_bytes(); | ||
|
||
let response = SigVerifyResponse { | ||
is_ok: Secp256k1::verify_signature( | ||
data_hash.as_ref(), | ||
data_sig.unwrap().as_slice(), | ||
data_pk.unwrap().as_slice(), | ||
) | ||
.is_ok(), | ||
}; | ||
|
||
ServiceResponse::<SigVerifyResponse>::from_succeed(response) | ||
} | ||
} |
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,183 @@ | ||
use std::cell::RefCell; | ||
use std::rc::Rc; | ||
use std::sync::Arc; | ||
|
||
use cita_trie::MemoryDB; | ||
use rand::rngs::OsRng; | ||
|
||
use async_trait::async_trait; | ||
use common_crypto::{ | ||
Crypto, PrivateKey, PublicKey, Secp256k1, Secp256k1PrivateKey, Signature, ToPublicKey, | ||
}; | ||
use framework::binding::sdk::{DefalutServiceSDK, DefaultChainQuerier}; | ||
use framework::binding::state::{GeneralServiceState, MPTTrie}; | ||
use protocol::traits::{NoopDispatcher, Storage}; | ||
use protocol::types::{ | ||
Address, Block, Hash, Hex, Proof, Receipt, ServiceContext, ServiceContextParams, | ||
SignedTransaction, | ||
}; | ||
use protocol::{types::Bytes, ProtocolResult}; | ||
|
||
use crate::types::{KeccakPayload, SigVerifyPayload}; | ||
use crate::UtilService; | ||
|
||
#[test] | ||
fn test_hash() { | ||
let cycles_limit = 1024 * 1024 * 1024; // 1073741824 | ||
let caller = Address::from_hex("0x755cdba6ae4f479f7164792b318b2a06c759833b").unwrap(); | ||
let context = mock_context(cycles_limit, caller); | ||
|
||
let service = new_util_service(); | ||
|
||
let res = service | ||
.keccak256(context, KeccakPayload { | ||
hex_str: Hex::from_string("0x1234".to_string()).unwrap(), | ||
}) | ||
.succeed_data; | ||
|
||
assert_eq!( | ||
res.result.as_hex(), | ||
"0x56570de287d73cd1cb6092bb8fdee6173974955fdef345ae579ee9f475ea7432".to_string() | ||
) | ||
} | ||
|
||
#[test] | ||
fn test_verify() { | ||
let cycles_limit = 1024 * 1024 * 1024; // 1073741824 | ||
let caller = Address::from_hex("0x755cdba6ae4f479f7164792b318b2a06c759833b").unwrap(); | ||
let context = mock_context(cycles_limit, caller); | ||
|
||
let service = new_util_service(); | ||
|
||
let priv_key = Secp256k1PrivateKey::generate(&mut OsRng); | ||
let pub_key = priv_key.pub_key(); | ||
|
||
let mut input_pk: String = "0x".to_string(); | ||
input_pk.push_str(hex::encode(pub_key.to_bytes()).as_str()); | ||
|
||
let pub_key_data = Hex::from_string(input_pk).unwrap(); | ||
let hash = Hash::from_hex("0x56570de287d73cd1cb6092bb8fdee6173974955fdef345ae579ee9f475ea7432") | ||
.unwrap(); | ||
|
||
let sig = Secp256k1::sign_message(&hash.as_bytes(), &priv_key.to_bytes()).unwrap(); | ||
let mut input_sig: String = "0x".to_string(); | ||
input_sig.push_str(hex::encode(sig.to_bytes()).as_str()); | ||
let sig_data = Hex::from_string(input_sig).unwrap(); | ||
|
||
println!( | ||
"pubkey: {}\r\nsig: {}", | ||
pub_key_data.as_string(), | ||
sig_data.as_string() | ||
); | ||
|
||
let res = service | ||
.verify(context, SigVerifyPayload { | ||
hash, | ||
sig: sig_data, | ||
pub_key: pub_key_data, | ||
}) | ||
.succeed_data; | ||
|
||
assert_eq!(res.is_ok, true) | ||
} | ||
|
||
fn new_util_service() -> UtilService< | ||
DefalutServiceSDK< | ||
GeneralServiceState<MemoryDB>, | ||
DefaultChainQuerier<MockStorage>, | ||
NoopDispatcher, | ||
>, | ||
> { | ||
let chain_db = DefaultChainQuerier::new(Arc::new(MockStorage {})); | ||
let trie = MPTTrie::new(Arc::new(MemoryDB::new(false))); | ||
let state = GeneralServiceState::new(trie); | ||
|
||
let sdk = DefalutServiceSDK::new( | ||
Rc::new(RefCell::new(state)), | ||
Rc::new(chain_db), | ||
NoopDispatcher {}, | ||
); | ||
|
||
UtilService::new(sdk) | ||
} | ||
|
||
fn mock_context(cycles_limit: u64, caller: Address) -> ServiceContext { | ||
let params = ServiceContextParams { | ||
tx_hash: None, | ||
nonce: None, | ||
cycles_limit, | ||
cycles_price: 1, | ||
cycles_used: Rc::new(RefCell::new(0)), | ||
caller, | ||
height: 1, | ||
timestamp: 0, | ||
service_name: "service_name".to_owned(), | ||
service_method: "service_method".to_owned(), | ||
service_payload: "service_payload".to_owned(), | ||
extra: None, | ||
events: Rc::new(RefCell::new(vec![])), | ||
}; | ||
|
||
ServiceContext::new(params) | ||
} | ||
|
||
struct MockStorage; | ||
|
||
#[async_trait] | ||
impl Storage for MockStorage { | ||
async fn insert_transactions(&self, _: Vec<SignedTransaction>) -> ProtocolResult<()> { | ||
unimplemented!() | ||
} | ||
|
||
async fn insert_block(&self, _: Block) -> ProtocolResult<()> { | ||
unimplemented!() | ||
} | ||
|
||
async fn insert_receipts(&self, _: Vec<Receipt>) -> ProtocolResult<()> { | ||
unimplemented!() | ||
} | ||
|
||
async fn update_latest_proof(&self, _: Proof) -> ProtocolResult<()> { | ||
unimplemented!() | ||
} | ||
|
||
async fn get_transaction_by_hash(&self, _: Hash) -> ProtocolResult<SignedTransaction> { | ||
unimplemented!() | ||
} | ||
|
||
async fn get_transactions(&self, _: Vec<Hash>) -> ProtocolResult<Vec<SignedTransaction>> { | ||
unimplemented!() | ||
} | ||
|
||
async fn get_latest_block(&self) -> ProtocolResult<Block> { | ||
unimplemented!() | ||
} | ||
|
||
async fn get_block_by_height(&self, _: u64) -> ProtocolResult<Block> { | ||
unimplemented!() | ||
} | ||
|
||
async fn get_block_by_hash(&self, _: Hash) -> ProtocolResult<Block> { | ||
unimplemented!() | ||
} | ||
|
||
async fn get_receipt(&self, _: Hash) -> ProtocolResult<Receipt> { | ||
unimplemented!() | ||
} | ||
|
||
async fn get_receipts(&self, _: Vec<Hash>) -> ProtocolResult<Vec<Receipt>> { | ||
unimplemented!() | ||
} | ||
|
||
async fn get_latest_proof(&self) -> ProtocolResult<Proof> { | ||
unimplemented!() | ||
} | ||
|
||
async fn update_overlord_wal(&self, _info: Bytes) -> ProtocolResult<()> { | ||
unimplemented!() | ||
} | ||
|
||
async fn load_overlord_wal(&self) -> ProtocolResult<Bytes> { | ||
unimplemented!() | ||
} | ||
} |
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,24 @@ | ||
use protocol::types::{Hash, Hex}; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
#[derive(Deserialize, Serialize, Clone, Debug)] | ||
pub struct KeccakPayload { | ||
pub hex_str: Hex, | ||
} | ||
|
||
#[derive(Deserialize, Serialize, Clone, Debug, Default)] | ||
pub struct KeccakResponse { | ||
pub result: Hash, | ||
} | ||
|
||
#[derive(Deserialize, Serialize, Clone, Debug)] | ||
pub struct SigVerifyPayload { | ||
pub hash: Hash, | ||
pub sig: Hex, | ||
pub pub_key: Hex, | ||
} | ||
|
||
#[derive(Deserialize, Serialize, Clone, Debug, Default)] | ||
pub struct SigVerifyResponse { | ||
pub is_ok: bool, | ||
} |
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
Oops, something went wrong.