Skip to content

Commit

Permalink
Merge branch 'master' into cuong/add_tests_contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
cuongquangnam authored Sep 4, 2023
2 parents 62ba208 + 97ac254 commit 72975c3
Show file tree
Hide file tree
Showing 15 changed files with 526 additions and 27 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
12 changes: 12 additions & 0 deletions lib/ain-evm/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,11 +584,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 @@ -45,6 +45,7 @@ pub struct FinalizedBlockInfo {
pub total_burnt_fees: U256,
pub total_priority_fees: U256,
pub block_number: U256,
pub state_root: XHash,
}

pub struct DeployContractInfo {
Expand Down Expand Up @@ -370,6 +371,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 @@ -378,6 +380,7 @@ impl EVMServices {
total_burnt_fees,
total_priority_fees,
block_number: current_block_number,
state_root: new_state_root,
})
}

Expand Down Expand Up @@ -619,6 +622,19 @@ impl EVMServices {
Ok(is_queued)
}

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 bytecode = ain_contracts::get_system_reserved_bytecode()?;
let addresses = (1..=1024)
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 @@ -105,6 +105,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 @@ -488,6 +528,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 @@ -508,6 +549,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 @@ -667,6 +709,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 @@ -860,7 +926,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 @@ -82,6 +82,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 @@ -99,6 +100,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 @@ -210,5 +217,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
7 changes: 3 additions & 4 deletions src/masternodes/mn_checks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1064,7 +1064,7 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor {
return Res::Err("tx not from foundation member");
}

if (static_cast<int>(height) >= consensus.BayfrontHeight) {
if (static_cast<int>(height) >= consensus.BayfrontHeight) {
if (token.IsPoolShare()) {
return Res::Err("Can't manually create 'Liquidity Pool Share' token; use poolpair creation");
}
Expand Down Expand Up @@ -3900,7 +3900,7 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor {
ExtractDestination(dst.address, dest);
const auto toAddress = std::get<WitnessV16EthHash>(dest);

// Safety: Safe since validate checks for < 0
// Safety: Safe since validate checks for < 0
const auto balanceIn = static_cast<uint64_t>(dst.amount.nValue);
auto tokenId = dst.amount.nTokenId;
CrossBoundaryResult result;
Expand All @@ -3911,7 +3911,6 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor {
}
}
else {
CrossBoundaryResult result;
evm_try_bridge_dst20(result, evmQueueId, toAddress.ToHexString(), balanceIn, tx.GetHash().GetHex(), tokenId.v, false);
if (!result.ok) {
return Res::Err("Error bridging DST20: %s", result.reason);
Expand All @@ -3926,7 +3925,7 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor {
ExtractDestination(src.address, dest);
const auto fromAddress = std::get<WitnessV16EthHash>(dest);

// Safety: Safe since validate checks for < 0
// Safety: Safe since validate checks for < 0
const auto balanceIn = static_cast<uint64_t>(src.amount.nValue);
auto tokenId = dst.amount.nTokenId;
if (tokenId == DCT_ID{0}) {
Expand Down
Loading

0 comments on commit 72975c3

Please sign in to comment.