Skip to content

Commit

Permalink
evm: Implement eth_syncing RPC (#2049)
Browse files Browse the repository at this point in the history
* Implement eth_syncing RPC

* Remove old imports

* Fix segfault

* Add starting block data

* Format

* Fix formatting
  • Loading branch information
shohamc1 authored Jun 23, 2023
1 parent 81a35d5 commit 4b68eca
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 14 deletions.
2 changes: 2 additions & 0 deletions lib/ain-cpp-imports/src/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ pub mod ffi {
fn getMinRelayTxFee() -> u64;
fn getEthPrivKey(key_id: [u8; 20]) -> [u8; 32];
fn getStateInputJSON() -> String;
fn getHighestBlock() -> i32;
fn getCurrentHeight() -> i32;
fn pastChangiIntermediateHeight2() -> bool;
}
}
12 changes: 12 additions & 0 deletions lib/ain-cpp-imports/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ mod ffi {
pub fn getStateInputJSON() -> String {
unimplemented!("{}", UNIMPL_MSG)
}
pub fn getHighestBlock() -> i32 {
unimplemented!("{}", UNIMPL_MSG)
}
pub fn getCurrentHeight() -> i32 {
unimplemented!("{}", UNIMPL_MSG)
}
pub fn pastChangiIntermediateHeight2() -> bool {
unimplemented!("{}", UNIMPL_MSG)
}
Expand Down Expand Up @@ -122,6 +128,12 @@ pub fn get_state_input_json() -> Option<String> {
}
}

pub fn get_sync_status() -> Result<(i32, i32), Box<dyn Error>> {
let current_block = ffi::getCurrentHeight();
let highest_block = ffi::getHighestBlock();
Ok((current_block, highest_block))
}

pub fn past_changi_intermediate_height_2_height() -> Result<bool, Box<dyn Error>> {
let height = ffi::pastChangiIntermediateHeight2();
Ok(height)
Expand Down
18 changes: 17 additions & 1 deletion lib/ain-evm/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::storage::{traits::BlockStorage, Storage};

pub struct BlockHandler {
storage: Arc<Storage>,
first_block_number: U256,
}

pub struct FeeHistoryData {
Expand All @@ -24,7 +25,22 @@ pub const INITIAL_BASE_FEE: U256 = U256([10_000_000_000, 0, 0, 0]); // wei

impl BlockHandler {
pub fn new(storage: Arc<Storage>) -> Self {
Self { storage }
let mut block_handler = Self {
storage,
first_block_number: U256::zero(),
};
let (_, block_number) = block_handler
.get_latest_block_hash_and_number()
.unwrap_or_default();

block_handler.first_block_number = block_number;
debug!("Current block number is {:#?}", block_number);

block_handler
}

pub fn get_first_block_number(&self) -> U256 {
self.first_block_number
}

pub fn get_latest_block_hash_and_number(&self) -> Option<(H256, U256)> {
Expand Down
1 change: 1 addition & 0 deletions lib/ain-grpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod codegen;
mod impls;
mod receipt;
pub mod rpc;
mod sync;
mod transaction;
mod transaction_log;
mod transaction_request;
Expand Down
41 changes: 39 additions & 2 deletions lib/ain-grpc/src/rpc/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use ain_evm::evm::MAX_GAS_PER_BLOCK;
use ain_evm::executor::TxResponse;
use ain_evm::handler::Handlers;

use crate::sync::{SyncInfo, SyncState};
use crate::transaction_log::{GetLogsRequest, LogResult};
use ain_evm::storage::traits::{BlockStorage, ReceiptStorage, TransactionStorage};
use ain_evm::transaction::{SignedTx, TransactionError};
Expand Down Expand Up @@ -44,6 +45,9 @@ pub trait MetachainRPC {
#[method(name = "chainId")]
fn chain_id(&self) -> RpcResult<String>;

#[method(name = "syncing")]
fn syncing(&self) -> RpcResult<SyncState>;

// ----------------------------------------
// Block
// ----------------------------------------
Expand Down Expand Up @@ -255,7 +259,7 @@ impl MetachainRPCModule {
.get_block_by_number(&U256::from(n))
.map(|block| block.header.number)
.unwrap_or(U256::max_value())
},
}
_ => {
self.handler
.storage
Expand Down Expand Up @@ -590,7 +594,7 @@ impl MetachainRPCServer for MetachainRPCModule {
_ => {
return Err(Error::Custom(String::from(
"invalid transaction parameters",
)))
)));
}
};

Expand Down Expand Up @@ -743,6 +747,39 @@ impl MetachainRPCServer for MetachainRPCModule {
Ok(self.handler.block.suggested_priority_fee())
}

fn syncing(&self) -> RpcResult<SyncState> {
let (current_native_height, highest_native_block) = ain_cpp_imports::get_sync_status()
.map_err(|e| {
Error::Custom(format!("ain_cpp_imports::get_sync_status error : {e:?}"))
})?;

if current_native_height == -1 {
return Err(Error::Custom(format!("Block index not available")));
}

match current_native_height != highest_native_block {
true => {
let current_block = self
.handler
.storage
.get_latest_block()
.map(|block| block.header.number)
.ok_or_else(|| Error::Custom(String::from("Unable to get current block")))?;

let starting_block = self.handler.block.get_first_block_number();

let highest_block = current_block + (highest_native_block - current_native_height);
debug!("Highest native: {highest_native_block}\nCurrent native: {current_native_height}\nCurrent ETH: {current_block}\nHighest ETH: {highest_block}");

Ok(SyncState::Syncing(SyncInfo {
starting_block,
current_block,
highest_block,
}))
}
false => Ok(SyncState::Synced(false)),
}
}
fn get_uncle_count_by_block_number(&self) -> RpcResult<U256> {
Ok(Default::default())
}
Expand Down
30 changes: 30 additions & 0 deletions lib/ain-grpc/src/sync.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use primitive_types::U256;
use serde::{Serialize, Serializer};

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct SyncInfo {
pub starting_block: U256,
pub current_block: U256,
pub highest_block: U256,
}

/// Sync state
#[derive(Debug, Deserialize, Clone)]
pub enum SyncState {
/// Only hashes
Synced(bool),
/// Full transactions
Syncing(SyncInfo),
}

impl Serialize for SyncState {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
SyncState::Synced(ref sync) => sync.serialize(serializer),
SyncState::Syncing(ref sync_info) => sync_info.serialize(serializer),
}
}
}
32 changes: 21 additions & 11 deletions src/ffi/ffiexports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ rust::string publishEthTransaction(rust::Vec<uint8_t> rawTransaction) {
try {
execTestTx(CTransaction(rawTx), targetHeight, optAuthTx);
send(MakeTransactionRef(std::move(rawTx)), optAuthTx)->GetHash().ToString();
} catch (std::runtime_error& e) {
} catch (std::runtime_error &e) {
return e.what();
} catch (const UniValue& objError) {
} catch (const UniValue &objError) {
const auto obj = objError.get_obj();

return obj["message"].get_str();
Expand All @@ -58,8 +58,8 @@ rust::string publishEthTransaction(rust::Vec<uint8_t> rawTransaction) {
rust::vec<rust::string> getAccounts() {
rust::vec<rust::string> addresses;
std::vector<std::shared_ptr<CWallet>> const wallets = GetWallets();
for (const std::shared_ptr<CWallet>& wallet : wallets) {
for (auto & it : wallet->mapAddressBook)
for (const std::shared_ptr<CWallet> &wallet: wallets) {
for (auto &it: wallet->mapAddressBook)
if (std::holds_alternative<WitnessV16EthHash>(it.first)) {
addresses.push_back(EncodeDestination(it.first));
}
Expand All @@ -68,14 +68,14 @@ rust::vec<rust::string> getAccounts() {
}

rust::string getDatadir() {
#ifdef WIN32
#ifdef WIN32
// https://learn.microsoft.com/en-us/cpp/cpp/char-wchar-t-char16-t-char32-t?view=msvc-170
// We're sidestepping this for now unsafely making an assumption. Can crash on Windows
// if odd paths are used. Require testing.
return rust::String(reinterpret_cast<const char16_t*>(GetDataDir().c_str()));
#else
#else
return rust::String(GetDataDir().c_str());
#endif
#endif
}

rust::string getNetwork() {
Expand All @@ -86,7 +86,7 @@ uint32_t getDifficulty(std::array<uint8_t, 32> blockHash) {
uint256 hash{};
std::copy(blockHash.begin(), blockHash.end(), hash.begin());

const CBlockIndex* pblockindex;
const CBlockIndex *pblockindex;
uint32_t difficulty{};
{
LOCK(cs_main);
Expand All @@ -106,7 +106,7 @@ std::array<uint8_t, 32> getChainWork(std::array<uint8_t, 32> blockHash) {
uint256 hash{};
std::copy(blockHash.begin(), blockHash.end(), hash.begin());

const CBlockIndex* pblockindex;
const CBlockIndex *pblockindex;
std::array<uint8_t, 32> chainWork{};
{
LOCK(cs_main);
Expand Down Expand Up @@ -139,7 +139,8 @@ rust::vec<rust::string> getPoolTransactions() {
}

CCustomTxMessage txMessage{CEvmTxMessage{}};
const auto res = CustomMetadataParse(std::numeric_limits<uint32_t>::max(), Params().GetConsensus(), metadata, txMessage);
const auto res = CustomMetadataParse(std::numeric_limits<uint32_t>::max(), Params().GetConsensus(), metadata,
txMessage);
if (!res) {
continue;
}
Expand Down Expand Up @@ -188,7 +189,7 @@ uint64_t getMinRelayTxFee() {
std::array<uint8_t, 32> getEthPrivKey(std::array<uint8_t, 20> keyID) {
CKey ethPrivKey;
const auto ethKeyID = CKeyID{uint160{std::vector<uint8_t>(keyID.begin(), keyID.end())}};
for (const auto &wallet : GetWallets()) {
for (const auto &wallet: GetWallets()) {
if (wallet->GetEthKey(ethKeyID, ethPrivKey)) {
std::array<uint8_t, 32> privKeyArray{};
std::copy(ethPrivKey.begin(), ethPrivKey.end(), privKeyArray.begin());
Expand All @@ -202,6 +203,15 @@ rust::string getStateInputJSON() {
return gArgs.GetArg("-ethstartstate", "");
}

int getHighestBlock() {
return pindexBestHeader ? pindexBestHeader->nHeight
: (int) ::ChainActive().Height(); // return current block count if no peers
}

int getCurrentHeight() {
return ::ChainActive().Height() ? (int) ::ChainActive().Height() : -1;
}

bool pastChangiIntermediateHeight2() {
return ::ChainActive().Height() >= Params().GetConsensus().ChangiIntermediateHeight2;
}
2 changes: 2 additions & 0 deletions src/ffi/ffiexports.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ uint64_t getNativeTxSize(rust::Vec<uint8_t> rawTransaction);
uint64_t getMinRelayTxFee();
std::array<uint8_t, 32> getEthPrivKey(std::array<uint8_t, 20> keyID);
rust::string getStateInputJSON();
int getHighestBlock();
int getCurrentHeight();
bool pastChangiIntermediateHeight2();

#endif // DEFI_FFI_FFIEXPORTS_H

0 comments on commit 4b68eca

Please sign in to comment.