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

Add EVM block limit test #2387

Merged
merged 7 commits into from
Aug 28, 2023
Merged
Changes from all 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
7 changes: 6 additions & 1 deletion lib/ain-evm/src/evm.rs
Original file line number Diff line number Diff line change
@@ -151,6 +151,7 @@ impl EVMServices {
block.header.state_root
});

debug!("[construct_block] queue_id: {:?}", queue_id);
debug!("[construct_block] beneficiary: {:?}", beneficiary);
let (vicinity, parent_hash, current_block_number) = match parent_data {
None => (
@@ -211,6 +212,10 @@ impl EVMServices {
executor.update_storage(address, storage)?;
}

debug!(
"[construct_block] Processing {:?} transactions in queue",
queue.transactions.len()
);
for queue_item in queue.transactions.clone() {
match queue_item.tx {
QueueTx::SignedTx(signed_tx) => {
@@ -461,7 +466,7 @@ impl EVMServices {
.core
.get_latest_contract_storage(address, ain_contracts::u256_to_h256(U256::one()))?;

debug!("Count: {:#x}", count + U256::one());
debug!("[counter_contract] count: {:#x}", count + U256::one());

Ok(DeployContractInfo {
address,
12 changes: 12 additions & 0 deletions test/functional/contracts/Loop.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract Loop {
function loop(uint256 num) public {
uint256 number = 0;
while (number < num) {
number++;
}
}
}
145 changes: 141 additions & 4 deletions test/functional/feature_evm.py
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
"""Test EVM behaviour"""
from test_framework.evm_contract import EVMContract
from test_framework.evm_key_pair import EvmKeyPair
from test_framework.test_framework import DefiTestFramework
from test_framework.util import (
@@ -87,6 +88,9 @@ def run_test(self):
# Multiple mempool fee replacement
self.multiple_eth_rbf()

# Multiple mempool fee replacement
self.mempool_block_limit()

# Test that node should not crash without chainId param
self.test_tx_without_chainid()

@@ -134,11 +138,11 @@ def erc55_wallet_support(self):
self.address = self.nodes[0].get_genesis_keys().ownerAuthAddress
self.eth_address = "0x9b8a4af42140d8a4c153a822f02571a1dd037e89"
self.eth_address_bech32 = "bcrt1qta8meuczw0mhqupzjl5wplz47xajz0dn0wxxr8"
eth_address_privkey = (
self.eth_address_privkey = (
"af990cc3ba17e776f7f57fcc59942a82846d75833fa17d2ba59ce6858d886e23"
)
self.to_address = "0x6c34cbb9219d8caa428835d2073e8ec88ba0a110"
to_address_privkey = (
self.to_address_privkey = (
"17b8cb134958b3d8422b6c43b0732fcdb8c713b524df2d45de12f0c7e214ba35"
)

@@ -242,8 +246,8 @@ def erc55_wallet_support(self):
assert_equal(addr_info["witness_version"], 16)

# Import addresses
self.nodes[0].importprivkey(eth_address_privkey) # eth_address
self.nodes[0].importprivkey(to_address_privkey) # self.to_address
self.nodes[0].importprivkey(self.eth_address_privkey) # eth_address
self.nodes[0].importprivkey(self.to_address_privkey) # self.to_address

# Generate chain
self.nodes[0].generate(101)
@@ -1204,6 +1208,139 @@ def multiple_eth_rbf(self):
assert_equal(block_txs[1], tx0)
assert_equal(block_txs[2], tx1)

def mempool_block_limit(self):
abi, bytecode = EVMContract.from_file("Loop.sol", "Loop").compile()
compiled = self.nodes[0].w3.eth.contract(abi=abi, bytecode=bytecode)
tx = compiled.constructor().build_transaction(
{
"chainId": self.nodes[0].w3.eth.chain_id,
"nonce": self.nodes[0].w3.eth.get_transaction_count(self.eth_address),
"maxFeePerGas": 10_000_000_000,
"maxPriorityFeePerGas": 1_500_000_000,
"gas": 1_000_000,
}
)
signed = self.nodes[0].w3.eth.account.sign_transaction(
tx, self.eth_address_privkey
)
hash = self.nodes[0].w3.eth.send_raw_transaction(signed.rawTransaction)
self.nodes[0].generate(1)
receipt = self.nodes[0].w3.eth.wait_for_transaction_receipt(hash)
contract = self.nodes[0].w3.eth.contract(
address=receipt["contractAddress"], abi=abi
)

hashes = []
start_nonce = self.nodes[0].w3.eth.get_transaction_count(self.eth_address)
for i in range(40):
# tx call actual used gas - 1_761_626.
# tx should always pass evm tx validation, but may return early in construct block.
tx = contract.functions.loop(10_000).build_transaction(
{
"chainId": self.nodes[0].w3.eth.chain_id,
"nonce": start_nonce + i,
"gasPrice": 25_000_000_000,
"gas": 30_000_000,
}
)
signed = self.nodes[0].w3.eth.account.sign_transaction(
tx, self.eth_address_privkey
)
hash = self.nodes[0].w3.eth.send_raw_transaction(signed.rawTransaction)
hashes.append(signed.hash.hex().lower()[2:])

hash = self.nodes[0].eth_sendTransaction(
{
"nonce": hex(start_nonce + 40),
"from": self.eth_address,
"to": self.to_address,
"value": "0xDE0B6B3A7640000", # 1 DFI
"gas": "0x5209",
"gasPrice": "0x5D21DBA00", # 25_000_000_000
}
)
hashes.append(hash.lower()[2:])
hash = self.nodes[0].eth_sendTransaction(
{
"nonce": hex(start_nonce + 41),
"from": self.eth_address,
"to": self.to_address,
"value": "0xDE0B6B3A7640000", # 1 DFI
"gas": "0x5209",
"gasPrice": "0x5D21DBA00", # 25_000_000_000
}
)
hashes.append(hash.lower()[2:])

first_block_total_txs = 17
second_block_total_txs = 17
third_block_total_txs = 8

self.nodes[0].generate(1)
block_info = self.nodes[0].getblock(self.nodes[0].getbestblockhash(), 4)
# check that the first 17 evm contract call txs is minted in the current block
assert_equal(len(block_info["tx"]) - 1, first_block_total_txs)
for idx, tx_info in enumerate(block_info["tx"][1:]):
if idx == 0:
continue
assert_equal(tx_info["vm"]["vmtype"], "evm")
assert_equal(tx_info["vm"]["txtype"], "EvmTx")
assert_equal(tx_info["vm"]["msg"]["sender"], self.eth_address)
assert_equal(tx_info["vm"]["msg"]["nonce"], start_nonce + idx)
assert_equal(tx_info["vm"]["msg"]["hash"], hashes[idx])
assert_equal(tx_info["vm"]["msg"]["to"], receipt["contractAddress"].lower())

self.nodes[0].generate(1)
block_info = self.nodes[0].getblock(self.nodes[0].getbestblockhash(), 4)
# check that the next 17 of the evm contract call txs is minted in the next block
assert_equal(len(block_info["tx"]) - 1, second_block_total_txs)
for idx, tx_info in enumerate(block_info["tx"][1:]):
assert_equal(tx_info["vm"]["vmtype"], "evm")
assert_equal(tx_info["vm"]["txtype"], "EvmTx")
assert_equal(tx_info["vm"]["msg"]["sender"], self.eth_address)
assert_equal(
tx_info["vm"]["msg"]["nonce"], start_nonce + first_block_total_txs + idx
)
assert_equal(
tx_info["vm"]["msg"]["hash"], hashes[first_block_total_txs + idx]
)
assert_equal(tx_info["vm"]["msg"]["to"], receipt["contractAddress"].lower())

# check that the remaining evm txs is minted into this block
self.nodes[0].generate(1)
block_info = self.nodes[0].getblock(self.nodes[0].getbestblockhash(), 4)
assert_equal(len(block_info["tx"]) - 1, third_block_total_txs)
# check ordering of evm txs - first 6 evm txs are evm contract all txs
tx_infos = block_info["tx"][1:]
for idx in range(1, (40 - first_block_total_txs - second_block_total_txs)):
assert_equal(tx_infos[idx]["vm"]["vmtype"], "evm")
assert_equal(tx_infos[idx]["vm"]["txtype"], "EvmTx")
assert_equal(tx_infos[idx]["vm"]["msg"]["sender"], self.eth_address)
assert_equal(
tx_infos[idx]["vm"]["msg"]["nonce"],
start_nonce + first_block_total_txs + second_block_total_txs + idx,
)
assert_equal(
tx_infos[idx]["vm"]["msg"]["hash"],
hashes[first_block_total_txs + second_block_total_txs + idx],
)
assert_equal(
tx_infos[idx]["vm"]["msg"]["to"], receipt["contractAddress"].lower()
)
for idx in range(6, third_block_total_txs):
assert_equal(tx_infos[idx]["vm"]["vmtype"], "evm")
assert_equal(tx_infos[idx]["vm"]["txtype"], "EvmTx")
assert_equal(tx_infos[idx]["vm"]["msg"]["sender"], self.eth_address)
assert_equal(
tx_infos[idx]["vm"]["msg"]["nonce"],
start_nonce + first_block_total_txs + second_block_total_txs + idx,
)
assert_equal(
tx_infos[idx]["vm"]["msg"]["hash"],
hashes[first_block_total_txs + second_block_total_txs + idx],
)
assert_equal(tx_infos[idx]["vm"]["msg"]["to"], self.to_address)

def toggle_evm_enablement(self):
# Deactivate EVM
self.nodes[0].setgov({"ATTRIBUTES": {"v0/params/feature/evm": "false"}})