2019-07-08 14:04:52 +00:00
|
|
|
/*
|
|
|
|
This file is part of solidity.
|
|
|
|
|
|
|
|
solidity is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
solidity is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2020-07-17 14:54:12 +00:00
|
|
|
// SPDX-License-Identifier: GPL-3.0
|
2019-07-08 14:04:52 +00:00
|
|
|
/**
|
|
|
|
* EVM execution host, i.e. component that implements a simulated Ethereum blockchain
|
|
|
|
* for testing purposes.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2019-11-21 22:19:37 +00:00
|
|
|
#include <test/evmc/mocked_host.hpp>
|
2019-07-08 14:04:52 +00:00
|
|
|
#include <test/evmc/evmc.hpp>
|
|
|
|
#include <test/evmc/evmc.h>
|
|
|
|
|
|
|
|
#include <liblangutil/EVMVersion.h>
|
|
|
|
|
2020-01-06 10:52:23 +00:00
|
|
|
#include <libsolutil/FixedHash.h>
|
2019-07-08 14:04:52 +00:00
|
|
|
|
2020-06-05 23:10:48 +00:00
|
|
|
#include <boost/filesystem.hpp>
|
|
|
|
|
2019-12-23 15:50:30 +00:00
|
|
|
namespace solidity::test
|
2019-07-08 14:04:52 +00:00
|
|
|
{
|
2019-12-23 15:50:30 +00:00
|
|
|
using Address = util::h160;
|
2022-09-16 10:57:29 +00:00
|
|
|
using StorageMap = std::map<evmc::bytes32, evmc::storage_value>;
|
2019-07-08 14:04:52 +00:00
|
|
|
|
2019-11-21 22:19:37 +00:00
|
|
|
class EVMHost: public evmc::MockedHost
|
2019-07-08 14:04:52 +00:00
|
|
|
{
|
|
|
|
public:
|
2022-09-25 16:22:34 +00:00
|
|
|
// Verbatim features of MockedHost.
|
|
|
|
using MockedHost::account_exists;
|
|
|
|
using MockedHost::get_storage;
|
|
|
|
using MockedHost::set_storage;
|
2019-11-29 23:10:41 +00:00
|
|
|
using MockedHost::get_balance;
|
2022-09-25 16:22:34 +00:00
|
|
|
using MockedHost::get_code_size;
|
|
|
|
using MockedHost::get_code_hash;
|
|
|
|
using MockedHost::copy_code;
|
|
|
|
using MockedHost::get_tx_context;
|
|
|
|
using MockedHost::emit_log;
|
|
|
|
using MockedHost::access_account;
|
|
|
|
using MockedHost::access_storage;
|
|
|
|
|
|
|
|
// Modified features of MockedHost.
|
|
|
|
void selfdestruct(evmc::address const& _addr, evmc::address const& _beneficiary) noexcept final;
|
|
|
|
evmc::result call(evmc_message const& _message) noexcept final;
|
|
|
|
evmc::bytes32 get_block_hash(int64_t number) const noexcept final;
|
|
|
|
|
|
|
|
// Solidity testing specific features.
|
2019-11-29 23:10:41 +00:00
|
|
|
|
2020-06-05 23:10:48 +00:00
|
|
|
/// Tries to dynamically load an evmc vm supporting evm1 or ewasm and caches the loaded VM.
|
|
|
|
/// @returns vmc::VM(nullptr) on failure.
|
2019-11-27 16:37:26 +00:00
|
|
|
static evmc::VM& getVM(std::string const& _path = {});
|
2019-07-16 17:05:13 +00:00
|
|
|
|
2020-06-05 23:10:48 +00:00
|
|
|
/// Tries to load all defined evmc vm shared libraries.
|
|
|
|
/// @param _vmPaths paths to multiple evmc shared libraries.
|
|
|
|
/// @throw Exception if multiple evm1 or multiple ewasm evmc vms where loaded.
|
2021-05-10 15:23:23 +00:00
|
|
|
/// @returns A pair of booleans, the first element being true, if an evmc vm supporting evm1 was loaded properly,
|
|
|
|
/// the second being true, if an evmc vm supporting ewasm was loaded properly.
|
|
|
|
static std::tuple<bool, bool> checkVmPaths(std::vector<boost::filesystem::path> const& _vmPaths);
|
2020-06-05 23:10:48 +00:00
|
|
|
|
|
|
|
explicit EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm);
|
2019-07-08 14:04:52 +00:00
|
|
|
|
2022-09-16 10:57:29 +00:00
|
|
|
/// Reset entire state (including accounts).
|
2020-09-24 17:46:39 +00:00
|
|
|
void reset();
|
2022-09-16 10:57:29 +00:00
|
|
|
|
|
|
|
/// Start new block.
|
2019-07-08 14:04:52 +00:00
|
|
|
void newBlock()
|
|
|
|
{
|
2019-11-28 10:54:57 +00:00
|
|
|
tx_context.block_number++;
|
|
|
|
tx_context.block_timestamp += 15;
|
2019-11-28 10:38:47 +00:00
|
|
|
recorded_logs.clear();
|
2021-05-25 10:32:59 +00:00
|
|
|
resetWarmAccess();
|
2019-07-08 14:04:52 +00:00
|
|
|
}
|
2021-02-04 20:52:07 +00:00
|
|
|
|
2021-02-02 13:08:12 +00:00
|
|
|
/// @returns contents of storage at @param _addr.
|
2022-09-16 10:57:29 +00:00
|
|
|
StorageMap const& get_address_storage(evmc::address const& _addr);
|
2019-07-08 14:04:52 +00:00
|
|
|
|
2019-11-07 10:34:12 +00:00
|
|
|
static Address convertFromEVMC(evmc::address const& _addr);
|
|
|
|
static evmc::address convertToEVMC(Address const& _addr);
|
2019-12-23 15:50:30 +00:00
|
|
|
static util::h256 convertFromEVMC(evmc::bytes32 const& _data);
|
|
|
|
static evmc::bytes32 convertToEVMC(util::h256 const& _data);
|
2019-11-28 12:06:00 +00:00
|
|
|
private:
|
2019-11-07 10:34:12 +00:00
|
|
|
evmc::address m_currentAddress = {};
|
2019-07-08 14:04:52 +00:00
|
|
|
|
2022-09-16 10:57:29 +00:00
|
|
|
/// Transfer value between accounts. Checks for sufficient balance.
|
2021-03-30 21:05:55 +00:00
|
|
|
void transfer(evmc::MockedAccount& _sender, evmc::MockedAccount& _recipient, u256 const& _value) noexcept;
|
|
|
|
|
2022-09-16 10:57:29 +00:00
|
|
|
/// Clears EIP-2929 account and storage access indicator
|
|
|
|
void resetWarmAccess();
|
|
|
|
|
2021-03-05 18:56:43 +00:00
|
|
|
/// Records calls made via @param _message.
|
|
|
|
void recordCalls(evmc_message const& _message) noexcept;
|
|
|
|
|
2019-11-28 12:10:32 +00:00
|
|
|
static evmc::result precompileECRecover(evmc_message const& _message) noexcept;
|
|
|
|
static evmc::result precompileSha256(evmc_message const& _message) noexcept;
|
|
|
|
static evmc::result precompileRipeMD160(evmc_message const& _message) noexcept;
|
|
|
|
static evmc::result precompileIdentity(evmc_message const& _message) noexcept;
|
|
|
|
static evmc::result precompileModExp(evmc_message const& _message) noexcept;
|
|
|
|
static evmc::result precompileALTBN128G1Add(evmc_message const& _message) noexcept;
|
|
|
|
static evmc::result precompileALTBN128G1Mul(evmc_message const& _message) noexcept;
|
|
|
|
static evmc::result precompileALTBN128PairingProduct(evmc_message const& _message) noexcept;
|
|
|
|
static evmc::result precompileGeneric(evmc_message const& _message, std::map<bytes, bytes> const& _inOut) noexcept;
|
2019-07-11 16:46:17 +00:00
|
|
|
/// @returns a result object with no gas usage and result data taken from @a _data.
|
|
|
|
/// @note The return value is only valid as long as @a _data is alive!
|
|
|
|
static evmc::result resultWithGas(evmc_message const& _message, bytes const& _data) noexcept;
|
2022-09-26 18:41:16 +00:00
|
|
|
static evmc::result resultWithFailure() noexcept;
|
2019-07-08 14:04:52 +00:00
|
|
|
|
2019-11-27 16:37:26 +00:00
|
|
|
evmc::VM& m_vm;
|
2022-09-16 10:57:29 +00:00
|
|
|
/// EVM version requested by the testing tool
|
2019-11-07 14:10:08 +00:00
|
|
|
langutil::EVMVersion m_evmVersion;
|
2022-09-16 10:57:29 +00:00
|
|
|
/// EVM version requested from EVMC (matches the above)
|
2019-11-07 14:10:08 +00:00
|
|
|
evmc_revision m_evmRevision;
|
2019-07-08 14:04:52 +00:00
|
|
|
};
|
|
|
|
|
2021-03-10 12:49:19 +00:00
|
|
|
class EVMHostPrinter
|
2021-03-10 11:00:18 +00:00
|
|
|
{
|
2021-03-10 12:49:19 +00:00
|
|
|
public:
|
2021-03-10 11:00:18 +00:00
|
|
|
/// Constructs a host printer object for state at @param _address.
|
|
|
|
explicit EVMHostPrinter(EVMHost& _host, evmc::address _address):
|
2021-03-10 12:49:19 +00:00
|
|
|
m_host(_host),
|
|
|
|
m_account(_address)
|
2021-03-10 11:00:18 +00:00
|
|
|
{}
|
|
|
|
/// @returns state at account maintained by host.
|
|
|
|
std::string state();
|
2021-03-10 12:49:19 +00:00
|
|
|
private:
|
2021-03-10 11:00:18 +00:00
|
|
|
/// Outputs storage at account to stateStream.
|
|
|
|
void storage();
|
|
|
|
/// Outputs call records for account to stateStream.
|
|
|
|
void callRecords();
|
|
|
|
/// Outputs balance of account to stateStream.
|
|
|
|
void balance();
|
|
|
|
/// Outputs self-destruct record for account to stateStream.
|
|
|
|
void selfdestructRecords();
|
|
|
|
|
2021-03-10 12:49:19 +00:00
|
|
|
std::ostringstream m_stateStream;
|
|
|
|
EVMHost& m_host;
|
|
|
|
evmc::address m_account;
|
2021-03-10 11:00:18 +00:00
|
|
|
};
|
2019-07-08 14:04:52 +00:00
|
|
|
|
|
|
|
}
|