Skip to content

Commit

Permalink
Merge branch master into evm_transferdomain_tx
Browse files Browse the repository at this point in the history
  • Loading branch information
Jouzo committed Sep 4, 2023
2 parents dc984c5 + 97ac254 commit 0ec6ec3
Show file tree
Hide file tree
Showing 23 changed files with 1,243 additions and 88 deletions.
6 changes: 6 additions & 0 deletions lib/ain-evm/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,12 @@ impl EVMBackend {
.unwrap_or_default()
}

pub fn get_balance(&self, address: &H160) -> U256 {
self.get_account(address)
.map(|acc| acc.balance)
.unwrap_or_default()
}

pub fn get_contract_storage(&self, contract: H160, storage_index: &[u8]) -> Result<U256> {
let Some(account) = self.get_account(&contract) else {
return Ok(U256::zero());
Expand Down
26 changes: 22 additions & 4 deletions lib/ain-evm/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub struct BlockService {
}

pub struct FeeHistoryData {
pub oldest_block: H256,
pub oldest_block: U256,
pub base_fee_per_gas: Vec<U256>,
pub gas_used_ratio: Vec<f64>,
pub reward: Option<Vec<Vec<U256>>>,
Expand Down Expand Up @@ -163,7 +163,7 @@ impl BlockService {
let mut blocks = Vec::with_capacity(block_count);
let mut block_number = first_block;

for _ in 0..=block_count {
for _ in 1..=block_count {
let block = match self.storage.get_block_by_number(&block_number)? {
None => Err(format_err!("Block {} out of range", block_number)),
Some(block) => Ok(block),
Expand All @@ -174,7 +174,7 @@ impl BlockService {
block_number -= U256::one();
}

let oldest_block = blocks.last().unwrap().header.hash();
let oldest_block = blocks.last().unwrap().header.number;

let (mut base_fee_per_gas, mut gas_used_ratio): (Vec<U256>, Vec<f64>) = blocks
.iter()
Expand Down Expand Up @@ -236,7 +236,7 @@ impl BlockService {
let mut data = Data::new(priority_fees);

for pct in &priority_fee_percentile {
block_rewards.push(U256::from(data.percentile(*pct).ceil() as u64));
block_rewards.push(U256::from(data.percentile(*pct).floor() as u64));
}

reward.push(block_rewards);
Expand All @@ -246,7 +246,25 @@ impl BlockService {
Some(reward)
};

// add another entry for baseFeePerGas
let next_block_base_fee = match self
.storage
.get_block_by_number(&(first_block + U256::one()))?
{
None => {
// get one block earlier (this should exist)
let block = self
.storage
.get_block_by_number(&first_block)?
.ok_or_else(|| format_err!("Block {} out of range", first_block))?;
self.calculate_base_fee(block.header.hash())?
}
Some(block) => self.calculate_base_fee(block.header.hash())?,
};

base_fee_per_gas.reverse();
base_fee_per_gas.push(next_block_base_fee);

gas_used_ratio.reverse();

Ok(FeeHistoryData {
Expand Down
12 changes: 12 additions & 0 deletions lib/ain-evm/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,11 +588,23 @@ impl EVMCoreService {
"[get_latest_block_backend] At block number : {:#x}, state_root : {:#x}",
block_number, state_root
);
self.get_backend(state_root)
}

pub fn get_backend(&self, state_root: H256) -> Result<EVMBackend> {
debug!("[get_backend] State_root : {:#x}", state_root);
EVMBackend::from_root(
state_root,
Arc::clone(&self.trie_store),
Arc::clone(&self.storage),
Vicinity::default(),
)
}

pub fn get_balance_at_state_root(&self, address: H160, state_root: H256) -> Result<U256> {
let balance = self.get_backend(state_root)?.get_balance(&address);

debug!("Account {:x?} balance {:x?}", address, balance);
Ok(balance)
}
}
16 changes: 16 additions & 0 deletions lib/ain-evm/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub struct FinalizedBlockInfo {
pub total_burnt_fees: U256,
pub total_priority_fees: U256,
pub block_number: U256,
pub state_root: XHash,
}

pub type ReceiptAndOptionalContractAddress = (ReceiptV3, Option<H160>);
Expand Down Expand Up @@ -487,6 +488,7 @@ impl EVMServices {
block.header.hash(),
block.header.number,
);
let new_state_root = format!("{:?}", block.header.state_root);
queue.block_data = Some(BlockData { block, receipts });

Ok(FinalizedBlockInfo {
Expand All @@ -495,6 +497,7 @@ impl EVMServices {
total_burnt_fees,
total_priority_fees,
block_number: current_block_number,
state_root: new_state_root,
})
}

Expand Down Expand Up @@ -620,6 +623,19 @@ impl EVMServices {
Ok(nonce)
}

pub fn get_dst20_total_supply(&self, token_id: u64, state_root: Option<H256>) -> Result<U256> {
let address = ain_contracts::dst20_address_from_token_id(token_id)?;
debug!("[get_dst20_total_supply] Fetching address {:#?}", address);

let backend = match state_root {
Some(state_root) => self.core.get_backend(state_root),
None => self.core.get_latest_block_backend(),
}?;

let total_supply_index = H256::from_low_u64_be(2);
backend.get_contract_storage(address, total_supply_index.as_bytes())
}

pub fn reserve_dst20_namespace(&self, executor: &mut AinExecutor) -> Result<()> {
let Contract { bytecode, .. } = get_reserved_contract();
let addresses = (1..=1024)
Expand Down
2 changes: 1 addition & 1 deletion lib/ain-grpc/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ impl Serialize for BlockTransactions {
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct RpcFeeHistory {
pub oldest_block: H256,
pub oldest_block: U256,
pub base_fee_per_gas: Vec<U256>,
pub gas_used_ratio: Vec<f64>,
pub reward: Option<Vec<Vec<U256>>>,
Expand Down
68 changes: 67 additions & 1 deletion lib/ain-rs-exports/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,46 @@ pub fn evm_try_get_balance(result: &mut ffi::CrossBoundaryResult, address: &str)
}
}

/// Retrieves the balance of an EVM account at state root.
///
/// # Arguments
///
/// * `address` - The EVM address of the account.
/// * `state_root` - The state root from which to restore temporary trie database.
///
/// # Errors
///
/// Returns an Error if the address is not a valid EVM address.
///
/// # Returns
///
/// Returns the balance of the account as a `u64` on success.
pub fn evm_try_get_balance_at_state_root(
result: &mut ffi::CrossBoundaryResult,
address: &str,
state_root: &str,
) -> u64 {
let Ok(address) = address.parse() else {
return cross_boundary_error_return(result, "Invalid address");
};
let Ok(state_root) = state_root.parse() else {
return cross_boundary_error_return(result, "Invalid state root");
};

match SERVICES
.evm
.core
.get_balance_at_state_root(address, state_root)
{
Err(e) => cross_boundary_error_return(result, e.to_string()),
Ok(balance) => {
let amount = WeiAmount(balance).to_satoshi().try_into();

try_cross_boundary_return(result, amount)
}
}
}

/// Retrieves the next valid nonce of an EVM account in a specific queue_id
///
/// # Arguments
Expand Down Expand Up @@ -647,6 +687,7 @@ pub fn evm_unsafe_try_construct_block_in_q(
total_burnt_fees,
total_priority_fees,
block_number,
state_root,
}) => {
let Ok(total_burnt_fees) = u64::try_from(WeiAmount(total_burnt_fees).to_satoshi())
else {
Expand All @@ -667,6 +708,7 @@ pub fn evm_unsafe_try_construct_block_in_q(
total_burnt_fees,
total_priority_fees,
block_number: block_number.as_u64(),
state_root,
}
}
Err(e) => cross_boundary_error_return(result, e.to_string()),
Expand Down Expand Up @@ -826,6 +868,30 @@ pub fn evm_try_is_dst20_deployed_or_queued(
}
}

pub fn evm_try_get_dst20_total_supply(
result: &mut ffi::CrossBoundaryResult,
token_id: u64,
state_root: &str,
) -> u64 {
let state_root = match state_root {
"" => None,
_ => match state_root.parse() {
Ok(state_root) => Some(state_root),
Err(_) => return cross_boundary_error_return(result, "Invalid state root"),
},
};

match SERVICES.evm.get_dst20_total_supply(token_id, state_root) {
Ok(total_supply) => {
let Ok(total_supply) = u64::try_from(WeiAmount(total_supply).to_satoshi()) else {
return cross_boundary_error_return(result, "Total supply value overflow");
};
cross_boundary_success_return(result, total_supply)
}
Err(e) => cross_boundary_error_return(result, e.to_string()),
}
}

pub fn evm_try_get_tx_by_hash(
result: &mut ffi::CrossBoundaryResult,
tx_hash: &str,
Expand Down Expand Up @@ -1014,7 +1080,7 @@ mod tests {
#[test]
fn test_hash_type_string() {
use primitive_types::H160;
let num = 0b11010111_11010111_11010111_11010111_11010111_11010111_11010111_11010111;
let num = 0b1101_0111_1101_0111_1101_0111_1101_0111_1101_0111_1101_0111_1101_0111_1101_0111;
let num_h160 = H160::from_low_u64_be(num);
let num_h160_string = format!("{:?}", num_h160);
println!("{}", num_h160_string);
Expand Down
13 changes: 13 additions & 0 deletions lib/ain-rs-exports/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ pub mod ffi {
pub total_burnt_fees: u64,
pub total_priority_fees: u64,
pub block_number: u64,
pub state_root: String,
}

#[derive(Default)]
Expand All @@ -110,6 +111,12 @@ pub mod ffi {
// If they are fallible, it's a TODO to changed and move later
// so errors are propogated up properly.
fn evm_try_get_balance(result: &mut CrossBoundaryResult, address: &str) -> u64;
fn evm_try_get_balance_at_state_root(
result: &mut CrossBoundaryResult,
address: &str,
state_root: &str,
) -> u64;

fn evm_unsafe_try_create_queue(result: &mut CrossBoundaryResult) -> u64;
fn evm_unsafe_try_remove_queue(result: &mut CrossBoundaryResult, queue_id: u64);
fn evm_try_disconnect_latest_block(result: &mut CrossBoundaryResult);
Expand Down Expand Up @@ -222,5 +229,11 @@ pub mod ffi {
result: &mut CrossBoundaryResult,
queue_id: u64,
) -> u64;

fn evm_try_get_dst20_total_supply(
result: &mut CrossBoundaryResult,
token_id: u64,
state_root: &str,
) -> u64;
}
}
24 changes: 24 additions & 0 deletions src/masternodes/errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,30 @@ class DeFiErrors {
return Res::Err("TransferDomain currently only supports a single transfer per transaction");
}

static Res AccountingMoreDVMInThanOut(const std::string &token, const std::string &amount) {
return Res::Err("More token #%s moved in DVM from EVM than out. DVM domain balance (should be negative or zero): %s", token, amount);
}

static Res AccountingMoreEVMOurThanIn(const std::string &token, const std::string &amount) {
return Res::Err("More token #%s moved in DVM from EVM than out. DVM domain balance (should be negative or zero): %s", token, amount);
}

static Res AccountingMissmatch(const std::string &direction, const std::string &oldBalance, const std::string &newBalance, const std::string &accounting) {
return Res::Err("Accounting mistmatch %s - Old: %s New: %s Accounting: %s", direction, oldBalance, newBalance, accounting);
}

static Res AccountingMissmatchEVM(const std::string &address, const CAmount oldBalance, const CAmount newBalance, const CAmount currentBalance) {
return Res::Err("Accounting mistmatch on EVM side for DFI token on address %s: Old: %lld New: %lld Current: %lld", address, oldBalance, newBalance, currentBalance);
}

static Res AccountingMissmatchEVMDST20(const std::string &token, const CAmount oldBalance, const CAmount newBalance, const CAmount currentBalance) {
return Res::Err("Accounting mistmatch on EVM side for DST20 total supply on token #%s: Old: %lld New: %lld Current: %lld", token, oldBalance, newBalance, currentBalance);
}

static Res InvalidEVMAddressBalance() {
return Res::Err("Unable to read EVM address balance");
}

static Res SettingEVMAttributeFailure() {
return Res::Err("Failed to set EVM attribute");
}
Expand Down
13 changes: 13 additions & 0 deletions src/masternodes/govvariables/attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ enum class EVMAttributesTypes : uint32_t {

extern UniValue AmountsToJSON(const TAmounts &diffs, AmountFormat format = AmountFormat::Symbol);

UniValue CTransferDomainStatsLive::ToUniValue() const {
UniValue obj(UniValue::VOBJ);
obj.pushKV("dvmIn", AmountsToJSON(dvmIn.balances));
obj.pushKV("dvmOut", AmountsToJSON(dvmOut.balances));
obj.pushKV("dvmCurrent", AmountsToJSON(dvmCurrent.balances));
obj.pushKV("evmIn", AmountsToJSON(evmIn.balances));
obj.pushKV("evmOut", AmountsToJSON(evmOut.balances));
obj.pushKV("evmOut", AmountsToJSON(evmCurrent.balances));
obj.pushKV("dvmEvm", AmountsToJSON(dvmEvmTotal.balances));
obj.pushKV("evmDvm", AmountsToJSON(evmDvmTotal.balances));
return obj;
}

static inline std::string trim_all_ws(std::string s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end());
Expand Down
18 changes: 18 additions & 0 deletions src/masternodes/govvariables/attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,27 @@ struct CTransferDomainStatsLive {
READWRITE(evmCurrent);
}

UniValue ToUniValue() const;

static constexpr CDataStructureV0 Key = {AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::TransferDomainStatsLive};
};

struct CEVMInitialState
{
CTransferDomainStatsLive transferDomainState;
std::map<CScript, CStatsTokenBalances> evmBalances;
CStatsTokenBalances dst20EvmTotalSupply;

ADD_SERIALIZE_METHODS;

template <typename Stream, typename Operation>
inline void SerializationOp(Stream &s, Operation ser_action) {
READWRITE(transferDomainState);
READWRITE(evmBalances);
READWRITE(dst20EvmTotalSupply);
}
};

struct CConsortiumMember {
static const uint16_t MAX_CONSORTIUM_MEMBERS_STRING_LENGTH = 512;
static const uint16_t MIN_CONSORTIUM_MEMBERS_STRING_LENGTH = 3;
Expand Down
4 changes: 1 addition & 3 deletions src/masternodes/mn_checks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3909,7 +3909,6 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor {
}
}
else {
CrossBoundaryResult result;
evm_try_bridge_dst20(result, evmQueueId, HexStr(dst.data), tx.GetHash().GetHex(), tokenId.v, true);
if (!result.ok) {
return Res::Err("Error bridging DST20: %s", result.reason);
Expand All @@ -3924,8 +3923,8 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor {
ExtractDestination(src.address, dest);

auto tokenId = dst.amount.nTokenId;
CrossBoundaryResult result;
if (tokenId == DCT_ID{0}) {
CrossBoundaryResult result;
if (!evm_unsafe_try_sub_balance_in_q(result, evmQueueId, HexStr(dst.data), tx.GetHash().GetHex())) {
return DeFiErrors::TransferDomainNotEnoughBalance(EncodeDestination(dest));
}
Expand All @@ -3934,7 +3933,6 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor {
}
}
else {
CrossBoundaryResult result;
evm_try_bridge_dst20(result, evmQueueId, HexStr(dst.data), tx.GetHash().GetHex(), tokenId.v, false);
if (!result.ok) {
return Res::Err("Error bridging DST20: %s", result.reason);
Expand Down
Loading

0 comments on commit 0ec6ec3

Please sign in to comment.