Skip to content

Commit

Permalink
User operation pack and hash, remove packages bytes and ethereum_types (
Browse files Browse the repository at this point in the history
  • Loading branch information
Vid201 committed Dec 1, 2022
1 parent 5aad276 commit cf95912
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 12 deletions.
3 changes: 1 addition & 2 deletions Cargo.lock

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

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ default-run = "bundler"
[dependencies]
anyhow = "1"
async-trait = "0.1"
bytes = { version = "1", features = ["serde"] }
clap = { version = "4", features = ["derive"] }
dirs = "4.0"
educe = { version = "0.4", features = ["Debug", "Default"] }
ethereum-interfaces = { git = "https://github.com/ledgerwatch/interfaces" }
ethereum-types = { version = "0.14", features = ["codec"] }
ethers = "1.0.0"
expanded-pathbuf = "0.1"
hex = { version = "0.4.3", default-features = false, features = ["std"] }
jsonrpsee = { version = "0.16", features = ["server", "macros"] }
parking_lot = "0.12"
prost = "0.11"
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ run-create-wallet:
cargo-fmt:
cargo fmt --all

cargo-test:
cargo test

fetch-thirdparty:
git submodule update --init
2 changes: 1 addition & 1 deletion src/rpc/eth.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{rpc::eth_api::EthApiServer, types::user_operation::UserOperation};
use async_trait::async_trait;
use ethereum_types::{Address, U64};
use ethers::types::{Address, U64};
use jsonrpsee::{core::RpcResult, tracing::info};

pub struct EthApiServerImpl {
Expand Down
2 changes: 1 addition & 1 deletion src/rpc/eth_api.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use ethereum_types::{Address, U64};
use ethers::types::{Address, U64};
use jsonrpsee::{core::RpcResult, proc_macros::rpc};

use crate::types::user_operation::UserOperation;
Expand Down
169 changes: 165 additions & 4 deletions src/types/user_operation.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use bytes::Bytes;
use ethereum_types::{Address, H512, U256};
use ethers::abi::AbiEncode;
use ethers::prelude::{EthAbiCodec, EthAbiType};
use ethers::types::{Address, Bytes, H256, U256};
use ethers::utils::keccak256;
use serde::{Deserialize, Serialize};
use std::str::FromStr;

pub type UoId = H512;
pub type UserOperationHash = H256;

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, EthAbiCodec, EthAbiType)]
#[serde(rename_all = "camelCase")]
pub struct UserOperation {
pub sender: Address,
Expand All @@ -19,3 +22,161 @@ pub struct UserOperation {
pub paymaster_and_data: Bytes,
pub signature: Bytes,
}

impl UserOperation {
pub fn pack(&self) -> Vec<u8> {
self.clone().encode_hex().into_bytes()
}

pub fn pack_for_signature(&self) -> Vec<u8> {
let mut encoded = String::from("0x");
let packed = hex::encode(
UserOperation {
signature: Bytes::from_str("0x").unwrap(),
..self.clone()
}
.encode(),
);
encoded.push_str(&packed[..packed.len() - 64]);
encoded.into_bytes()
}

pub fn hash(&self, entry_point_address: Address, chain_id: U256) -> UserOperationHash {
H256::from_slice(
keccak256(
[
keccak256(hex::decode(&self.pack_for_signature()[2..]).unwrap()).to_vec(),
entry_point_address.encode(),
chain_id.encode(),
]
.concat(),
)
.as_slice(),
)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn user_operation_pack() {
let user_operations = vec![
UserOperation {
sender: Address::zero(),
nonce: U256::zero(),
init_code: Bytes::default(),
call_data: Bytes::default(),
call_gas_limit: U256::zero(),
verification_gas_limit: U256::from(100000),
pre_verification_gas: U256::from(21000),
max_fee_per_gas: U256::zero(),
max_priority_fee_per_gas: U256::from(1e9 as u64),
paymaster_and_data: Bytes::default(),
signature: Bytes::default(),
},
UserOperation {
sender: "0x663F3ad617193148711d28f5334eE4Ed07016602".parse().unwrap(),
nonce: U256::zero(),
init_code: Bytes::default(),
call_data: Bytes::default(),
call_gas_limit: U256::from(200000),
verification_gas_limit: U256::from(100000),
pre_verification_gas: U256::from(21000),
max_fee_per_gas: U256::from(3000000000 as u64),
max_priority_fee_per_gas: U256::from(1000000000),
paymaster_and_data: Bytes::default(),
signature: Bytes::from_str("0x7cb39607585dee8e297d0d7a669ad8c5e43975220b6773c10a138deadbc8ec864981de4b9b3c735288a217115fb33f8326a61ddabc60a534e3b5536515c70f931c").unwrap(),
},
];
assert_eq!(user_operations[0].pack(), String::from("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000052080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").into_bytes());
assert_eq!(user_operations[1].pack(), String::from("0x000000000000000000000000663f3ad617193148711d28f5334ee4ed070166020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000186a0000000000000000000000000000000000000000000000000000000000000520800000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000417cb39607585dee8e297d0d7a669ad8c5e43975220b6773c10a138deadbc8ec864981de4b9b3c735288a217115fb33f8326a61ddabc60a534e3b5536515c70f931c00000000000000000000000000000000000000000000000000000000000000").into_bytes());
}

#[test]
fn user_operation_pack_for_signature() {
let user_operations = vec![
UserOperation {
sender: Address::zero(),
nonce: U256::zero(),
init_code: Bytes::default(),
call_data: Bytes::default(),
call_gas_limit: U256::zero(),
verification_gas_limit: U256::from(100000),
pre_verification_gas: U256::from(21000),
max_fee_per_gas: U256::zero(),
max_priority_fee_per_gas: U256::from(1e9 as u64),
paymaster_and_data: Bytes::default(),
signature: Bytes::default(),
},
UserOperation {
sender: "0x663F3ad617193148711d28f5334eE4Ed07016602".parse().unwrap(),
nonce: U256::zero(),
init_code: Bytes::default(),
call_data: Bytes::default(),
call_gas_limit: U256::from(200000),
verification_gas_limit: U256::from(100000),
pre_verification_gas: U256::from(21000),
max_fee_per_gas: U256::from(3000000000 as u64),
max_priority_fee_per_gas: U256::from(1000000000),
paymaster_and_data: Bytes::default(),
signature: Bytes::from_str("0x7cb39607585dee8e297d0d7a669ad8c5e43975220b6773c10a138deadbc8ec864981de4b9b3c735288a217115fb33f8326a61ddabc60a534e3b5536515c70f931c").unwrap(),
},
];
assert_eq!(user_operations[0].pack_for_signature(), String::from("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000052080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").into_bytes());
assert_eq!(user_operations[1].pack_for_signature(), String::from("0x000000000000000000000000663f3ad617193148711d28f5334ee4ed070166020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000186a0000000000000000000000000000000000000000000000000000000000000520800000000000000000000000000000000000000000000000000000000b2d05e00000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").into_bytes());
}

#[test]
fn user_operation_hash() {
let user_operations = vec![
UserOperation {
sender: Address::zero(),
nonce: U256::zero(),
init_code: Bytes::default(),
call_data: Bytes::default(),
call_gas_limit: U256::zero(),
verification_gas_limit: U256::from(100000),
pre_verification_gas: U256::from(21000),
max_fee_per_gas: U256::zero(),
max_priority_fee_per_gas: U256::from(1e9 as u64),
paymaster_and_data: Bytes::default(),
signature: Bytes::default(),
},
UserOperation {
sender: "0x663F3ad617193148711d28f5334eE4Ed07016602".parse().unwrap(),
nonce: U256::zero(),
init_code: Bytes::default(),
call_data: Bytes::default(),
call_gas_limit: U256::from(200000),
verification_gas_limit: U256::from(100000),
pre_verification_gas: U256::from(21000),
max_fee_per_gas: U256::from(3000000000 as u64),
max_priority_fee_per_gas: U256::from(1000000000),
paymaster_and_data: Bytes::default(),
signature: Bytes::from_str("0x7cb39607585dee8e297d0d7a669ad8c5e43975220b6773c10a138deadbc8ec864981de4b9b3c735288a217115fb33f8326a61ddabc60a534e3b5536515c70f931c").unwrap(),
},
];
assert_eq!(
user_operations[0].hash(
"0x2DF1592238420ecFe7f2431360e224707e77fA0E"
.parse()
.unwrap(),
U256::from(1)
),
H256::from_str("0x42e145138104ec4124367ea3f7994833071b2011927290f6844d593e05011279")
.unwrap()
);
assert_eq!(
user_operations[1].hash(
"0x2DF1592238420ecFe7f2431360e224707e77fA0E"
.parse()
.unwrap(),
U256::from(1)
),
H256::from_str("0x583c8fcba470fd9da514f9482ccd31c299b0161a36b365aab353a6bfebaa0bb2")
.unwrap()
);
}
}
4 changes: 2 additions & 2 deletions src/uopool/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
types::user_operation::{UoId, UserOperation},
types::user_operation::{UserOperation, UserOperationHash},
uopool::{server::server::uo_pool_server::UoPoolServer, services::UoPoolService},
};
use anyhow::Result;
Expand All @@ -15,7 +15,7 @@ pub mod services;
#[derive(Educe)]
#[educe(Debug)]
pub struct UserOperationPool {
pub pool: Arc<RwLock<HashMap<UoId, UserOperation>>>,
pub pool: Arc<RwLock<HashMap<UserOperationHash, UserOperation>>>,
}

impl UserOperationPool {
Expand Down

0 comments on commit cf95912

Please sign in to comment.