Skip to content

Commit d357940

Browse files
committed
Add test for prestate trace with state override 'state' and 'state diff' parameters
1 parent bf0cbbf commit d357940

File tree

1 file changed

+246
-1
lines changed

1 file changed

+246
-1
lines changed

category/rpc/eth_call_test.cpp

Lines changed: 246 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <category/mpt/db.hpp>
3232
#include <category/mpt/ondisk_db_config.hpp>
3333
#include <category/rpc/eth_call.h>
34+
#include <category/vm/utils/evm-as.hpp>
3435
#include <test_resource_data.h>
3536

3637
#include <boost/fiber/future/promise.hpp>
@@ -1796,4 +1797,248 @@ TEST_F(EthCallFixture, prestate_state_overrides)
17961797

17971798
monad_state_override_destroy(state_override);
17981799
monad_eth_call_executor_destroy(executor);
1799-
}
1800+
}
1801+
1802+
TEST_F(EthCallFixture, prestate_override_state)
1803+
{
1804+
1805+
static constexpr Address CONTRACT_ADDR =
1806+
0xcccccccccccccccccccccccccccccccccccccccc_address;
1807+
1808+
using namespace monad::vm::utils;
1809+
auto eb = evm_as::latest()
1810+
.push(1)
1811+
.sload()
1812+
.push0()
1813+
.sload()
1814+
.add()
1815+
.push0()
1816+
.mstore()
1817+
.push(32)
1818+
.push0()
1819+
.return_();
1820+
std::vector<uint8_t> bytecode_container{};
1821+
ASSERT_TRUE(evm_as::validate(eb));
1822+
evm_as::compile(eb, bytecode_container);
1823+
byte_string_view bytecode_view{
1824+
bytecode_container.data(), bytecode_container.size()};
1825+
auto const code_hash = to_bytes(keccak256(bytecode_view));
1826+
auto const compiled_code = vm::make_shared_intercode(bytecode_view);
1827+
1828+
bytes32_t storage_key = to_bytes(to_big_endian(uint256_t{0}));
1829+
bytes32_t storage_value = to_bytes(to_big_endian(uint256_t{64}));
1830+
1831+
bytes32_t other_storage_key = to_bytes(to_big_endian(uint256_t{1}));
1832+
bytes32_t other_storage_value = to_bytes(to_big_endian(uint256_t{128}));
1833+
1834+
bytes32_t untouched_storage_key = to_bytes(to_big_endian(uint256_t{2}));
1835+
bytes32_t untouched_storage_value = to_bytes(to_big_endian(uint256_t{256}));
1836+
1837+
StateDeltas deltas{
1838+
{CONTRACT_ADDR,
1839+
StateDelta{
1840+
.account =
1841+
AccountDelta{
1842+
std::nullopt,
1843+
Account{
1844+
.balance = 0x0,
1845+
.code_hash = code_hash,
1846+
.nonce = 1,
1847+
}},
1848+
.storage =
1849+
StorageDeltas{{storage_key, {bytes32_t{}, storage_value}}}}}};
1850+
1851+
commit_sequential(
1852+
tdb, deltas, {{code_hash, compiled_code}}, BlockHeader{.number = 0});
1853+
1854+
auto const storage = tdb.read_storage(
1855+
CONTRACT_ADDR,
1856+
Incarnation{0, 0},
1857+
to_bytes(to_big_endian(uint256_t{0})));
1858+
ASSERT_EQ(storage, to_bytes(to_big_endian(uint256_t{uint64_t{64}})));
1859+
1860+
for (uint64_t i = 1; i < 256; ++i) {
1861+
commit_sequential(tdb, {}, {}, BlockHeader{.number = i});
1862+
}
1863+
1864+
static constexpr auto from = Address{};
1865+
1866+
Transaction tx{.gas_limit = 200000u, .to = CONTRACT_ADDR};
1867+
BlockHeader header{.number = 256};
1868+
1869+
commit_sequential(tdb, {}, {}, header);
1870+
1871+
auto const rlp_tx = to_vec(rlp::encode_transaction(tx));
1872+
auto const rlp_header = to_vec(rlp::encode_block_header(header));
1873+
auto const rlp_sender =
1874+
to_vec(rlp::encode_address(std::make_optional(from)));
1875+
auto const rlp_block_id = to_vec(rlp_finalized_id);
1876+
1877+
auto executor = create_executor(dbname.string());
1878+
1879+
// Test 'state' override option. It should wipe the existing and update the
1880+
// given slots.
1881+
struct callback_context ctx_state;
1882+
{
1883+
auto state_override = monad_state_override_create();
1884+
add_override_address(
1885+
state_override, CONTRACT_ADDR.bytes, sizeof(Address));
1886+
set_override_state(
1887+
state_override,
1888+
CONTRACT_ADDR.bytes,
1889+
sizeof(Address),
1890+
other_storage_key.bytes,
1891+
sizeof(bytes32_t),
1892+
other_storage_value.bytes,
1893+
sizeof(bytes32_t));
1894+
set_override_state(
1895+
state_override,
1896+
CONTRACT_ADDR.bytes,
1897+
sizeof(Address),
1898+
untouched_storage_key.bytes,
1899+
sizeof(bytes32_t),
1900+
untouched_storage_value.bytes,
1901+
sizeof(bytes32_t));
1902+
1903+
boost::fibers::future<void> f = ctx_state.promise.get_future();
1904+
monad_eth_call_executor_submit(
1905+
executor,
1906+
CHAIN_CONFIG_MONAD_DEVNET,
1907+
rlp_tx.data(),
1908+
rlp_tx.size(),
1909+
rlp_header.data(),
1910+
rlp_header.size(),
1911+
rlp_sender.data(),
1912+
rlp_sender.size(),
1913+
header.number,
1914+
rlp_block_id.data(),
1915+
rlp_block_id.size(),
1916+
state_override,
1917+
complete_callback,
1918+
(void *)&ctx_state,
1919+
PRESTATE_TRACER,
1920+
true);
1921+
f.get();
1922+
1923+
ASSERT_TRUE(ctx_state.result->status_code == EVMC_SUCCESS);
1924+
ASSERT_EQ(ctx_state.result->output_data_len, sizeof(bytes32_t));
1925+
1926+
bytes32_t result;
1927+
std::memcpy(
1928+
result.bytes, ctx_state.result->output_data, sizeof(bytes32_t));
1929+
1930+
bytes32_t expected = to_bytes(to_big_endian(uint256_t{uint64_t{128}}));
1931+
1932+
EXPECT_EQ(result, expected);
1933+
1934+
std::vector<uint8_t> const encoded_prestate_trace(
1935+
ctx_state.result->encoded_trace,
1936+
ctx_state.result->encoded_trace +
1937+
ctx_state.result->encoded_trace_len);
1938+
1939+
auto const expected_json = R"({
1940+
"0x0000000000000000000000000000000000000000": {
1941+
"balance": "0x0"
1942+
},
1943+
"0xcccccccccccccccccccccccccccccccccccccccc": {
1944+
"balance": "0x0",
1945+
"code": "0x6001545f54015f5260205ff3",
1946+
"nonce": 1,
1947+
"storage": {
1948+
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000000",
1949+
"0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000080"
1950+
}
1951+
}
1952+
})";
1953+
1954+
EXPECT_EQ(
1955+
nlohmann::json::parse(expected_json),
1956+
nlohmann::json::from_cbor(encoded_prestate_trace));
1957+
1958+
monad_state_override_destroy(state_override);
1959+
}
1960+
1961+
// Similar to above, but test state diff override. It should keep existing
1962+
// and update the given slots.
1963+
struct callback_context ctx_statediff;
1964+
{
1965+
auto state_override = monad_state_override_create();
1966+
add_override_address(
1967+
state_override, CONTRACT_ADDR.bytes, sizeof(Address));
1968+
set_override_state_diff(
1969+
state_override,
1970+
CONTRACT_ADDR.bytes,
1971+
sizeof(Address),
1972+
other_storage_key.bytes,
1973+
sizeof(bytes32_t),
1974+
other_storage_value.bytes,
1975+
sizeof(bytes32_t));
1976+
set_override_state_diff(
1977+
state_override,
1978+
CONTRACT_ADDR.bytes,
1979+
sizeof(Address),
1980+
untouched_storage_key.bytes,
1981+
sizeof(bytes32_t),
1982+
untouched_storage_value.bytes,
1983+
sizeof(bytes32_t));
1984+
1985+
boost::fibers::future<void> f = ctx_statediff.promise.get_future();
1986+
monad_eth_call_executor_submit(
1987+
executor,
1988+
CHAIN_CONFIG_MONAD_DEVNET,
1989+
rlp_tx.data(),
1990+
rlp_tx.size(),
1991+
rlp_header.data(),
1992+
rlp_header.size(),
1993+
rlp_sender.data(),
1994+
rlp_sender.size(),
1995+
header.number,
1996+
rlp_block_id.data(),
1997+
rlp_block_id.size(),
1998+
state_override,
1999+
complete_callback,
2000+
(void *)&ctx_statediff,
2001+
PRESTATE_TRACER,
2002+
true);
2003+
f.get();
2004+
2005+
ASSERT_TRUE(ctx_statediff.result->status_code == EVMC_SUCCESS);
2006+
ASSERT_EQ(ctx_statediff.result->output_data_len, sizeof(bytes32_t));
2007+
2008+
bytes32_t result;
2009+
std::memcpy(
2010+
result.bytes, ctx_statediff.result->output_data, sizeof(bytes32_t));
2011+
2012+
bytes32_t expected = to_bytes(to_big_endian(uint256_t{uint64_t{192}}));
2013+
2014+
EXPECT_EQ(result, expected);
2015+
2016+
std::vector<uint8_t> const encoded_prestate_trace(
2017+
ctx_statediff.result->encoded_trace,
2018+
ctx_statediff.result->encoded_trace +
2019+
ctx_statediff.result->encoded_trace_len);
2020+
2021+
auto const expected_json = R"({
2022+
"0x0000000000000000000000000000000000000000": {
2023+
"balance": "0x0"
2024+
},
2025+
"0xcccccccccccccccccccccccccccccccccccccccc": {
2026+
"balance": "0x0",
2027+
"code": "0x6001545f54015f5260205ff3",
2028+
"nonce": 1,
2029+
"storage": {
2030+
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000040",
2031+
"0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000080"
2032+
}
2033+
}
2034+
})";
2035+
2036+
EXPECT_EQ(
2037+
nlohmann::json::parse(expected_json),
2038+
nlohmann::json::from_cbor(encoded_prestate_trace));
2039+
2040+
monad_state_override_destroy(state_override);
2041+
}
2042+
2043+
monad_eth_call_executor_destroy(executor);
2044+
}

0 commit comments

Comments
 (0)