Commit 51da1fcf authored by clabby's avatar clabby

:broom:

parent b2bc5430
use reth::{ use reth::{
blockchain_tree::noop::NoopBlockchainTree, blockchain_tree::noop::NoopBlockchainTree,
primitives::{ primitives::{
BlockHashOrNumber, ChainSpecBuilder, Receipt, TransactionMeta, TransactionSigned, U128, BlockHashOrNumber, Receipt, TransactionKind, TransactionMeta, TransactionSigned, MAINNET,
U256, U64, U128, U256, U64,
}, },
providers::{providers::BlockchainProvider, BlockReader, ProviderFactory, ReceiptProvider}, providers::{providers::BlockchainProvider, BlockReader, ProviderFactory, ReceiptProvider},
revm::primitives::calc_blob_gasprice,
rpc::types::{Log, TransactionReceipt}, rpc::types::{Log, TransactionReceipt},
utils::db::open_db_read_only, utils::db::open_db_read_only,
}; };
use std::{os::raw::c_char, path::Path, sync::Arc}; use std::{os::raw::c_char, path::Path};
#[repr(C)] #[repr(C)]
pub struct ReceiptsResult { pub struct ReceiptsResult {
...@@ -38,45 +37,51 @@ impl ReceiptsResult { ...@@ -38,45 +37,51 @@ impl ReceiptsResult {
/// Read the receipts for a blockhash from the RETH database directly. /// Read the receipts for a blockhash from the RETH database directly.
/// ///
/// WARNING: Will panic on error. /// # Safety
/// TODO: Gracefully return OK status. /// - All possible nil pointer dereferences are checked, and the function will return a
/// failing [ReceiptsResult] if any are found.
#[no_mangle] #[no_mangle]
pub extern "C" fn read_receipts( pub unsafe extern "C" fn read_receipts(
block_hash: *const u8, block_hash: *const u8,
block_hash_len: usize, block_hash_len: usize,
db_path: *const c_char, db_path: *const c_char,
) -> ReceiptsResult { ) -> ReceiptsResult {
// Convert the raw pointer and length back to a Rust slice // Convert the raw pointer and length back to a Rust slice
let Ok(block_hash): Result<[u8; 32], _> = let Ok(block_hash): Result<[u8; 32], _> = {
unsafe { std::slice::from_raw_parts(block_hash, block_hash_len) }.try_into() if block_hash.is_null() {
else { return ReceiptsResult::fail();
}
std::slice::from_raw_parts(block_hash, block_hash_len)
}
.try_into() else {
return ReceiptsResult::fail(); return ReceiptsResult::fail();
}; };
// Convert the *const c_char to a Rust &str // Convert the *const c_char to a Rust &str
let Ok(db_path_str) = unsafe { let Ok(db_path_str) = {
assert!(!db_path.is_null(), "Null pointer for database path"); if db_path.is_null() {
return ReceiptsResult::fail();
}
std::ffi::CStr::from_ptr(db_path) std::ffi::CStr::from_ptr(db_path)
} }
.to_str() else { .to_str() else {
return ReceiptsResult::fail(); return ReceiptsResult::fail();
}; };
let Ok(db) = open_db_read_only(&Path::new(db_path_str), None) else { let Ok(db) = open_db_read_only(Path::new(db_path_str), None) else {
return ReceiptsResult::fail(); return ReceiptsResult::fail();
}; };
let spec = Arc::new(ChainSpecBuilder::mainnet().build()); let factory = ProviderFactory::new(db, MAINNET.clone());
let factory = ProviderFactory::new(db, spec.clone());
// Create a read-only BlockChainProvider // Create a read-only BlockChainProvider
let Ok(provider) = BlockchainProvider::new(factory, NoopBlockchainTree::default()) else { let Ok(provider) = BlockchainProvider::new(factory, NoopBlockchainTree::default()) else {
return ReceiptsResult::fail(); return ReceiptsResult::fail();
}; };
// Fetch the block and the receipts within it
let Ok(block) = provider.block_by_hash(block_hash.into()) else { let Ok(block) = provider.block_by_hash(block_hash.into()) else {
return ReceiptsResult::fail(); return ReceiptsResult::fail();
}; };
let Ok(receipts) = provider.receipts_by_block(BlockHashOrNumber::Hash(block_hash.into())) let Ok(receipts) = provider.receipts_by_block(BlockHashOrNumber::Hash(block_hash.into()))
else { else {
return ReceiptsResult::fail(); return ReceiptsResult::fail();
...@@ -86,7 +91,6 @@ pub extern "C" fn read_receipts( ...@@ -86,7 +91,6 @@ pub extern "C" fn read_receipts(
let block_number = block.number; let block_number = block.number;
let base_fee = block.base_fee_per_gas; let base_fee = block.base_fee_per_gas;
let block_hash = block.hash_slow(); let block_hash = block.hash_slow();
let excess_blob_gas = block.excess_blob_gas;
let Some(receipts) = block let Some(receipts) = block
.body .body
.into_iter() .into_iter()
...@@ -99,7 +103,7 @@ pub extern "C" fn read_receipts( ...@@ -99,7 +103,7 @@ pub extern "C" fn read_receipts(
block_hash, block_hash,
block_number, block_number,
base_fee, base_fee,
excess_blob_gas, excess_blob_gas: None,
}; };
build_transaction_receipt_with_block_receipts(tx, meta, receipt, &receipts) build_transaction_receipt_with_block_receipts(tx, meta, receipt, &receipts)
}) })
...@@ -127,14 +131,15 @@ pub extern "C" fn read_receipts( ...@@ -127,14 +131,15 @@ pub extern "C" fn read_receipts(
} }
/// Free a string that was allocated in Rust and passed to C. /// Free a string that was allocated in Rust and passed to C.
///
/// # Safety
/// - All possible nil pointer dereferences are checked.
#[no_mangle] #[no_mangle]
pub extern "C" fn free_string(string: *mut c_char) { pub unsafe extern "C" fn free_string(string: *mut c_char) {
unsafe { // Convert the raw pointer back to a CString and let it go out of scope,
// Convert the raw pointer back to a CString and let it go out of scope, // which will deallocate the memory.
// which will deallocate the memory. if !string.is_null() {
if !string.is_null() { let _ = std::ffi::CString::from_raw(string);
let _ = std::ffi::CString::from_raw(string);
}
} }
} }
...@@ -181,16 +186,16 @@ fn build_transaction_receipt_with_block_receipts( ...@@ -181,16 +186,16 @@ fn build_transaction_receipt_with_block_receipts(
}, },
// EIP-4844 fields // EIP-4844 fields
blob_gas_price: meta.excess_blob_gas.map(calc_blob_gasprice).map(U128::from), blob_gas_price: None,
blob_gas_used: transaction.transaction.blob_gas_used().map(U128::from), blob_gas_used: None,
}; };
match tx.transaction.kind() { match tx.transaction.kind() {
reth::primitives::TransactionKind::Create => { TransactionKind::Create => {
res_receipt.contract_address = res_receipt.contract_address =
Some(transaction.signer().create(tx.transaction.nonce())); Some(transaction.signer().create(tx.transaction.nonce()));
} }
reth::primitives::TransactionKind::Call(addr) => { TransactionKind::Call(addr) => {
res_receipt.to = Some(*addr); res_receipt.to = Some(*addr);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment