Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

evm: Implement eth_syncing RPC #2049

Merged
merged 7 commits into from
Jun 23, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,5 +16,7 @@ pub mod ffi {
fn getMinRelayTxFee() -> u64;
fn getEthPrivKey(key_id: [u8; 20]) -> [u8; 32];
fn getStateInputJSON() -> String;
fn getHighestBlock() -> i32;
fn getCurrentHeight() -> i32;
}
}
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 get_chain_id() -> Result<u64, Box<dyn Error>> {
Expand Down Expand Up @@ -119,5 +125,11 @@ 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))
}

#[cfg(test)]
mod tests {}
1 change: 1 addition & 0 deletions lib/ain-grpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub mod codegen;
mod impls;
mod receipt;
pub mod rpc;
mod sync;
mod transaction;
mod transaction_request;
mod utils;
Expand Down
36 changes: 36 additions & 0 deletions lib/ain-grpc/src/rpc/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use ain_cpp_imports::get_eth_priv_key;
use ain_evm::executor::TxResponse;
use ain_evm::handler::Handlers;

use crate::sync::{SyncInfo, SyncState};
use ain_evm::storage::traits::{BlockStorage, ReceiptStorage, TransactionStorage};
use ain_evm::transaction::{SignedTx, TransactionError};
use ethereum::{EnvelopedEncodable, TransactionV2};
Expand Down Expand Up @@ -203,6 +204,9 @@ pub trait MetachainRPC {

#[method(name = "maxPriorityFeePerGas")]
fn max_priority_fee_per_gas(&self) -> RpcResult<U256>;

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

pub struct MetachainRPCModule {
Expand Down Expand Up @@ -703,6 +707,38 @@ impl MetachainRPCServer for MetachainRPCModule {
fn max_priority_fee_per_gas(&self) -> RpcResult<U256> {
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 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: U256::zero(),
Jouzo marked this conversation as resolved.
Show resolved Hide resolved
current_block,
highest_block,
}))
}
false => Ok(SyncState::Synced(false)),
}
}
}

fn sign(
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 @@ -201,3 +202,12 @@ std::array<uint8_t, 32> getEthPrivKey(std::array<uint8_t, 20> keyID) {
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;
}
2 changes: 2 additions & 0 deletions src/ffi/ffiexports.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@ 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();

#endif // DEFI_FFI_FFIEXPORTS_H