Skip to content

Commit

Permalink
integrate postgres into rocksdb-exporter (#14)
Browse files Browse the repository at this point in the history
* let the docker can be build

* abstract evm-exporter setter

* abstract evm-exporter getter

* let the enterprise-web3 all services be compiled

* adding mock postgres setter and getter which can be compiled

* adding pg error
  • Loading branch information
tommady authored Jun 20, 2024
1 parent d4517d2 commit 468e310
Show file tree
Hide file tree
Showing 22 changed files with 531 additions and 269 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[workspace]
resolver = "2"
members = [
"redis-versioned-kv",
"evm-exporter",
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM docker.io/rust:1.70.0-slim AS builder
FROM docker.io/rust:slim-buster AS builder

RUN apt-get update -y && apt-get install -y libssl-dev pkg-config make perl clang
RUN apt-get update -y && apt-get install -y libssl-dev pkg-config make perl clang llvm
ENV OPENSSL_LIB_DIR="/usr/lib/x86_64-linux-gnu"
ENV OPENSSL_INCLUDE_DIR="/usr/include/openssl"
COPY . /enterprise-web3
Expand Down
7 changes: 3 additions & 4 deletions evm-exporter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ edition = "2021"
primitive-types = "0.11.1"
thiserror = "1.0.34"
ethereum-types = { version = "0.13.1", default-features = false, features = ["serialize"] }

redis = { version = "0.21", default-features = false }
sqlx = { version = "0.7", default-features = false, features = ["postgres", "time", "bigdecimal"] }
redis = { version = "0.25", default-features = false }
redis-versioned-kv = { path = "../redis-versioned-kv" }
hex = "0.4.3"
uint = "0.9.3"
sha3 = "0.8"
libsecp256k1 = { version = "0.5", features = ["static-context", "hmac"] }

ethereum = { version = "0.12.0", default-features = false, features = ["with-serde"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_json = "1.0"
3 changes: 3 additions & 0 deletions evm-exporter/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ pub enum Error {
#[error(transparent)]
RedisError(#[from] redis::RedisError),

#[error(transparent)]
PostgresError(#[from] sqlx::Error),

#[error(transparent)]
FromHexError(#[from] hex::FromHexError),

Expand Down
178 changes: 148 additions & 30 deletions evm-exporter/src/getter.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,158 @@
use {
crate::{keys, AccountBasic, Block, Receipt, Result, TransactionStatus},
crate::{keys, AccountBasic, Block, ConnectionType, Receipt, Result, TransactionStatus},
primitive_types::{H160, H256, U256},
redis::{Commands, ConnectionLike},
redis::{Commands, Connection},
redis_versioned_kv::VersionedKVCommand,
sqlx::PgConnection,
};

pub struct Getter<'a, C> {
conn: &'a mut C,
pub trait Getter {
fn new(conn: ConnectionType, something: String) -> Self
where
Self: std::marker::Sized;
fn latest_height(&mut self) -> Result<u32>;
fn lowest_height(&mut self) -> Result<u32>;
fn get_balance(&mut self, height: u32, address: H160) -> Result<U256>;
fn get_nonce(&mut self, height: u32, address: H160) -> Result<U256>;
fn get_byte_code(&mut self, height: u32, address: H160) -> Result<Vec<u8>>;
fn get_account_basic(&mut self, height: u32, address: H160) -> Result<AccountBasic>;
fn addr_state_exists(&mut self, height: u32, address: H160) -> Result<bool>;
fn get_state(&mut self, height: u32, address: H160, index: H256) -> Result<H256>;
fn get_block_hash_by_height(&mut self, height: U256) -> Result<Option<H256>>;
fn get_height_by_block_hash(&mut self, block_hash: H256) -> Result<Option<U256>>;
fn get_block_by_hash(&mut self, block_hash: H256) -> Result<Option<Block>>;
fn get_transaction_receipt_by_block_hash(
&mut self,
block_hash: H256,
) -> Result<Option<Vec<Receipt>>>;
fn get_transaction_status_by_block_hash(
&mut self,
block_hash: H256,
) -> Result<Option<Vec<TransactionStatus>>>;
fn get_transaction_index_by_tx_hash(&mut self, tx_hash: H256) -> Result<Option<(H256, u32)>>;
fn get_pending_balance(&mut self, address: H160) -> Result<Option<U256>>;
fn get_pending_nonce(&mut self, address: H160) -> Result<Option<U256>>;
fn get_pending_byte_code(&mut self, address: H160) -> Result<Option<Vec<u8>>>;
fn get_pending_state(&mut self, address: H160, index: H256) -> Result<Option<H256>>;
fn get_total_issuance(&mut self, height: u32) -> Result<U256>;
fn get_allowances(&mut self, height: u32, owner: H160, spender: H160) -> Result<U256>;
}

pub struct PgGetter {
conn: PgConnection,
}

impl Getter for PgGetter {
fn new(connection: ConnectionType, _something: String) -> Self {
if let ConnectionType::Postgres(conn) = connection {
Self { conn }
} else {
panic!("Invalid connection type for Postgres")
}
}
fn latest_height(&mut self) -> Result<u32> {
Ok(0)
}
fn lowest_height(&mut self) -> Result<u32> {
Ok(0)
}
fn get_balance(&mut self, height: u32, address: H160) -> Result<U256> {
Ok(U256::zero())
}
fn get_nonce(&mut self, height: u32, address: H160) -> Result<U256> {
Ok(U256::zero())
}
fn get_byte_code(&mut self, height: u32, address: H160) -> Result<Vec<u8>> {
Ok(vec![0])
}
fn get_account_basic(&mut self, height: u32, address: H160) -> Result<AccountBasic> {
Ok(AccountBasic {
balance: self.get_balance(height, address)?,
code: self.get_byte_code(height, address)?,
nonce: self.get_nonce(height, address)?,
})
}
fn addr_state_exists(&mut self, height: u32, address: H160) -> Result<bool> {
Ok(true)
}
fn get_state(&mut self, height: u32, address: H160, index: H256) -> Result<H256> {
Ok(H256::zero())
}
fn get_block_hash_by_height(&mut self, height: U256) -> Result<Option<H256>> {
Ok(Some(H256::zero()))
}
fn get_height_by_block_hash(&mut self, block_hash: H256) -> Result<Option<U256>> {
Ok(Some(U256::zero()))
}
fn get_block_by_hash(&mut self, block_hash: H256) -> Result<Option<Block>> {
Ok(None)
}
fn get_transaction_receipt_by_block_hash(
&mut self,
block_hash: H256,
) -> Result<Option<Vec<Receipt>>> {
Ok(None)
}
fn get_transaction_status_by_block_hash(
&mut self,
block_hash: H256,
) -> Result<Option<Vec<TransactionStatus>>> {
Ok(None)
}
fn get_transaction_index_by_tx_hash(&mut self, tx_hash: H256) -> Result<Option<(H256, u32)>> {
Ok(None)
}
fn get_pending_balance(&mut self, address: H160) -> Result<Option<U256>> {
Ok(Some(U256::zero()))
}
fn get_pending_nonce(&mut self, address: H160) -> Result<Option<U256>> {
Ok(Some(U256::zero()))
}
fn get_pending_byte_code(&mut self, address: H160) -> Result<Option<Vec<u8>>> {
Ok(None)
}
fn get_pending_state(&mut self, address: H160, index: H256) -> Result<Option<H256>> {
Ok(Some(H256::zero()))
}
fn get_total_issuance(&mut self, height: u32) -> Result<U256> {
Ok(U256::zero())
}
fn get_allowances(&mut self, height: u32, owner: H160, spender: H160) -> Result<U256> {
Ok(U256::zero())
}
}

pub struct RedisGetter {
conn: Connection,
pub prefix: String,
}

impl<'a, C: ConnectionLike> Getter<'a, C> {
pub fn new(conn: &'a mut C, prefix: String) -> Self {
Self { conn, prefix }
impl Getter for RedisGetter {
fn new(connection: ConnectionType, prefix: String) -> Self {
if let ConnectionType::Redis(conn) = connection {
Self { conn, prefix }
} else {
panic!("Invalid connection type for Redis")
}
}

pub fn latest_height(&mut self) -> Result<u32> {
fn latest_height(&mut self) -> Result<u32> {
let height_key = keys::latest_height_key(&self.prefix);
let height: Option<String> = self.conn.get(height_key)?;
match height {
Some(str) => Ok(str.parse::<u32>()?),
_ => Ok(0),
}
}
pub fn lowest_height(&mut self) -> Result<u32> {
fn lowest_height(&mut self) -> Result<u32> {
let height_key = keys::lowest_height_key(&self.prefix);
let height: Option<String> = self.conn.get(height_key)?;
match height {
Some(str) => Ok(str.parse::<u32>()?),
_ => Ok(0),
}
}
pub fn get_balance(&mut self, height: u32, address: H160) -> Result<U256> {
fn get_balance(&mut self, height: u32, address: H160) -> Result<U256> {
let balance_key = keys::balance_key(&self.prefix, address);
let balance: Option<String> = self.conn.vkv_get(balance_key, height)?;
let balance = if let Some(s) = balance {
Expand All @@ -42,7 +163,7 @@ impl<'a, C: ConnectionLike> Getter<'a, C> {
Ok(balance)
}

pub fn get_nonce(&mut self, height: u32, address: H160) -> Result<U256> {
fn get_nonce(&mut self, height: u32, address: H160) -> Result<U256> {
let nonce_key = keys::nonce_key(&self.prefix, address);
let nonce: Option<String> = self.conn.vkv_get(nonce_key, height)?;
let nonce = if let Some(s) = nonce {
Expand All @@ -53,7 +174,7 @@ impl<'a, C: ConnectionLike> Getter<'a, C> {
Ok(nonce)
}

pub fn get_byte_code(&mut self, height: u32, address: H160) -> Result<Vec<u8>> {
fn get_byte_code(&mut self, height: u32, address: H160) -> Result<Vec<u8>> {
let code_key = keys::code_key(&self.prefix, address);
let code: Option<String> = self.conn.vkv_get(code_key, height)?;
let code = if let Some(s) = code {
Expand All @@ -64,21 +185,21 @@ impl<'a, C: ConnectionLike> Getter<'a, C> {
Ok(code)
}

pub fn get_account_basic(&mut self, height: u32, address: H160) -> Result<AccountBasic> {
fn get_account_basic(&mut self, height: u32, address: H160) -> Result<AccountBasic> {
Ok(AccountBasic {
balance: self.get_balance(height, address)?,
code: self.get_byte_code(height, address)?,
nonce: self.get_nonce(height, address)?,
})
}

pub fn addr_state_exists(&mut self, height: u32, address: H160) -> Result<bool> {
fn addr_state_exists(&mut self, height: u32, address: H160) -> Result<bool> {
let state_addr_key = keys::state_addr_key(&self.prefix, address);
let value: Option<String> = self.conn.vkv_get(state_addr_key, height)?;
Ok(value.is_some())
}

pub fn get_state(&mut self, height: u32, address: H160, index: H256) -> Result<H256> {
fn get_state(&mut self, height: u32, address: H160, index: H256) -> Result<H256> {
let state_key = keys::state_key(&self.prefix, address, index);
let value: Option<String> = self.conn.vkv_get(state_key, height)?;
let val = if let Some(s) = value {
Expand All @@ -89,7 +210,7 @@ impl<'a, C: ConnectionLike> Getter<'a, C> {
Ok(val)
}

pub fn get_block_hash_by_height(&mut self, height: U256) -> Result<Option<H256>> {
fn get_block_hash_by_height(&mut self, height: U256) -> Result<Option<H256>> {
let block_hash_key = keys::block_hash_key(&self.prefix, height);
let value: Option<String> = self.conn.get::<&str, Option<String>>(&block_hash_key)?;
if let Some(hash) = value {
Expand All @@ -99,7 +220,7 @@ impl<'a, C: ConnectionLike> Getter<'a, C> {
}
}

pub fn get_height_by_block_hash(&mut self, block_hash: H256) -> Result<Option<U256>> {
fn get_height_by_block_hash(&mut self, block_hash: H256) -> Result<Option<U256>> {
let block_height_key = keys::block_height_key(&self.prefix, block_hash);
let value: Option<String> = self.conn.get::<&str, Option<String>>(&block_height_key)?;
if let Some(hash) = value {
Expand All @@ -109,7 +230,7 @@ impl<'a, C: ConnectionLike> Getter<'a, C> {
}
}

pub fn get_block_by_hash(&mut self, block_hash: H256) -> Result<Option<Block>> {
fn get_block_by_hash(&mut self, block_hash: H256) -> Result<Option<Block>> {
let block_key = keys::block_key(&self.prefix, block_hash);
let value: Option<String> = self.conn.get::<&str, Option<String>>(&block_key)?;
if let Some(block) = value {
Expand All @@ -119,7 +240,7 @@ impl<'a, C: ConnectionLike> Getter<'a, C> {
}
}

pub fn get_transaction_receipt_by_block_hash(
fn get_transaction_receipt_by_block_hash(
&mut self,
block_hash: H256,
) -> Result<Option<Vec<Receipt>>> {
Expand All @@ -132,7 +253,7 @@ impl<'a, C: ConnectionLike> Getter<'a, C> {
}
}

pub fn get_transaction_status_by_block_hash(
fn get_transaction_status_by_block_hash(
&mut self,
block_hash: H256,
) -> Result<Option<Vec<TransactionStatus>>> {
Expand All @@ -146,10 +267,7 @@ impl<'a, C: ConnectionLike> Getter<'a, C> {
}
}

pub fn get_transaction_index_by_tx_hash(
&mut self,
tx_hash: H256,
) -> Result<Option<(H256, u32)>> {
fn get_transaction_index_by_tx_hash(&mut self, tx_hash: H256) -> Result<Option<(H256, u32)>> {
let transaction_index_key = keys::transaction_index_key(&self.prefix, tx_hash);

let value: Option<String> = self.conn.get(transaction_index_key)?;
Expand All @@ -160,7 +278,7 @@ impl<'a, C: ConnectionLike> Getter<'a, C> {
}
}

pub fn get_pending_balance(&mut self, address: H160) -> Result<Option<U256>> {
fn get_pending_balance(&mut self, address: H160) -> Result<Option<U256>> {
let balance_key = keys::pending_balance_key(&self.prefix, address);
let balance: Option<String> = self.conn.get(balance_key)?;
let balance = if let Some(s) = balance {
Expand All @@ -171,7 +289,7 @@ impl<'a, C: ConnectionLike> Getter<'a, C> {
Ok(balance)
}

pub fn get_pending_nonce(&mut self, address: H160) -> Result<Option<U256>> {
fn get_pending_nonce(&mut self, address: H160) -> Result<Option<U256>> {
let nonce_key = keys::pending_nonce_key(&self.prefix, address);
let nonce: Option<String> = self.conn.get(nonce_key)?;
let nonce = if let Some(s) = nonce {
Expand All @@ -182,7 +300,7 @@ impl<'a, C: ConnectionLike> Getter<'a, C> {
Ok(nonce)
}

pub fn get_pending_byte_code(&mut self, address: H160) -> Result<Option<Vec<u8>>> {
fn get_pending_byte_code(&mut self, address: H160) -> Result<Option<Vec<u8>>> {
let code_key = keys::pending_code_key(&self.prefix, address);
let code: Option<String> = self.conn.get(code_key)?;
let code = if let Some(s) = code {
Expand All @@ -193,7 +311,7 @@ impl<'a, C: ConnectionLike> Getter<'a, C> {
Ok(code)
}

pub fn get_pending_state(&mut self, address: H160, index: H256) -> Result<Option<H256>> {
fn get_pending_state(&mut self, address: H160, index: H256) -> Result<Option<H256>> {
let state_key = keys::pending_state_key(&self.prefix, address, index);
let value: Option<String> = self.conn.get(state_key)?;
let val = if let Some(s) = value {
Expand All @@ -204,7 +322,7 @@ impl<'a, C: ConnectionLike> Getter<'a, C> {
Ok(val)
}

pub fn get_total_issuance(&mut self, height: u32) -> Result<U256> {
fn get_total_issuance(&mut self, height: u32) -> Result<U256> {
let key = keys::total_issuance_key(&self.prefix);
let value: Option<String> = self.conn.vkv_get(key, height)?;
let val = if let Some(s) = value {
Expand All @@ -215,7 +333,7 @@ impl<'a, C: ConnectionLike> Getter<'a, C> {
Ok(val)
}

pub fn get_allowances(&mut self, height: u32, owner: H160, spender: H160) -> Result<U256> {
fn get_allowances(&mut self, height: u32, owner: H160, spender: H160) -> Result<U256> {
let key = keys::allowances_key(&self.prefix, owner, spender);
let value: Option<String> = self.conn.vkv_get(key, height)?;
let val = if let Some(s) = value {
Expand Down
5 changes: 5 additions & 0 deletions evm-exporter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,8 @@ pub use setter::*;

mod utils;
pub use utils::*;

pub enum ConnectionType {
Redis(redis::Connection),
Postgres(sqlx::PgConnection),
}
Loading

0 comments on commit 468e310

Please sign in to comment.