mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #7010 from ethereum/useevmone
Use evmone for testing.
This commit is contained in:
commit
18ffe3b3ad
@ -282,7 +282,7 @@ jobs:
|
||||
at: build
|
||||
- run:
|
||||
name: "soltest: Syntax Tests"
|
||||
command: build/test/soltest -t 'syntaxTest*' -- --no-ipc --testpath test
|
||||
command: build/test/soltest -t 'syntaxTest*' -- --testpath test
|
||||
- run:
|
||||
name: "Code Coverage: Syntax Tests"
|
||||
command: codecov --flags syntax --gcov-root build
|
||||
@ -478,7 +478,6 @@ jobs:
|
||||
environment:
|
||||
EVM: constantinople
|
||||
OPTIMIZE: 0
|
||||
SOLTEST_IPC: 0
|
||||
ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2
|
||||
|
||||
t_ubu_homestead:
|
||||
|
@ -46,15 +46,6 @@ RUN set -ex; \
|
||||
|
||||
FROM base AS libraries
|
||||
|
||||
# Aleth for end-to-end tests
|
||||
ARG ALETH_VERSION="1.6.0"
|
||||
ARG ALETH_HASH="7f7004e1563299bc57882e32b32e4a195747dfb6"
|
||||
ARG ALETH_URL="https://github.com/ethereum/aleth/releases/download/v${ALETH_VERSION}/aleth-${ALETH_VERSION}-linux-x86_64.tar.gz"
|
||||
RUN set -ex; \
|
||||
wget -q -O /tmp/aleth.tar.gz "${ALETH_URL}"; \
|
||||
test "$(shasum /tmp/aleth.tar.gz)" = "$ALETH_HASH /tmp/aleth.tar.gz"; \
|
||||
tar -xf /tmp/aleth.tar.gz -C /usr
|
||||
|
||||
# Z3
|
||||
RUN set -ex; \
|
||||
git clone --depth=1 --branch="Z3-4.8.5" https://github.com/Z3Prover/z3.git /usr/src/z3; \
|
||||
|
@ -36,27 +36,17 @@ set -e
|
||||
OPTIMIZE=${OPTIMIZE:-"0"}
|
||||
EVM=${EVM:-"invalid"}
|
||||
WORKDIR=${CIRCLE_WORKING_DIRECTORY:-.}
|
||||
SOLTEST_IPC=${SOLTEST_IPC:-1}
|
||||
REPODIR="$(realpath $(dirname $0)/..)"
|
||||
ALETH_PATH="/usr/bin/aleth"
|
||||
|
||||
source "${REPODIR}/scripts/common.sh"
|
||||
# Test result output directory (CircleCI is reading test results from here)
|
||||
mkdir -p test_results
|
||||
|
||||
ALETH_PID=$(run_aleth)
|
||||
|
||||
function cleanup() {
|
||||
safe_kill $ALETH_PID $ALETH_PATH
|
||||
}
|
||||
trap cleanup INT TERM
|
||||
|
||||
# in case we run with ASAN enabled, we must increase stck size.
|
||||
ulimit -s 16384
|
||||
|
||||
BOOST_TEST_ARGS="--color_output=no --show_progress=yes --logger=JUNIT,error,test_results/$EVM.xml"
|
||||
SOLTEST_ARGS="--evm-version=$EVM --ipcpath "${WORKDIR}/geth.ipc" $flags"
|
||||
test "${SOLTEST_IPC}" = "1" || SOLTEST_ARGS="$SOLTEST_ARGS --no-ipc"
|
||||
SOLTEST_ARGS="--evm-version=$EVM --evmonepath /usr/lib/libevmone.so $flags"
|
||||
test "${OPTIMIZE}" = "1" && SOLTEST_ARGS="${SOLTEST_ARGS} --optimize"
|
||||
test "${ABI_ENCODER_V2}" = "1" && SOLTEST_ARGS="${SOLTEST_ARGS} --abiencoderv2 --optimize-yul"
|
||||
|
||||
|
@ -5,9 +5,6 @@
|
||||
#
|
||||
# http://solidity.readthedocs.org
|
||||
#
|
||||
# TODO - Tests currently disabled, because Tests-over-IPC code is using UNIX
|
||||
# sockets unconditionally at the time of writing.
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# This file is part of solidity.
|
||||
#
|
||||
@ -71,7 +68,7 @@ build_script:
|
||||
|
||||
test_script:
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\build\test\%CONFIGURATION%
|
||||
- soltest.exe --show-progress -- --testpath %APPVEYOR_BUILD_FOLDER%\test --no-ipc --no-smt
|
||||
- soltest.exe --show-progress -- --testpath %APPVEYOR_BUILD_FOLDER%\test --no-smt
|
||||
# Skip bytecode compare if private key is not available
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
- ps: if ($env:priv_key) {
|
||||
|
@ -81,15 +81,23 @@ Thank you for your help!
|
||||
Running the compiler tests
|
||||
==========================
|
||||
|
||||
The ``./scripts/tests.sh`` script executes most Solidity tests and
|
||||
runs ``aleth`` automatically if it is in the path. The script does not download it,
|
||||
so you need to install it first. Please read on for the details.
|
||||
The ``./scripts/tests.sh`` script executes most Solidity tests automatically,
|
||||
but for quicker feedback, you might want to run specific tests.
|
||||
|
||||
Solidity includes different types of tests, most of them bundled into the `Boost C++ Test Framework <https://www.boost.org/doc/libs/1_69_0/libs/test/doc/html/index.html>`_ application ``soltest``.
|
||||
Some of them require the ``aleth`` client in testing mode, others require ``libz3``.
|
||||
Solidity includes different types of tests, most of them bundled into the
|
||||
`Boost C++ Test Framework <https://www.boost.org/doc/libs/1_69_0/libs/test/doc/html/index.html>`_ application ``soltest``.
|
||||
Running ``build/test/soltest` or its wrapper ``scripts/soltest.sh`` is sufficient for most changes.
|
||||
|
||||
To run a basic set of tests that require neither ``aleth`` nor ``libz3``, run
|
||||
``./scripts/soltest.sh --no-ipc --no-smt``.
|
||||
Some tests require the ``libevmone.so`` library, others require ``libz3``.
|
||||
|
||||
The test system will automatically try to discover the location of ``libevmone.so``
|
||||
starting from the current directory. If it does not find it, the relevant tests
|
||||
are skipped. To run all tests, download the library from
|
||||
`Github <https://github.com/ethereum/evmone/releases/download/v0.1.0/evmone-0.1.0-linux-x86_64.tar.gz>`_
|
||||
and either place it in the project root path or inside the ``deps`` folder.
|
||||
|
||||
If you do not have libz3 installed on your system, you should disable the SMT tests:
|
||||
``./scripts/soltest.sh --no-smt``.
|
||||
|
||||
``./build/test/soltest --help`` has extensive help on all of the options available.
|
||||
See especially:
|
||||
@ -100,27 +108,19 @@ See especially:
|
||||
|
||||
.. note ::
|
||||
|
||||
Those working in a Windows environment wanting to run the above basic sets without aleth or libz3 in Git Bash, you would have to do: ``./build/test/Release/soltest.exe -- --no-ipc --no-smt``.
|
||||
If you're running this in plain Command Prompt, use ``.\build\test\Release\soltest.exe -- --no-ipc --no-smt``.
|
||||
|
||||
The option ``--no-smt`` disables the tests that require ``libz3`` and
|
||||
``--no-ipc`` disables those that require ``aleth``.
|
||||
|
||||
If you want to run the ipc tests (that test the semantics of the generated code),
|
||||
you need to install `aleth <https://github.com/ethereum/aleth/releases/download/v1.6.0/aleth-1.6.0-linux-x86_64.tar.gz>`_ and run it in testing mode: ``aleth --db memorydb --test -d /tmp/testeth``.
|
||||
|
||||
To run the actual tests, use: ``./scripts/soltest.sh --ipcpath /tmp/testeth/geth.ipc``.
|
||||
Those working in a Windows environment wanting to run the above basic sets without libz3 in Git Bash, you would have to do: ``./build/test/Release/soltest.exe -- --no-smt``.
|
||||
If you are running this in plain Command Prompt, use ``.\build\test\Release\soltest.exe -- --no-smt``.
|
||||
|
||||
To run a subset of tests, you can use filters:
|
||||
``./scripts/soltest.sh -t TestSuite/TestName --ipcpath /tmp/testeth/geth.ipc``,
|
||||
``./scripts/soltest.sh -t TestSuite/TestName,
|
||||
where ``TestName`` can be a wildcard ``*``.
|
||||
|
||||
For example, here's an example test you might run;
|
||||
``./scripts/soltest.sh -t "yulOptimizerTests/disambiguator/*" --no-ipc --no-smt``.
|
||||
For example, here is an example test you might run;
|
||||
``./scripts/soltest.sh -t "yulOptimizerTests/disambiguator/*" --no-smt``.
|
||||
This will test all the tests for the disambiguator.
|
||||
|
||||
To get a list of all tests, use
|
||||
``./build/test/soltest --list_content=HRF -- --ipcpath /tmp/irrelevant``.
|
||||
``./build/test/soltest --list_content=HRF``.
|
||||
|
||||
If you want to debug using GDB, make sure you build differently than the "usual".
|
||||
For example, you could run the following command in your ``build`` folder:
|
||||
@ -137,11 +137,6 @@ in addition to those found in ``soltest``.
|
||||
|
||||
The CI runs additional tests (including ``solc-js`` and testing third party Solidity frameworks) that require compiling the Emscripten target.
|
||||
|
||||
.. note ::
|
||||
|
||||
Some versions of ``aleth`` can not be used for testing. We suggest using
|
||||
the same version that the Solidity continuous integration tests use.
|
||||
Currently the CI uses version ``1.6.0`` of ``aleth``.
|
||||
|
||||
Writing and running syntax tests
|
||||
--------------------------------
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
/// Operators need to stay in the global namespace.
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
ALETH_PATH=$1
|
||||
ALETH_TMP_OUT=$2
|
||||
shift
|
||||
shift
|
||||
|
||||
|
||||
$ALETH_PATH $@ &> >(tail -n 100000 &> "$ALETH_TMP_OUT") &
|
||||
|
||||
PID=$!
|
||||
|
||||
function cleanup()
|
||||
{
|
||||
kill $PID
|
||||
}
|
||||
|
||||
trap cleanup INT TERM
|
||||
|
||||
wait $PID
|
||||
|
@ -55,42 +55,3 @@ safe_kill()
|
||||
kill -9 $PID
|
||||
fi
|
||||
}
|
||||
|
||||
# Ensures aleth executable and exposes the following information:
|
||||
#
|
||||
# - env var ALETH_PATH: to point to the aleth executable.
|
||||
# - directory /tmp/test if needed. No cleanup is done on this directory
|
||||
function download_aleth()
|
||||
{
|
||||
if which aleth &>/dev/null; then
|
||||
ALETH_PATH=`which aleth`
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
ALETH_PATH="$(realpath $(dirname "$0")/..)/aleth"
|
||||
elif [ "$CIRCLECI" ] || [ -z $CI ]; then
|
||||
ALETH_PATH="aleth"
|
||||
else
|
||||
ALETH_PATH="/tmp/test/bin/aleth"
|
||||
mkdir -p /tmp/test
|
||||
# Any time the hash is updated here, the "Running the compiler tests" section in contributing.rst should also be updated.
|
||||
local ALETH_HASH="7f7004e1563299bc57882e32b32e4a195747dfb6"
|
||||
local ALETH_VERSION="1.6.0"
|
||||
wget -q -O /tmp/test/aleth.tar.gz https://github.com/ethereum/aleth/releases/download/v${ALETH_VERSION}/aleth-${ALETH_VERSION}-linux-x86_64.tar.gz
|
||||
test "$(shasum /tmp/test/aleth.tar.gz)" = "$ALETH_HASH /tmp/test/aleth.tar.gz"
|
||||
tar -xf /tmp/test/aleth.tar.gz -C /tmp/test
|
||||
sync
|
||||
chmod +x $ALETH_PATH
|
||||
sync # Otherwise we might get a "text file busy" error
|
||||
fi
|
||||
}
|
||||
|
||||
# Executes aleth in the background and echos its PID.
|
||||
function run_aleth()
|
||||
{
|
||||
$ALETH_PATH --db memorydb --test -d "${WORKDIR}" &> /dev/null &
|
||||
echo $!
|
||||
|
||||
# Wait until the IPC endpoint is available.
|
||||
while [ ! -S "${WORKDIR}/geth.ipc" ] ; do sleep 1; done
|
||||
sleep 2
|
||||
}
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Script to build the eth binary from latest develop
|
||||
# for ubuntu trusty and ubuntu artful.
|
||||
# Requires docker.
|
||||
|
||||
set -e
|
||||
|
||||
REPO_ROOT="$(dirname "$0")"/../..
|
||||
|
||||
for rel in artful trusty
|
||||
do
|
||||
docker build -t eth_$rel -f "$REPO_ROOT"/scripts/cpp-ethereum/eth_$rel.docker .
|
||||
tmp_container=$(docker create eth_$rel sh)
|
||||
echo "Built eth ($rel) at $REPO_ROOT/build/eth_$rel"
|
||||
docker cp ${tmp_container}:/build/eth/eth "$REPO_ROOT"/build/eth_$rel
|
||||
done
|
@ -1,7 +0,0 @@
|
||||
FROM ubuntu:artful
|
||||
|
||||
RUN apt update
|
||||
RUN apt -y install libleveldb-dev cmake g++ git
|
||||
RUN git clone --recursive https://github.com/ethereum/cpp-ethereum --branch develop --single-branch --depth 1
|
||||
RUN mkdir /build && cd /build && cmake /cpp-ethereum -DCMAKE_BUILD_TYPE=RelWithDebInfo -DTOOLS=Off -DTESTS=Off
|
||||
RUN cd /build && make eth
|
@ -1,13 +0,0 @@
|
||||
FROM ubuntu:trusty
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get -y install software-properties-common python-software-properties
|
||||
RUN add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||
RUN apt-get update
|
||||
RUN apt-get -y install gcc libleveldb-dev git curl make gcc-7 g++-7
|
||||
RUN ln -sf /usr/bin/gcc-7 /usr/bin/gcc
|
||||
RUN ln -sf /usr/bin/g++-7 /usr/bin/g++
|
||||
RUN git clone --recursive https://github.com/ethereum/cpp-ethereum --branch develop --single-branch --depth 1
|
||||
RUN ./cpp-ethereum/scripts/install_cmake.sh
|
||||
RUN mkdir /build && cd /build && ~/.local/bin/cmake /cpp-ethereum -DCMAKE_BUILD_TYPE=RelWithDebInfo -DTOOLS=Off -DTESTS=Off
|
||||
RUN cd /build && make eth
|
@ -104,9 +104,6 @@ case $(uname -s) in
|
||||
brew install cmake
|
||||
if [ "$CI" = true ]; then
|
||||
brew upgrade cmake
|
||||
brew tap ethereum/ethereum
|
||||
brew install cpp-ethereum
|
||||
brew linkapps cpp-ethereum
|
||||
else
|
||||
brew upgrade
|
||||
fi
|
||||
@ -337,13 +334,6 @@ case $(uname -s) in
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install libz3-dev
|
||||
fi
|
||||
|
||||
# Install 'eth', for use in the Solidity Tests-over-IPC.
|
||||
# We will not use this 'eth', but its dependencies
|
||||
sudo add-apt-repository -y ppa:ethereum/ethereum
|
||||
sudo add-apt-repository -y ppa:ethereum/ethereum-dev
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install eth
|
||||
fi
|
||||
;;
|
||||
|
||||
|
@ -33,10 +33,6 @@ REPO_ROOT="$(dirname "$0")/.."
|
||||
source "${REPO_ROOT}/scripts/common.sh"
|
||||
|
||||
WORKDIR=`mktemp -d`
|
||||
# Will be printed in case of a test failure
|
||||
ALETH_TMP_OUT=`mktemp`
|
||||
IPC_ENABLED=true
|
||||
ALETH_PID=
|
||||
CMDLINE_PID=
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]
|
||||
@ -48,10 +44,6 @@ cleanup() {
|
||||
# ensure failing commands don't cause termination during cleanup (especially within safe_kill)
|
||||
set +e
|
||||
|
||||
if [[ "$IPC_ENABLED" = true ]] && [[ -n "${ALETH_PID}" ]]
|
||||
then
|
||||
safe_kill $ALETH_PID $ALETH_PATH
|
||||
fi
|
||||
if [[ -n "$CMDLINE_PID" ]]
|
||||
then
|
||||
safe_kill $CMDLINE_PID "Commandline tests"
|
||||
@ -59,7 +51,6 @@ cleanup() {
|
||||
|
||||
echo "Cleaning up working directory ${WORKDIR} ..."
|
||||
rm -rf "$WORKDIR" || true
|
||||
rm $ALETH_TMP_OUT
|
||||
}
|
||||
trap cleanup INT TERM
|
||||
|
||||
@ -89,20 +80,6 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
function check_aleth() {
|
||||
printTask "Running IPC tests with $ALETH_PATH..."
|
||||
if ! hash $ALETH_PATH 2>/dev/null; then
|
||||
printError "$ALETH_PATH not found"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$IPC_ENABLED" = true ];
|
||||
then
|
||||
download_aleth
|
||||
check_aleth
|
||||
ALETH_PID=$(run_aleth)
|
||||
fi
|
||||
|
||||
EVM_VERSIONS="homestead byzantium"
|
||||
|
||||
@ -112,7 +89,7 @@ then
|
||||
fi
|
||||
|
||||
# And then run the Solidity unit-tests in the matrix combination of optimizer / no optimizer
|
||||
# and homestead / byzantium VM, # pointing to that IPC endpoint.
|
||||
# and homestead / byzantium VM
|
||||
for optimize in "" "--optimize"
|
||||
do
|
||||
for vm in $EVM_VERSIONS
|
||||
@ -143,16 +120,9 @@ do
|
||||
fi
|
||||
|
||||
set +e
|
||||
"$REPO_ROOT"/build/test/soltest --show-progress $log -- --testpath "$REPO_ROOT"/test "$optimize" --evm-version "$vm" $SMT_FLAGS $IPC_FLAGS $force_abiv2_flag --ipcpath "${WORKDIR}/geth.ipc"
|
||||
"$REPO_ROOT"/build/test/soltest --show-progress $log -- --testpath "$REPO_ROOT"/test "$optimize" --evm-version "$vm" $SMT_FLAGS $force_abiv2_flag
|
||||
|
||||
if test "0" -ne "$?"; then
|
||||
if [ -n "$log_directory" ]
|
||||
then
|
||||
# Need to kill aleth first so the log is written
|
||||
safe_kill $ALETH_PID $ALETH_PATH
|
||||
cp $ALETH_TMP_OUT $log_directory/aleth.log
|
||||
printError "Some test failed, wrote aleth.log"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
set -e
|
||||
|
@ -57,15 +57,30 @@ boost::filesystem::path testPath()
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string IPCEnvOrDefaultPath()
|
||||
std::string EVMOneEnvOrDefaultPath()
|
||||
{
|
||||
if (auto path = getenv("ETH_TEST_IPC"))
|
||||
if (auto path = getenv("ETH_EVMONE"))
|
||||
return path;
|
||||
|
||||
if (auto home = getenv("HOME"))
|
||||
return std::string(home) + "/.ethereum/geth.ipc";
|
||||
|
||||
return std::string{};
|
||||
auto const searchPath =
|
||||
{
|
||||
fs::path("/usr/local/lib"),
|
||||
fs::path("/usr/lib"),
|
||||
fs::current_path() / "deps",
|
||||
fs::current_path() / "deps" / "lib",
|
||||
fs::current_path() / ".." / "deps",
|
||||
fs::current_path() / ".." / "deps" / "lib",
|
||||
fs::current_path() / ".." / ".." / "deps",
|
||||
fs::current_path() / ".." / ".." / "deps" / "lib",
|
||||
fs::current_path()
|
||||
};
|
||||
for (auto const& basePath: searchPath)
|
||||
{
|
||||
fs::path p = basePath / "libevmone.so";
|
||||
if (fs::exists(p))
|
||||
return p.string();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
CommonOptions::CommonOptions(std::string _caption):
|
||||
@ -77,8 +92,7 @@ CommonOptions::CommonOptions(std::string _caption):
|
||||
options.add_options()
|
||||
("evm-version", po::value(&evmVersionString), "which evm version to use")
|
||||
("testpath", po::value<fs::path>(&this->testPath)->default_value(dev::test::testPath()), "path to test files")
|
||||
("ipcpath", po::value<fs::path>(&ipcPath)->default_value(IPCEnvOrDefaultPath()), "path to ipc socket")
|
||||
("no-ipc", po::bool_switch(&disableIPC), "disable semantic tests")
|
||||
("evmonepath", po::value<fs::path>(&evmonePath)->default_value(EVMOneEnvOrDefaultPath()), "path to libevmone.so")
|
||||
("no-smt", po::bool_switch(&disableSMT), "disable SMT checker");
|
||||
}
|
||||
|
||||
@ -95,19 +109,6 @@ void CommonOptions::validate() const
|
||||
"Invalid test path specified."
|
||||
);
|
||||
|
||||
if (!disableIPC)
|
||||
{
|
||||
assertThrow(
|
||||
!ipcPath.empty(),
|
||||
ConfigException,
|
||||
"No ipc path specified. The --ipcpath argument must not be empty when given."
|
||||
);
|
||||
assertThrow(
|
||||
fs::exists(ipcPath),
|
||||
ConfigException,
|
||||
"Invalid ipc path specified."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool CommonOptions::parse(int argc, char const* const* argv)
|
||||
|
@ -34,11 +34,10 @@ struct ConfigException : public Exception {};
|
||||
|
||||
struct CommonOptions: boost::noncopyable
|
||||
{
|
||||
boost::filesystem::path ipcPath;
|
||||
boost::filesystem::path evmonePath;
|
||||
boost::filesystem::path testPath;
|
||||
bool optimize = false;
|
||||
bool optimizeYul = false;
|
||||
bool disableIPC = false;
|
||||
bool disableSMT = false;
|
||||
|
||||
langutil::EVMVersion evmVersion() const;
|
||||
|
510
test/EVMHost.cpp
510
test/EVMHost.cpp
@ -24,6 +24,8 @@
|
||||
#include <test/evmc/helpers.hpp>
|
||||
#include <test/evmc/loader.h>
|
||||
|
||||
#include <libevmasm/GasMeter.h>
|
||||
|
||||
#include <libdevcore/Exceptions.h>
|
||||
#include <libdevcore/Assertions.h>
|
||||
#include <libdevcore/Keccak256.h>
|
||||
@ -33,9 +35,36 @@ using namespace std;
|
||||
using namespace dev;
|
||||
using namespace dev::test;
|
||||
|
||||
EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::vm& _vmInstance):
|
||||
m_vm(_vmInstance)
|
||||
|
||||
evmc::vm* EVMHost::getVM(string const& _path)
|
||||
{
|
||||
static unique_ptr<evmc::vm> theVM;
|
||||
if (!theVM && !_path.empty())
|
||||
{
|
||||
evmc_loader_error_code errorCode = {};
|
||||
evmc_instance* vm = evmc_load_and_create(_path.c_str(), &errorCode);
|
||||
if (vm && errorCode == EVMC_LOADER_SUCCESS)
|
||||
theVM = make_unique<evmc::vm>(vm);
|
||||
else
|
||||
{
|
||||
cerr << "Error loading VM from " << _path;
|
||||
if (char const* errorMsg = evmc_last_error_msg())
|
||||
cerr << ":" << endl << errorMsg;
|
||||
cerr << endl;
|
||||
}
|
||||
}
|
||||
return theVM.get();
|
||||
}
|
||||
|
||||
EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::vm* _vm):
|
||||
m_vm(_vm)
|
||||
{
|
||||
if (!m_vm)
|
||||
{
|
||||
cerr << "Unable to find library libevmone.so" << endl;
|
||||
assertThrow(false, Exception, "");
|
||||
}
|
||||
|
||||
if (_evmVersion == langutil::EVMVersion::homestead())
|
||||
m_evmVersion = EVMC_HOMESTEAD;
|
||||
else if (_evmVersion == langutil::EVMVersion::tangerineWhistle())
|
||||
@ -77,8 +106,22 @@ void EVMHost::selfdestruct(const evmc_address& _addr, const evmc_address& _benef
|
||||
|
||||
evmc::result EVMHost::call(evmc_message const& _message) noexcept
|
||||
{
|
||||
if (_message.destination == convertToEVMC(Address(2)))
|
||||
if (_message.destination == convertToEVMC(Address(1)))
|
||||
return precompileECRecover(_message);
|
||||
else if (_message.destination == convertToEVMC(Address(2)))
|
||||
return precompileSha256(_message);
|
||||
else if (_message.destination == convertToEVMC(Address(3)))
|
||||
return precompileRipeMD160(_message);
|
||||
else if (_message.destination == convertToEVMC(Address(4)))
|
||||
return precompileIdentity(_message);
|
||||
else if (_message.destination == convertToEVMC(Address(5)))
|
||||
return precompileModExp(_message);
|
||||
else if (_message.destination == convertToEVMC(Address(6)))
|
||||
return precompileALTBN128G1Add(_message);
|
||||
else if (_message.destination == convertToEVMC(Address(7)))
|
||||
return precompileALTBN128G1Mul(_message);
|
||||
else if (_message.destination == convertToEVMC(Address(8)))
|
||||
return precompileALTBN128PairingProduct(_message);
|
||||
|
||||
State stateBackup = m_state;
|
||||
|
||||
@ -88,6 +131,20 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
|
||||
bytes code;
|
||||
|
||||
evmc_message message = _message;
|
||||
if (message.depth == 0)
|
||||
{
|
||||
message.gas -= message.kind == EVMC_CREATE ? eth::GasCosts::txCreateGas : eth::GasCosts::txGas;
|
||||
for (size_t i = 0; i < message.input_size; ++i)
|
||||
message.gas -= message.input_data[i] == 0 ? eth::GasCosts::txDataZeroGas : eth::GasCosts::txDataNonZeroGas;
|
||||
if (message.gas < 0)
|
||||
{
|
||||
evmc::result result({});
|
||||
result.status_code = EVMC_OUT_OF_GAS;
|
||||
m_state = stateBackup;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (message.kind == EVMC_CREATE)
|
||||
{
|
||||
// TODO this is not the right formula
|
||||
@ -123,17 +180,28 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
|
||||
|
||||
evmc_address currentAddress = m_currentAddress;
|
||||
m_currentAddress = message.destination;
|
||||
evmc::result result = m_vm.execute(*this, m_evmVersion, message, code.data(), code.size());
|
||||
evmc::result result = m_vm->execute(*this, m_evmVersion, message, code.data(), code.size());
|
||||
m_currentAddress = currentAddress;
|
||||
|
||||
if (message.kind == EVMC_CREATE)
|
||||
{
|
||||
result.gas_left -= eth::GasCosts::createDataGas * result.output_size;
|
||||
if (result.gas_left < 0)
|
||||
{
|
||||
result.gas_left = 0;
|
||||
result.status_code = EVMC_OUT_OF_GAS;
|
||||
// TODO clear some fields?
|
||||
}
|
||||
else
|
||||
{
|
||||
result.create_address = message.destination;
|
||||
destination.code = bytes(result.output_data, result.output_data + result.output_size);
|
||||
destination.codeHash = convertToEVMC(keccak256(destination.code));
|
||||
}
|
||||
}
|
||||
|
||||
if (result.status_code != EVMC_SUCCESS)
|
||||
m_state = stateBackup;
|
||||
else if (message.kind == EVMC_CREATE)
|
||||
{
|
||||
result.create_address = message.destination;
|
||||
destination.code = bytes(result.output_data, result.output_data + result.output_size);
|
||||
destination.codeHash = convertToEVMC(keccak256(destination.code));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -199,6 +267,35 @@ evmc_bytes32 EVMHost::convertToEVMC(h256 const& _data)
|
||||
return d;
|
||||
}
|
||||
|
||||
evmc::result EVMHost::precompileECRecover(evmc_message const& _message) noexcept
|
||||
{
|
||||
// NOTE this is a partial implementation for some inputs.
|
||||
static map<bytes, bytes> const inputOutput{
|
||||
{
|
||||
fromHex(
|
||||
"18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c"
|
||||
"000000000000000000000000000000000000000000000000000000000000001c"
|
||||
"73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f"
|
||||
"eeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549"
|
||||
),
|
||||
fromHex("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b")
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"
|
||||
"000000000000000000000000000000000000000000000000000000000000001c"
|
||||
"debaaa0cddb321b2dcaaf846d39605de7b97e77ba6106587855b9106cb104215"
|
||||
"61a22d94fa8b8a687ff9c911c844d1c016d1a685a9166858f9c7c1bc85128aca"
|
||||
),
|
||||
fromHex("0000000000000000000000008743523d96a1b2cbe0c6909653a56da18ed484af")
|
||||
}
|
||||
};
|
||||
evmc::result result = precompileGeneric(_message, inputOutput);
|
||||
result.status_code = EVMC_SUCCESS;
|
||||
result.gas_left = _message.gas;
|
||||
return result;
|
||||
}
|
||||
|
||||
evmc::result EVMHost::precompileSha256(evmc_message const& _message) noexcept
|
||||
{
|
||||
// static data so that we do not need a release routine...
|
||||
@ -209,7 +306,400 @@ evmc::result EVMHost::precompileSha256(evmc_message const& _message) noexcept
|
||||
));
|
||||
|
||||
evmc::result result({});
|
||||
result.gas_left = _message.gas;
|
||||
result.output_data = hash.data();
|
||||
result.output_size = hash.size();
|
||||
return result;
|
||||
}
|
||||
|
||||
evmc::result EVMHost::precompileRipeMD160(evmc_message const& _message) noexcept
|
||||
{
|
||||
// NOTE this is a partial implementation for some inputs.
|
||||
static map<bytes, bytes> const inputOutput{
|
||||
{
|
||||
bytes{},
|
||||
fromHex("0000000000000000000000009c1185a5c5e9fc54612808977ee8f548b2258d31")
|
||||
},
|
||||
{
|
||||
fromHex("0000000000000000000000000000000000000000000000000000000000000004"),
|
||||
fromHex("0000000000000000000000001b0f3c404d12075c68c938f9f60ebea4f74941a0")
|
||||
},
|
||||
{
|
||||
fromHex("0000000000000000000000000000000000000000000000000000000000000005"),
|
||||
fromHex("000000000000000000000000ee54aa84fc32d8fed5a5fe160442ae84626829d9")
|
||||
},
|
||||
{
|
||||
fromHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
fromHex("0000000000000000000000001cf4e77f5966e13e109703cd8a0df7ceda7f3dc3")
|
||||
},
|
||||
{
|
||||
fromHex("0000000000000000000000000000000000000000000000000000000000000000"),
|
||||
fromHex("000000000000000000000000f93175303eba2a7b372174fc9330237f5ad202fc")
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"0800000000000000000000000000000000000000000000000000000000000000"
|
||||
"0401000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000400000000000000000000000000000000000000000000000000000000"
|
||||
"00000100"
|
||||
),
|
||||
fromHex("000000000000000000000000f93175303eba2a7b372174fc9330237f5ad202fc")
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"0800000000000000000000000000000000000000000000000000000000000000"
|
||||
"0501000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000500000000000000000000000000000000000000000000000000000000"
|
||||
"00000100"
|
||||
),
|
||||
fromHex("0000000000000000000000004f4fc112e2bfbe0d38f896a46629e08e2fcfad5")
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
"ff010000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
"ffffffff00000000000000000000000000000000000000000000000000000000"
|
||||
"00000100"
|
||||
),
|
||||
fromHex("000000000000000000000000c0a2e4b1f3ff766a9a0089e7a410391730872495")
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"6162636465666768696a6b6c6d6e6f707172737475767778797a414243444546"
|
||||
"4748494a4b4c4d4e4f505152535455565758595a303132333435363738393f21"
|
||||
),
|
||||
fromHex("00000000000000000000000036c6b90a49e17d4c1e1b0e634ec74124d9b207da")
|
||||
},
|
||||
{
|
||||
fromHex("6162636465666768696a6b6c6d6e6f707172737475767778797a414243444546"),
|
||||
fromHex("000000000000000000000000ac5ab22e07b0fb80c69b6207902f725e2507e546")
|
||||
}
|
||||
};
|
||||
return precompileGeneric(_message, inputOutput);
|
||||
}
|
||||
|
||||
evmc::result EVMHost::precompileIdentity(evmc_message const& _message) noexcept
|
||||
{
|
||||
// static data so that we do not need a release routine...
|
||||
bytes static data;
|
||||
data = bytes(_message.input_data, _message.input_data + _message.input_size);
|
||||
evmc::result result({});
|
||||
result.gas_left = _message.gas;
|
||||
result.output_data = data.data();
|
||||
result.output_size = data.size();
|
||||
return result;
|
||||
}
|
||||
|
||||
evmc::result EVMHost::precompileModExp(evmc_message const&) noexcept
|
||||
{
|
||||
// TODO implement
|
||||
evmc::result result({});
|
||||
result.status_code = EVMC_FAILURE;
|
||||
return result;
|
||||
}
|
||||
|
||||
evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noexcept
|
||||
{
|
||||
// NOTE this is a partial implementation for some inputs.
|
||||
|
||||
static map<bytes, bytes> const inputOutput{
|
||||
{
|
||||
fromHex(
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d5012"
|
||||
"02254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
),
|
||||
fromHex(
|
||||
"1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d5012"
|
||||
"02254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c"
|
||||
)
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"0000000000000000000000000000000000000000000000000000000000000001"
|
||||
"0000000000000000000000000000000000000000000000000000000000000002"
|
||||
"0000000000000000000000000000000000000000000000000000000000000001"
|
||||
"0000000000000000000000000000000000000000000000000000000000000002"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
),
|
||||
fromHex(
|
||||
"030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd3"
|
||||
"15ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4"
|
||||
)
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"0000000000000000000000000000000000000000000000000000000000000001"
|
||||
"0000000000000000000000000000000000000000000000000000000000000002"
|
||||
"0000000000000000000000000000000000000000000000000000000000000001"
|
||||
"30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
),
|
||||
fromHex(
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
)
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"10b4876441e14a6be92a7fe66550848c01c676a12ac31d7cc13b21f49c4307c8"
|
||||
"09f5528bdb0ef9354837a0f4b4c9da973bd5b805d359976f719ab0b74e0a7368"
|
||||
"28d3c57516712e7843a5b3cfa7d7274a037943f5bd57c227620ad207728e4283"
|
||||
"2795fa9df21d4b8b329a45bae120f1fd9df9049ecacaa9dd1eca18bc6a55cd2f"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
),
|
||||
fromHex(
|
||||
"16aed5ed486df6b2fb38015ded41400009ed4f34bef65b87b1f90f47052f8d94"
|
||||
"16dabf21b3f25b9665269d98dc17b1da6118251dc0b403ae50e96dfe91239375"
|
||||
)
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d5012"
|
||||
"02254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c"
|
||||
"1644e84fef7b7fdc98254f0654580173307a3bc44db990581e7ab55a22446dcf"
|
||||
"28c2916b7e875692b195831945805438fcd30d2693d8a80cf8c88ec6ef4c315d"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
),
|
||||
fromHex(
|
||||
"1e018816fc9bbd91313301ae9c254bb7d64d6cd54f3b49b92925e43e256b5faa"
|
||||
"1d1f2259c715327bedb42c095af6c0267e4e1be836b4e04b3f0502552f93cca9"
|
||||
)
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"16aed5ed486df6b2fb38015ded41400009ed4f34bef65b87b1f90f47052f8d94"
|
||||
"16dabf21b3f25b9665269d98dc17b1da6118251dc0b403ae50e96dfe91239375"
|
||||
"25ff95a3abccf32adc6a4c3c8caddca67723d8ada802e9b9f612e3ddb40b2005"
|
||||
"0d82b09bb4ec927bbf182bdc402790429322b7e2f285f2aad8ea135cbf7143d8"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
),
|
||||
fromHex(
|
||||
"29d160febeef9770d47a32ee3b763850eb0594844fa57dd31b8ed02c78fdb797"
|
||||
"2c7cdf62c2498486fd52646e577a06723ce97737b3c958262d78c4a413661e8a"
|
||||
),
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"18014701594179c6b9ccae848e3d15c1f76f8a68b8092578296520e46c9bae0c"
|
||||
"1b5ed0e9e8f3ff35589ea81a45cf63887d4a92c099a3be1d97b26f0db96323dd"
|
||||
"16a1d378d1a98cf5383cdc512011234287ca43b6a078d1842d5c58c5b1f475cc"
|
||||
"1309377a7026d08ca1529eab74381a7e0d3a4b79d80bacec207cd52fc8e3769c"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
),
|
||||
fromHex(
|
||||
"2583ed10e418133e44619c336f1be5ddae9e20d634a7683d9661401c750d7df4"
|
||||
"0185fbba22de9e698262925665735dbc4d6e8288bc3fc39fae10ca58e16e77f7"
|
||||
)
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59"
|
||||
"3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41"
|
||||
"0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2"
|
||||
"16da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
),
|
||||
fromHex(
|
||||
"1496064626ba8bffeb7805f0d16143a65649bb0850333ea512c03fcdaf31e254"
|
||||
"07b4f210ab542533f1ee5633ae4406cd16c63494b537ce3f1cf4afff6f76a48f"
|
||||
),
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"1e018816fc9bbd91313301ae9c254bb7d64d6cd54f3b49b92925e43e256b5faa"
|
||||
"1d1f2259c715327bedb42c095af6c0267e4e1be836b4e04b3f0502552f93cca9"
|
||||
"2364294faf6b89fedeede9986aa777c4f6c2f5c4a4559ee93dfec9b7b94ef80b"
|
||||
"05aeae62655ea23865ae6661ae371a55c12098703d0f2301f4223e708c92efc6"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
),
|
||||
fromHex(
|
||||
"2801b21090cbc48409e352647f3857134d373f81741f9d5e3d432f336d76f517"
|
||||
"13cf106acf943c2a331de21c7d5e3351354e7412f2dba2918483a6593a6828d4"
|
||||
)
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"2583ed10e418133e44619c336f1be5ddae9e20d634a7683d9661401c750d7df4"
|
||||
"0185fbba22de9e698262925665735dbc4d6e8288bc3fc39fae10ca58e16e77f7"
|
||||
"258f1faa356e470cca19c928afa5ceed6215c756912af5725b8db5777cc8f3b6"
|
||||
"175ced8a58d0c132c2b95ba14c16dde93e7f7789214116ff69da6f44daa966e6"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
),
|
||||
fromHex(
|
||||
"10b4876441e14a6be92a7fe66550848c01c676a12ac31d7cc13b21f49c4307c8"
|
||||
"09f5528bdb0ef9354837a0f4b4c9da973bd5b805d359976f719ab0b74e0a7368"
|
||||
)
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"26dcfbc2e0bc9d82efb4acd73cb3e99730e27e10177fcfb78b6399a4bfcdf391"
|
||||
"27c440dbd5053253a3a692f9bf89b9b6e9612127cf97db1e11ffa9679acc933b"
|
||||
"1496064626ba8bffeb7805f0d16143a65649bb0850333ea512c03fcdaf31e254"
|
||||
"07b4f210ab542533f1ee5633ae4406cd16c63494b537ce3f1cf4afff6f76a48f"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
),
|
||||
fromHex(
|
||||
"186bac5188a98c45e6016873d107f5cd131f3a3e339d0375e58bd6219347b008"
|
||||
"1e396bc242de0214898b0f68035f53ad5a6f96c6c8390ac56ed6ec9561d23159"
|
||||
)
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"26dcfbc2e0bc9d82efb4acd73cb3e99730e27e10177fcfb78b6399a4bfcdf391"
|
||||
"27c440dbd5053253a3a692f9bf89b9b6e9612127cf97db1e11ffa9679acc933b"
|
||||
"1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59"
|
||||
"3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
),
|
||||
fromHex(
|
||||
"20a754d2071d4d53903e3b31a7e98ad6882d58aec240ef981fdf0a9d22c5926a"
|
||||
"29c853fcea789887315916bbeb89ca37edb355b4f980c9a12a94f30deeed3021"
|
||||
)
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"27231d5cdd0011259ff75678cf5a8f7840c22cb71d52b25e21e071205e8d9bc4"
|
||||
"26dd3d225c9a71476db0cf834232eba84020f3073c6d20c519963e0b98f235e1"
|
||||
"2174f0221490cd9c15b0387f3251ec3d49517a51c37a8076eac12afb4a95a707"
|
||||
"1d1c3fcd3161e2a417b4df0955f02db1fffa9005210fb30c5aa3755307e9d1f5"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
),
|
||||
fromHex(
|
||||
"18014701594179c6b9ccae848e3d15c1f76f8a68b8092578296520e46c9bae0c"
|
||||
"1b5ed0e9e8f3ff35589ea81a45cf63887d4a92c099a3be1d97b26f0db96323dd"
|
||||
),
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"2801b21090cbc48409e352647f3857134d373f81741f9d5e3d432f336d76f517"
|
||||
"13cf106acf943c2a331de21c7d5e3351354e7412f2dba2918483a6593a6828d4"
|
||||
"2a49621e12910cd90f3e731083d454255bf1c533d6e15b8699156778d0f27f5d"
|
||||
"2590ee31824548d159aa2d22296bf149d564c0872f41b89b7dc5c6e6e3cd1c4d"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
),
|
||||
fromHex(
|
||||
"27231d5cdd0011259ff75678cf5a8f7840c22cb71d52b25e21e071205e8d9bc4"
|
||||
"26dd3d225c9a71476db0cf834232eba84020f3073c6d20c519963e0b98f235e1"
|
||||
)
|
||||
},
|
||||
{
|
||||
fromHex(
|
||||
"29d160febeef9770d47a32ee3b763850eb0594844fa57dd31b8ed02c78fdb797"
|
||||
"2c7cdf62c2498486fd52646e577a06723ce97737b3c958262d78c4a413661e8a"
|
||||
"0aee46a7ea6e80a3675026dfa84019deee2a2dedb1bbe11d7fe124cb3efb4b5a"
|
||||
"044747b6e9176e13ede3a4dfd0d33ccca6321b9acd23bf3683a60adc0366ebaf"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
),
|
||||
fromHex(
|
||||
"26dcfbc2e0bc9d82efb4acd73cb3e99730e27e10177fcfb78b6399a4bfcdf391"
|
||||
"27c440dbd5053253a3a692f9bf89b9b6e9612127cf97db1e11ffa9679acc933b"
|
||||
)
|
||||
}
|
||||
};
|
||||
return precompileGeneric(_message, inputOutput);
|
||||
}
|
||||
|
||||
evmc::result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noexcept
|
||||
{
|
||||
// NOTE this is a partial implementation for some inputs.
|
||||
static map<bytes, bytes> const inputOutput{
|
||||
{
|
||||
fromHex("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000"),
|
||||
fromHex("030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4")
|
||||
},
|
||||
{
|
||||
fromHex("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000"),
|
||||
fromHex("17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c")
|
||||
},
|
||||
{
|
||||
fromHex("09b54f111d3b2d1b2fe1ae9669b3db3d7bf93b70f00647e65c849275de6dc7fe18b2e77c63a3e400d6d1f1fbc6e1a1167bbca603d34d03edea231eb0ab7b14b4030f7b0c405c888aff922307ea2cd1c70f64664bab76899500341f4260a209290000000000000000000000000000000000000000000000000000000000000000"),
|
||||
fromHex("16a1d378d1a98cf5383cdc512011234287ca43b6a078d1842d5c58c5b1f475cc1309377a7026d08ca1529eab74381a7e0d3a4b79d80bacec207cd52fc8e3769c")
|
||||
},
|
||||
{
|
||||
fromHex("0a6de0e2240aa253f46ce0da883b61976e3588146e01c9d8976548c145fe6e4a04fbaa3a4aed4bb77f30ebb07a3ec1c7d77a7f2edd75636babfeff97b1ea686e1551dcd4965285ef049512d2d30cbfc1a91acd5baad4a6e19e22e93176197f170000000000000000000000000000000000000000000000000000000000000000"),
|
||||
fromHex("28d3c57516712e7843a5b3cfa7d7274a037943f5bd57c227620ad207728e42832795fa9df21d4b8b329a45bae120f1fd9df9049ecacaa9dd1eca18bc6a55cd2f")
|
||||
},
|
||||
{
|
||||
fromHex("0c54b42137b67cc268cbb53ac62b00ecead23984092b494a88befe58445a244a18e3723d37fae9262d58b548a0575f59d9c3266db7afb4d5739555837f6b8b3e0c692b41f1acc961f6ea83bae2c3a1a55c54f766c63ba76989f52c149c17b5e70000000000000000000000000000000000000000000000000000000000000000"),
|
||||
fromHex("258f1faa356e470cca19c928afa5ceed6215c756912af5725b8db5777cc8f3b6175ced8a58d0c132c2b95ba14c16dde93e7f7789214116ff69da6f44daa966e6")
|
||||
},
|
||||
{
|
||||
fromHex("0f103f14a584d4203c27c26155b2c955f8dfa816980b24ba824e1972d6486a5d0c4165133b9f5be17c804203af781bcf168da7386620479f9b885ecbcd27b17b0ea71d0abb524cac7cfff5323e1d0b14ab705842426c978f96753ccce258ed930000000000000000000000000000000000000000000000000000000000000000"),
|
||||
fromHex("2a49621e12910cd90f3e731083d454255bf1c533d6e15b8699156778d0f27f5d2590ee31824548d159aa2d22296bf149d564c0872f41b89b7dc5c6e6e3cd1c4d")
|
||||
},
|
||||
{
|
||||
fromHex("111e2e2a5f8828f80ddad08f9f74db56dac1cc16c1cb278036f79a84cf7a116f1d7d62e192b219b9808faa906c5ced871788f6339e8d91b83ac1343e20a16b3000000000000000000000000000000000000000e40800000000000000008cdcbc0000000000000000000000000000000000000000000000000000000000000000"),
|
||||
fromHex("25ff95a3abccf32adc6a4c3c8caddca67723d8ada802e9b9f612e3ddb40b20050d82b09bb4ec927bbf182bdc402790429322b7e2f285f2aad8ea135cbf7143d8")
|
||||
},
|
||||
{
|
||||
fromHex("17d5d09b4146424bff7e6fb01487c477bbfcd0cdbbc92d5d6457aae0b6717cc502b5636903efbf46db9235bbe74045d21c138897fda32e079040db1a16c1a7a11887420878c0c8e37605291c626585eabbec8d8b97a848fe8d58a37b004583510000000000000000000000000000000000000000000000000000000000000000"),
|
||||
fromHex("2364294faf6b89fedeede9986aa777c4f6c2f5c4a4559ee93dfec9b7b94ef80b05aeae62655ea23865ae6661ae371a55c12098703d0f2301f4223e708c92efc6")
|
||||
},
|
||||
{
|
||||
fromHex("1c36e713d4d54e3a9644dffca1fc524be4868f66572516025a61ca542539d43f042dcc4525b82dfb242b09cb21909d5c22643dcdbe98c4d082cc2877e96b24db016086cc934d5cab679c6991a4efcedbab26d7e4fb23b6a1ad4e6b5c2fb59ce50000000000000000000000000000000000000000000000000000000000000000"),
|
||||
fromHex("1644e84fef7b7fdc98254f0654580173307a3bc44db990581e7ab55a22446dcf28c2916b7e875692b195831945805438fcd30d2693d8a80cf8c88ec6ef4c315d")
|
||||
},
|
||||
{
|
||||
fromHex("1e39e9f0f91fa7ff8047ffd90de08785777fe61c0e3434e728fce4cf35047ddc2e0b64d75ebfa86d7f8f8e08abbe2e7ae6e0a1c0b34d028f19fa56e9450527cb1eec35a0e955cad4bee5846ae0f1d0b742d8636b278450c534e38e06a60509f90000000000000000000000000000000000000000000000000000000000000000"),
|
||||
fromHex("1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d501202254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c")
|
||||
},
|
||||
{
|
||||
fromHex("232063b584fb76c8d07995bee3a38fa7565405f3549c6a918ddaa90ab971e7f82ac9b135a81d96425c92d02296322ad56ffb16299633233e4880f95aafa7fda70689c3dc4311426ee11707866b2cbdf9751dacd07245bf99d2113d3f5a8cac470000000000000000000000000000000000000000000000000000000000000000"),
|
||||
fromHex("2174f0221490cd9c15b0387f3251ec3d49517a51c37a8076eac12afb4a95a7071d1c3fcd3161e2a417b4df0955f02db1fffa9005210fb30c5aa3755307e9d1f5")
|
||||
}
|
||||
};
|
||||
return precompileGeneric(_message, inputOutput);
|
||||
}
|
||||
|
||||
evmc::result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _message) noexcept
|
||||
{
|
||||
// This is a partial implementation - it always returns "success"
|
||||
bytes static data = fromHex("0000000000000000000000000000000000000000000000000000000000000001");
|
||||
return resultWithGas(_message, data);
|
||||
}
|
||||
|
||||
evmc::result EVMHost::precompileGeneric(
|
||||
evmc_message const& _message,
|
||||
map<bytes, bytes> const& _inOut) noexcept
|
||||
{
|
||||
bytes input(_message.input_data, _message.input_data + _message.input_size);
|
||||
if (_inOut.count(input))
|
||||
return resultWithGas(_message, _inOut.at(input));
|
||||
else
|
||||
{
|
||||
evmc::result result({});
|
||||
result.status_code = EVMC_FAILURE;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
evmc::result EVMHost::resultWithGas(
|
||||
evmc_message const& _message,
|
||||
bytes const& _data
|
||||
) noexcept
|
||||
{
|
||||
evmc::result result({});
|
||||
result.status_code = EVMC_SUCCESS;
|
||||
result.gas_left = _message.gas;
|
||||
result.output_data = _data.data();
|
||||
result.output_size = _data.size();
|
||||
return result;
|
||||
}
|
||||
|
@ -38,7 +38,12 @@ using Address = h160;
|
||||
class EVMHost: public evmc::Host
|
||||
{
|
||||
public:
|
||||
explicit EVMHost(langutil::EVMVersion _evmVersion, evmc::vm& _vmInstance);
|
||||
/// Tries to dynamically load libevmone. @returns nullptr on failure.
|
||||
/// The path has to be provided for the first successful run and will be ignored
|
||||
/// afterwards.
|
||||
static evmc::vm* getVM(std::string const& _path = {});
|
||||
|
||||
explicit EVMHost(langutil::EVMVersion _evmVersion, evmc::vm* _vm = getVM());
|
||||
|
||||
struct Account
|
||||
{
|
||||
@ -66,6 +71,10 @@ public:
|
||||
|
||||
Account* account(evmc_address const& _address)
|
||||
{
|
||||
// Make all precompiled contracts exist.
|
||||
// Be future-proof and consider everything below 1024 as precompiled contract.
|
||||
if (u160(convertFromEVMC(_address)) < 1024)
|
||||
m_state.accounts[_address];
|
||||
auto it = m_state.accounts.find(_address);
|
||||
return it == m_state.accounts.end() ? nullptr : &it->second;
|
||||
}
|
||||
@ -147,11 +156,6 @@ public:
|
||||
size_t _topicsCount
|
||||
) noexcept;
|
||||
|
||||
evmc_revision getRevision()
|
||||
{
|
||||
return m_evmVersion;
|
||||
}
|
||||
|
||||
static Address convertFromEVMC(evmc_address const& _addr);
|
||||
static evmc_address convertToEVMC(Address const& _addr);
|
||||
static h256 convertFromEVMC(evmc_bytes32 const& _data);
|
||||
@ -163,9 +167,20 @@ public:
|
||||
evmc_address m_coinbase = convertToEVMC(Address("0x7878787878787878787878787878787878787878"));
|
||||
|
||||
private:
|
||||
evmc::result precompileECRecover(evmc_message const& _message) noexcept;
|
||||
evmc::result precompileSha256(evmc_message const& _message) noexcept;
|
||||
evmc::result precompileRipeMD160(evmc_message const& _message) noexcept;
|
||||
evmc::result precompileIdentity(evmc_message const& _message) noexcept;
|
||||
evmc::result precompileModExp(evmc_message const& _message) noexcept;
|
||||
evmc::result precompileALTBN128G1Add(evmc_message const& _message) noexcept;
|
||||
evmc::result precompileALTBN128G1Mul(evmc_message const& _message) noexcept;
|
||||
evmc::result precompileALTBN128PairingProduct(evmc_message const& _message) noexcept;
|
||||
evmc::result precompileGeneric(evmc_message const& _message, std::map<bytes, bytes> const& _inOut) noexcept;
|
||||
/// @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;
|
||||
|
||||
evmc::vm& m_vm;
|
||||
evmc::vm* m_vm = nullptr;
|
||||
evmc_revision m_evmVersion;
|
||||
};
|
||||
|
||||
|
@ -22,6 +22,12 @@
|
||||
|
||||
#include <test/ExecutionFramework.h>
|
||||
|
||||
#include <test/EVMHost.h>
|
||||
|
||||
#include <test/evmc/evmc.hpp>
|
||||
#include <test/evmc/loader.h>
|
||||
#include <test/evmc/helpers.hpp>
|
||||
|
||||
#include <libdevcore/CommonIO.h>
|
||||
|
||||
#include <boost/test/framework.hpp>
|
||||
@ -29,46 +35,31 @@
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
using namespace dev;
|
||||
using namespace dev::test;
|
||||
|
||||
namespace // anonymous
|
||||
{
|
||||
|
||||
h256 const EmptyTrie("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421");
|
||||
|
||||
string getIPCSocketPath()
|
||||
{
|
||||
string ipcPath = dev::test::Options::get().ipcPath.string();
|
||||
if (ipcPath.empty())
|
||||
BOOST_FAIL("ERROR: ipcPath not set! (use --ipcpath <path> or the environment variable ETH_TEST_IPC)");
|
||||
|
||||
return ipcPath;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ExecutionFramework::ExecutionFramework():
|
||||
ExecutionFramework(getIPCSocketPath(), dev::test::Options::get().evmVersion())
|
||||
ExecutionFramework(dev::test::Options::get().evmVersion())
|
||||
{
|
||||
}
|
||||
|
||||
ExecutionFramework::ExecutionFramework(string const& _ipcPath, langutil::EVMVersion _evmVersion):
|
||||
m_rpc(RPCSession::instance(_ipcPath)),
|
||||
ExecutionFramework::ExecutionFramework(langutil::EVMVersion _evmVersion):
|
||||
m_evmVersion(_evmVersion),
|
||||
m_optimiserSettings(solidity::OptimiserSettings::minimal()),
|
||||
m_showMessages(dev::test::Options::get().showMessages),
|
||||
m_sender(m_rpc.account(0))
|
||||
m_evmHost(make_shared<EVMHost>(m_evmVersion))
|
||||
{
|
||||
if (dev::test::Options::get().optimizeYul)
|
||||
m_optimiserSettings = solidity::OptimiserSettings::full();
|
||||
else if (dev::test::Options::get().optimize)
|
||||
m_optimiserSettings = solidity::OptimiserSettings::standard();
|
||||
m_rpc.test_rewindToBlock(0);
|
||||
m_evmHost->reset();
|
||||
|
||||
for (size_t i = 0; i < 10; i++)
|
||||
m_evmHost->m_state.accounts[EVMHost::convertToEVMC(account(i))].balance =
|
||||
EVMHost::convertToEVMC(u256(1) << 100);
|
||||
|
||||
}
|
||||
|
||||
std::pair<bool, string> ExecutionFramework::compareAndCreateMessage(
|
||||
@ -99,22 +90,28 @@ std::pair<bool, string> ExecutionFramework::compareAndCreateMessage(
|
||||
|
||||
u256 ExecutionFramework::gasLimit() const
|
||||
{
|
||||
auto latestBlock = m_rpc.eth_getBlockByNumber("latest", false);
|
||||
return u256(latestBlock["gasLimit"].asString());
|
||||
return {m_evmHost->get_tx_context().block_gas_limit};
|
||||
}
|
||||
|
||||
u256 ExecutionFramework::gasPrice() const
|
||||
{
|
||||
return u256(m_rpc.eth_gasPrice());
|
||||
return {EVMHost::convertFromEVMC(m_evmHost->get_tx_context().tx_gas_price)};
|
||||
}
|
||||
|
||||
u256 ExecutionFramework::blockHash(u256 const& _blockNumber) const
|
||||
u256 ExecutionFramework::blockHash(u256 const& _number) const
|
||||
{
|
||||
return u256(m_rpc.eth_getBlockByNumber(toHex(_blockNumber, HexPrefix::Add), false)["hash"].asString());
|
||||
return {EVMHost::convertFromEVMC(m_evmHost->get_block_hash(uint64_t(_number & numeric_limits<uint64_t>::max())))};
|
||||
}
|
||||
|
||||
u256 ExecutionFramework::blockNumber() const
|
||||
{
|
||||
return m_evmHost->m_state.blockNumber;
|
||||
}
|
||||
|
||||
void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 const& _value)
|
||||
{
|
||||
m_evmHost->newBlock();
|
||||
|
||||
if (m_showMessages)
|
||||
{
|
||||
if (_isCreation)
|
||||
@ -125,104 +122,121 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256
|
||||
cout << " value: " << _value << endl;
|
||||
cout << " in: " << toHex(_data) << endl;
|
||||
}
|
||||
RPCSession::TransactionData d;
|
||||
d.data = "0x" + toHex(_data);
|
||||
d.from = "0x" + toString(m_sender);
|
||||
d.gas = toHex(m_gas, HexPrefix::Add);
|
||||
d.gasPrice = toHex(m_gasPrice, HexPrefix::Add);
|
||||
d.value = toHex(_value, HexPrefix::Add);
|
||||
if (!_isCreation)
|
||||
{
|
||||
d.to = dev::toString(m_contractAddress);
|
||||
BOOST_REQUIRE(m_rpc.eth_getCode(d.to, "pending").size() > 2);
|
||||
// Use eth_call to get the output
|
||||
m_output = fromHex(m_rpc.eth_call(d, "pending"), WhenError::Throw);
|
||||
}
|
||||
|
||||
string txHash = m_rpc.eth_sendTransaction(d);
|
||||
m_rpc.rpcCall("eth_flush");
|
||||
m_rpc.test_mineBlocks(1);
|
||||
RPCSession::TransactionReceipt receipt(m_rpc.eth_getTransactionReceipt(txHash));
|
||||
|
||||
m_blockNumber = u256(receipt.blockNumber);
|
||||
evmc_message message = {};
|
||||
message.input_data = _data.data();
|
||||
message.input_size = _data.size();
|
||||
message.sender = EVMHost::convertToEVMC(m_sender);
|
||||
message.value = EVMHost::convertToEVMC(_value);
|
||||
|
||||
if (_isCreation)
|
||||
{
|
||||
m_contractAddress = Address(receipt.contractAddress);
|
||||
BOOST_REQUIRE(m_contractAddress);
|
||||
string code = m_rpc.eth_getCode(receipt.contractAddress, "latest");
|
||||
m_output = fromHex(code, WhenError::Throw);
|
||||
message.kind = EVMC_CREATE;
|
||||
message.destination = EVMHost::convertToEVMC(Address{});
|
||||
}
|
||||
else
|
||||
{
|
||||
message.kind = EVMC_CALL;
|
||||
message.destination = EVMHost::convertToEVMC(m_contractAddress);
|
||||
}
|
||||
message.gas = m_gas.convert_to<int64_t>();
|
||||
|
||||
evmc::result result = m_evmHost->call(message);
|
||||
|
||||
m_output = bytes(result.output_data, result.output_data + result.output_size);
|
||||
if (_isCreation)
|
||||
m_contractAddress = EVMHost::convertFromEVMC(result.create_address);
|
||||
|
||||
m_gasUsed = m_gas - result.gas_left;
|
||||
m_transactionSuccessful = (result.status_code == EVMC_SUCCESS);
|
||||
|
||||
if (m_showMessages)
|
||||
{
|
||||
cout << " out: " << toHex(m_output) << endl;
|
||||
cout << " tx hash: " << txHash << endl;
|
||||
cout << " result: " << size_t(result.status_code) << endl;
|
||||
cout << " gas used: " << m_gasUsed.str() << endl;
|
||||
}
|
||||
|
||||
m_gasUsed = u256(receipt.gasUsed);
|
||||
m_logs.clear();
|
||||
for (auto const& log: receipt.logEntries)
|
||||
{
|
||||
LogEntry entry;
|
||||
entry.address = Address(log.address);
|
||||
for (auto const& topic: log.topics)
|
||||
entry.topics.push_back(h256(topic));
|
||||
entry.data = fromHex(log.data, WhenError::Throw);
|
||||
m_logs.push_back(entry);
|
||||
}
|
||||
|
||||
if (!receipt.status.empty())
|
||||
m_transactionSuccessful = (receipt.status == "1");
|
||||
else
|
||||
m_transactionSuccessful = (m_gas != m_gasUsed);
|
||||
}
|
||||
|
||||
void ExecutionFramework::sendEther(Address const& _to, u256 const& _value)
|
||||
void ExecutionFramework::sendEther(Address const& _addr, u256 const& _amount)
|
||||
{
|
||||
RPCSession::TransactionData d;
|
||||
d.data = "0x";
|
||||
d.from = "0x" + toString(m_sender);
|
||||
d.gas = toHex(m_gas, HexPrefix::Add);
|
||||
d.gasPrice = toHex(m_gasPrice, HexPrefix::Add);
|
||||
d.value = toHex(_value, HexPrefix::Add);
|
||||
d.to = dev::toString(_to);
|
||||
m_evmHost->newBlock();
|
||||
|
||||
string txHash = m_rpc.eth_sendTransaction(d);
|
||||
m_rpc.test_mineBlocks(1);
|
||||
if (m_showMessages)
|
||||
{
|
||||
cout << "SEND_ETHER " << m_sender.hex() << " -> " << _addr.hex() << ":" << endl;
|
||||
if (_amount > 0)
|
||||
cout << " value: " << _amount << endl;
|
||||
}
|
||||
evmc_message message = {};
|
||||
message.sender = EVMHost::convertToEVMC(m_sender);
|
||||
message.value = EVMHost::convertToEVMC(_amount);
|
||||
message.kind = EVMC_CALL;
|
||||
message.destination = EVMHost::convertToEVMC(_addr);
|
||||
message.gas = m_gas.convert_to<int64_t>();
|
||||
|
||||
m_evmHost->call(message);
|
||||
}
|
||||
|
||||
size_t ExecutionFramework::currentTimestamp()
|
||||
{
|
||||
auto latestBlock = m_rpc.eth_getBlockByNumber("latest", false);
|
||||
return size_t(u256(latestBlock.get("timestamp", "invalid").asString()));
|
||||
return m_evmHost->get_tx_context().block_timestamp;
|
||||
}
|
||||
|
||||
size_t ExecutionFramework::blockTimestamp(u256 _number)
|
||||
size_t ExecutionFramework::blockTimestamp(u256 _block)
|
||||
{
|
||||
auto latestBlock = m_rpc.eth_getBlockByNumber(toString(_number), false);
|
||||
return size_t(u256(latestBlock.get("timestamp", "invalid").asString()));
|
||||
if (_block > blockNumber())
|
||||
return 0;
|
||||
else
|
||||
return size_t((currentTimestamp() / blockNumber()) * _block);
|
||||
}
|
||||
|
||||
Address ExecutionFramework::account(size_t _i)
|
||||
Address ExecutionFramework::account(size_t _idx)
|
||||
{
|
||||
return Address(m_rpc.accountCreateIfNotExists(_i));
|
||||
return Address(h256(u256{"0x1212121212121212121212121212120000000012"} + _idx * 0x1000), Address::AlignRight);
|
||||
}
|
||||
|
||||
bool ExecutionFramework::addressHasCode(Address const& _addr)
|
||||
{
|
||||
string code = m_rpc.eth_getCode(toString(_addr), "latest");
|
||||
return !code.empty() && code != "0x";
|
||||
return m_evmHost->get_code_size(EVMHost::convertToEVMC(_addr)) != 0;
|
||||
}
|
||||
|
||||
size_t ExecutionFramework::numLogs() const
|
||||
{
|
||||
return m_evmHost->m_state.logs.size();
|
||||
}
|
||||
|
||||
size_t ExecutionFramework::numLogTopics(size_t _logIdx) const
|
||||
{
|
||||
return m_evmHost->m_state.logs.at(_logIdx).topics.size();
|
||||
}
|
||||
|
||||
h256 ExecutionFramework::logTopic(size_t _logIdx, size_t _topicIdx) const
|
||||
{
|
||||
return m_evmHost->m_state.logs.at(_logIdx).topics.at(_topicIdx);
|
||||
}
|
||||
|
||||
Address ExecutionFramework::logAddress(size_t _logIdx) const
|
||||
{
|
||||
return m_evmHost->m_state.logs.at(_logIdx).address;
|
||||
}
|
||||
|
||||
bytes const& ExecutionFramework::logData(size_t _logIdx) const
|
||||
{
|
||||
return m_evmHost->m_state.logs.at(_logIdx).data;
|
||||
}
|
||||
|
||||
u256 ExecutionFramework::balanceAt(Address const& _addr)
|
||||
{
|
||||
return u256(m_rpc.eth_getBalance(toString(_addr), "latest"));
|
||||
return u256(EVMHost::convertFromEVMC(m_evmHost->get_balance(EVMHost::convertToEVMC(_addr))));
|
||||
}
|
||||
|
||||
bool ExecutionFramework::storageEmpty(Address const& _addr)
|
||||
{
|
||||
h256 root(m_rpc.eth_getStorageRoot(toString(_addr), "latest"));
|
||||
BOOST_CHECK(root);
|
||||
return root == EmptyTrie;
|
||||
if (EVMHost::Account const* acc = m_evmHost->account(EVMHost::convertToEVMC(_addr)))
|
||||
{
|
||||
for (auto const& entry: acc->storage)
|
||||
if (!(entry.second == evmc_bytes32{}))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -23,7 +23,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <test/Options.h>
|
||||
#include <test/RPCSession.h>
|
||||
|
||||
#include <libsolidity/interface/OptimiserSettings.h>
|
||||
|
||||
@ -38,24 +37,26 @@ namespace dev
|
||||
{
|
||||
namespace test
|
||||
{
|
||||
using rational = boost::rational<dev::bigint>;
|
||||
/// An Ethereum address: 20 bytes.
|
||||
/// @NOTE This is not endian-specific; it's just a bunch of bytes.
|
||||
using Address = h160;
|
||||
class EVMHost;
|
||||
|
||||
// The various denominations; here for ease of use where needed within code.
|
||||
static const u256 wei = 1;
|
||||
static const u256 shannon = u256("1000000000");
|
||||
static const u256 szabo = shannon * 1000;
|
||||
static const u256 finney = szabo * 1000;
|
||||
static const u256 ether = finney * 1000;
|
||||
using rational = boost::rational<dev::bigint>;
|
||||
/// An Ethereum address: 20 bytes.
|
||||
/// @NOTE This is not endian-specific; it's just a bunch of bytes.
|
||||
using Address = h160;
|
||||
|
||||
// The various denominations; here for ease of use where needed within code.
|
||||
static const u256 wei = 1;
|
||||
static const u256 shannon = u256("1000000000");
|
||||
static const u256 szabo = shannon * 1000;
|
||||
static const u256 finney = szabo * 1000;
|
||||
static const u256 ether = finney * 1000;
|
||||
|
||||
class ExecutionFramework
|
||||
{
|
||||
|
||||
public:
|
||||
ExecutionFramework();
|
||||
explicit ExecutionFramework(std::string const& _ipcPath, langutil::EVMVersion _evmVersion);
|
||||
explicit ExecutionFramework(langutil::EVMVersion _evmVersion);
|
||||
virtual ~ExecutionFramework() = default;
|
||||
|
||||
virtual bytes const& compileAndRunWithoutCheck(
|
||||
@ -200,9 +201,7 @@ public:
|
||||
u256 gasLimit() const;
|
||||
u256 gasPrice() const;
|
||||
u256 blockHash(u256 const& _blockNumber) const;
|
||||
u256 const& blockNumber() const {
|
||||
return m_blockNumber;
|
||||
}
|
||||
u256 blockNumber() const;
|
||||
|
||||
template<typename Range>
|
||||
static bytes encodeArray(bool _dynamicallySized, bool _dynamicallyEncoded, Range const& _elements)
|
||||
@ -257,26 +256,23 @@ protected:
|
||||
bool storageEmpty(Address const& _addr);
|
||||
bool addressHasCode(Address const& _addr);
|
||||
|
||||
RPCSession& m_rpc;
|
||||
|
||||
struct LogEntry
|
||||
{
|
||||
Address address;
|
||||
std::vector<h256> topics;
|
||||
bytes data;
|
||||
};
|
||||
size_t numLogs() const;
|
||||
size_t numLogTopics(size_t _logIdx) const;
|
||||
h256 logTopic(size_t _logIdx, size_t _topicIdx) const;
|
||||
Address logAddress(size_t _logIdx) const;
|
||||
bytes const& logData(size_t _logIdx) const;
|
||||
|
||||
langutil::EVMVersion m_evmVersion;
|
||||
solidity::OptimiserSettings m_optimiserSettings = solidity::OptimiserSettings::minimal();
|
||||
bool m_showMessages = false;
|
||||
std::shared_ptr<EVMHost> m_evmHost;
|
||||
|
||||
bool m_transactionSuccessful = true;
|
||||
Address m_sender;
|
||||
Address m_sender = account(0);
|
||||
Address m_contractAddress;
|
||||
u256 m_blockNumber;
|
||||
u256 const m_gasPrice = 100 * szabo;
|
||||
u256 const m_gas = 100000000;
|
||||
bytes m_output;
|
||||
std::vector<LogEntry> m_logs;
|
||||
u256 m_gasUsed;
|
||||
};
|
||||
|
||||
|
@ -44,7 +44,7 @@ struct Testsuite
|
||||
boost::filesystem::path const path;
|
||||
boost::filesystem::path const subpath;
|
||||
bool smt;
|
||||
bool ipc;
|
||||
bool needsVM;
|
||||
TestCase::TestCaseCreator testCaseCreator;
|
||||
};
|
||||
|
||||
@ -52,7 +52,7 @@ struct Testsuite
|
||||
/// Array of testsuits that can be run interactively as well as automatically
|
||||
Testsuite const g_interactiveTestsuites[] = {
|
||||
/*
|
||||
Title Path Subpath SMT IPC Creator function */
|
||||
Title Path Subpath SMT NeedsVM Creator function */
|
||||
{"Yul Optimizer", "libyul", "yulOptimizerTests", false, false, &yul::test::YulOptimizerTest::create},
|
||||
{"Yul Interpreter", "libyul", "yulInterpreterTests", false, false, &yul::test::YulInterpreterTest::create},
|
||||
{"Yul Object Compiler", "libyul", "objectCompiler", false, false, &yul::test::ObjectCompilerTest::create},
|
||||
|
@ -1,396 +0,0 @@
|
||||
/*
|
||||
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/>.
|
||||
|
||||
The Implementation originally from https://msdn.microsoft.com/en-us/library/windows/desktop/aa365592(v=vs.85).aspx
|
||||
*/
|
||||
/// @file RPCSession.cpp
|
||||
/// Low-level IPC communication between the test framework and the Ethereum node.
|
||||
|
||||
#include <test/RPCSession.h>
|
||||
|
||||
#include <test/Options.h>
|
||||
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
|
||||
#include <libdevcore/CommonData.h>
|
||||
|
||||
#include <libdevcore/JSON.h>
|
||||
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
using namespace std;
|
||||
using namespace dev;
|
||||
|
||||
IPCSocket::IPCSocket(string const& _path): m_path(_path)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
m_socket = CreateFile(
|
||||
m_path.c_str(), // pipe name
|
||||
GENERIC_READ | // read and write access
|
||||
GENERIC_WRITE,
|
||||
0, // no sharing
|
||||
NULL, // default security attribute
|
||||
OPEN_EXISTING, // opens existing pipe
|
||||
0, // default attributes
|
||||
NULL); // no template file
|
||||
|
||||
if (m_socket == INVALID_HANDLE_VALUE)
|
||||
BOOST_FAIL("Error creating IPC socket object!");
|
||||
|
||||
#else
|
||||
if (_path.length() >= sizeof(sockaddr_un::sun_path))
|
||||
BOOST_FAIL("Error opening IPC: socket path is too long!");
|
||||
|
||||
struct sockaddr_un saun;
|
||||
memset(&saun, 0, sizeof(sockaddr_un));
|
||||
saun.sun_family = AF_UNIX;
|
||||
strcpy(saun.sun_path, _path.c_str());
|
||||
|
||||
// http://idletechnology.blogspot.ca/2011/12/unix-domain-sockets-on-osx.html
|
||||
//
|
||||
// SUN_LEN() might be optimal, but it seemingly affects the portability,
|
||||
// with at least Android missing this macro. Just using the sizeof() for
|
||||
// structure seemingly works, and would only have the side-effect of
|
||||
// sending larger-than-required packets over the socket. Given that this
|
||||
// code is only used for unit-tests, that approach seems simpler.
|
||||
#if defined(__APPLE__)
|
||||
saun.sun_len = sizeof(struct sockaddr_un);
|
||||
#endif // defined(__APPLE__)
|
||||
|
||||
if ((m_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
|
||||
BOOST_FAIL("Error creating IPC socket object");
|
||||
|
||||
if (connect(m_socket, reinterpret_cast<struct sockaddr const*>(&saun), sizeof(struct sockaddr_un)) < 0)
|
||||
{
|
||||
close(m_socket);
|
||||
BOOST_FAIL("Error connecting to IPC socket: " << _path);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
string IPCSocket::sendRequest(string const& _req)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
// Write to the pipe.
|
||||
DWORD cbWritten;
|
||||
BOOL fSuccess = WriteFile(
|
||||
m_socket, // pipe handle
|
||||
_req.c_str(), // message
|
||||
_req.size(), // message length
|
||||
&cbWritten, // bytes written
|
||||
NULL); // not overlapped
|
||||
|
||||
if (!fSuccess || (_req.size() != cbWritten))
|
||||
BOOST_FAIL("WriteFile to pipe failed");
|
||||
|
||||
// Read from the pipe.
|
||||
DWORD cbRead;
|
||||
fSuccess = ReadFile(
|
||||
m_socket, // pipe handle
|
||||
m_readBuf, // buffer to receive reply
|
||||
sizeof(m_readBuf), // size of buffer
|
||||
&cbRead, // number of bytes read
|
||||
NULL); // not overlapped
|
||||
|
||||
if (!fSuccess)
|
||||
BOOST_FAIL("ReadFile from pipe failed");
|
||||
|
||||
return string(m_readBuf, m_readBuf + cbRead);
|
||||
#else
|
||||
if (send(m_socket, _req.c_str(), _req.length(), 0) != (ssize_t)_req.length())
|
||||
BOOST_FAIL("Writing on IPC failed.");
|
||||
|
||||
auto start = chrono::steady_clock::now();
|
||||
ssize_t ret;
|
||||
do
|
||||
{
|
||||
ret = recv(m_socket, m_readBuf, sizeof(m_readBuf), 0);
|
||||
// Also consider closed socket an error.
|
||||
if (ret < 0)
|
||||
BOOST_FAIL("Reading on IPC failed.");
|
||||
}
|
||||
while (
|
||||
ret == 0 &&
|
||||
chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count() < m_readTimeOutMS
|
||||
);
|
||||
|
||||
if (ret == 0)
|
||||
BOOST_FAIL("Timeout reading on IPC.");
|
||||
|
||||
return string(m_readBuf, m_readBuf + ret);
|
||||
#endif
|
||||
}
|
||||
|
||||
RPCSession& RPCSession::instance(string const& _path)
|
||||
{
|
||||
try
|
||||
{
|
||||
static RPCSession session(_path);
|
||||
BOOST_REQUIRE_EQUAL(session.m_ipcSocket.path(), _path);
|
||||
return session;
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Error creating RPC session for socket: " + _path));
|
||||
}
|
||||
}
|
||||
|
||||
string RPCSession::eth_getCode(string const& _address, string const& _blockNumber)
|
||||
{
|
||||
return rpcCall("eth_getCode", { quote(_address), quote(_blockNumber) }).asString();
|
||||
}
|
||||
|
||||
Json::Value RPCSession::eth_getBlockByNumber(string const& _blockNumber, bool _fullObjects)
|
||||
{
|
||||
// NOTE: to_string() converts bool to 0 or 1
|
||||
return rpcCall("eth_getBlockByNumber", { quote(_blockNumber), _fullObjects ? "true" : "false" });
|
||||
}
|
||||
|
||||
RPCSession::TransactionReceipt RPCSession::eth_getTransactionReceipt(string const& _transactionHash)
|
||||
{
|
||||
TransactionReceipt receipt;
|
||||
Json::Value const result = rpcCall("eth_getTransactionReceipt", { quote(_transactionHash) });
|
||||
receipt.gasUsed = result["gasUsed"].asString();
|
||||
receipt.contractAddress = result["contractAddress"].asString();
|
||||
receipt.blockNumber = result["blockNumber"].asString();
|
||||
if (m_receiptHasStatusField)
|
||||
{
|
||||
BOOST_REQUIRE(!result["status"].isNull());
|
||||
receipt.status = result["status"].asString();
|
||||
}
|
||||
for (auto const& log: result["logs"])
|
||||
{
|
||||
LogEntry entry;
|
||||
entry.address = log["address"].asString();
|
||||
entry.data = log["data"].asString();
|
||||
for (auto const& topic: log["topics"])
|
||||
entry.topics.push_back(topic.asString());
|
||||
receipt.logEntries.push_back(entry);
|
||||
}
|
||||
return receipt;
|
||||
}
|
||||
|
||||
string RPCSession::eth_sendTransaction(TransactionData const& _td)
|
||||
{
|
||||
return rpcCall("eth_sendTransaction", { _td.toJson() }).asString();
|
||||
}
|
||||
|
||||
string RPCSession::eth_call(TransactionData const& _td, string const& _blockNumber)
|
||||
{
|
||||
return rpcCall("eth_call", { _td.toJson(), quote(_blockNumber) }).asString();
|
||||
}
|
||||
|
||||
string RPCSession::eth_sendTransaction(string const& _transaction)
|
||||
{
|
||||
return rpcCall("eth_sendTransaction", { _transaction }).asString();
|
||||
}
|
||||
|
||||
string RPCSession::eth_getBalance(string const& _address, string const& _blockNumber)
|
||||
{
|
||||
string address = (_address.length() == 20) ? "0x" + _address : _address;
|
||||
return rpcCall("eth_getBalance", { quote(address), quote(_blockNumber) }).asString();
|
||||
}
|
||||
|
||||
string RPCSession::eth_getStorageRoot(string const& _address, string const& _blockNumber)
|
||||
{
|
||||
string address = (_address.length() == 20) ? "0x" + _address : _address;
|
||||
return rpcCall("eth_getStorageRoot", { quote(address), quote(_blockNumber) }).asString();
|
||||
}
|
||||
|
||||
string RPCSession::eth_gasPrice()
|
||||
{
|
||||
return rpcCall("eth_gasPrice").asString();
|
||||
}
|
||||
|
||||
void RPCSession::personal_unlockAccount(string const& _address, string const& _password, int _duration)
|
||||
{
|
||||
BOOST_REQUIRE_MESSAGE(
|
||||
rpcCall("personal_unlockAccount", { quote(_address), quote(_password), to_string(_duration) }),
|
||||
"Error unlocking account " + _address
|
||||
);
|
||||
}
|
||||
|
||||
string RPCSession::personal_newAccount(string const& _password)
|
||||
{
|
||||
string addr = rpcCall("personal_newAccount", { quote(_password) }).asString();
|
||||
BOOST_TEST_MESSAGE("Created account " + addr);
|
||||
return addr;
|
||||
}
|
||||
|
||||
void RPCSession::test_setChainParams(vector<string> const& _accounts)
|
||||
{
|
||||
string forks;
|
||||
if (test::Options::get().evmVersion() >= langutil::EVMVersion::tangerineWhistle())
|
||||
forks += "\"EIP150ForkBlock\": \"0x00\",\n";
|
||||
if (test::Options::get().evmVersion() >= langutil::EVMVersion::spuriousDragon())
|
||||
forks += "\"EIP158ForkBlock\": \"0x00\",\n";
|
||||
if (test::Options::get().evmVersion() >= langutil::EVMVersion::byzantium())
|
||||
{
|
||||
forks += "\"byzantiumForkBlock\": \"0x00\",\n";
|
||||
m_receiptHasStatusField = true;
|
||||
}
|
||||
if (test::Options::get().evmVersion() >= langutil::EVMVersion::constantinople())
|
||||
forks += "\"constantinopleForkBlock\": \"0x00\",\n";
|
||||
if (test::Options::get().evmVersion() >= langutil::EVMVersion::petersburg())
|
||||
forks += "\"constantinopleFixForkBlock\": \"0x00\",\n";
|
||||
static string const c_configString = R"(
|
||||
{
|
||||
"sealEngine": "NoProof",
|
||||
"params": {
|
||||
"accountStartNonce": "0x00",
|
||||
"maximumExtraDataSize": "0x1000000",
|
||||
"blockReward": "0x",
|
||||
"allowFutureBlocks": true,
|
||||
)" + forks + R"(
|
||||
"homesteadForkBlock": "0x00"
|
||||
},
|
||||
"genesis": {
|
||||
"author": "0000000000000010000000000000000000000000",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x",
|
||||
"gasLimit": "0x1000000000000",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"nonce": "0x0000000000000042",
|
||||
"difficulty": "131072"
|
||||
},
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "wei": "1", "precompiled": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } },
|
||||
"0000000000000000000000000000000000000002": { "wei": "1", "precompiled": { "name": "sha256", "linear": { "base": 60, "word": 12 } } },
|
||||
"0000000000000000000000000000000000000003": { "wei": "1", "precompiled": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } },
|
||||
"0000000000000000000000000000000000000004": { "wei": "1", "precompiled": { "name": "identity", "linear": { "base": 15, "word": 3 } } },
|
||||
"0000000000000000000000000000000000000005": { "wei": "1", "precompiled": { "name": "modexp" } },
|
||||
"0000000000000000000000000000000000000006": { "wei": "1", "precompiled": { "name": "alt_bn128_G1_add", "linear": { "base": 500, "word": 0 } } },
|
||||
"0000000000000000000000000000000000000007": { "wei": "1", "precompiled": { "name": "alt_bn128_G1_mul", "linear": { "base": 40000, "word": 0 } } },
|
||||
"0000000000000000000000000000000000000008": { "wei": "1", "precompiled": { "name": "alt_bn128_pairing_product" } }
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
Json::Value config;
|
||||
BOOST_REQUIRE(jsonParseStrict(c_configString, config));
|
||||
for (auto const& account: _accounts)
|
||||
config["accounts"][account]["wei"] = "0x100000000000000000000000000000000000000000";
|
||||
test_setChainParams(jsonCompactPrint(config));
|
||||
}
|
||||
|
||||
void RPCSession::test_setChainParams(string const& _config)
|
||||
{
|
||||
BOOST_REQUIRE(rpcCall("test_setChainParams", { _config }) == true);
|
||||
}
|
||||
|
||||
void RPCSession::test_rewindToBlock(size_t _blockNr)
|
||||
{
|
||||
BOOST_REQUIRE(rpcCall("test_rewindToBlock", { to_string(_blockNr) }) == true);
|
||||
}
|
||||
|
||||
void RPCSession::test_mineBlocks(int _number)
|
||||
{
|
||||
u256 startBlock = fromBigEndian<u256>(fromHex(rpcCall("eth_blockNumber").asString()));
|
||||
BOOST_REQUIRE(rpcCall("test_mineBlocks", { to_string(_number) }, true) == true);
|
||||
BOOST_REQUIRE(fromBigEndian<u256>(fromHex(rpcCall("eth_blockNumber").asString())) == startBlock + _number);
|
||||
}
|
||||
|
||||
void RPCSession::test_modifyTimestamp(size_t _timestamp)
|
||||
{
|
||||
BOOST_REQUIRE(rpcCall("test_modifyTimestamp", { to_string(_timestamp) }) == true);
|
||||
}
|
||||
|
||||
Json::Value RPCSession::rpcCall(string const& _methodName, vector<string> const& _args, bool _canFail)
|
||||
{
|
||||
string request = "{\"jsonrpc\":\"2.0\",\"method\":\"" + _methodName + "\",\"params\":[";
|
||||
for (size_t i = 0; i < _args.size(); ++i)
|
||||
{
|
||||
request += _args[i];
|
||||
if (i + 1 != _args.size())
|
||||
request += ", ";
|
||||
}
|
||||
|
||||
request += "],\"id\":" + to_string(m_rpcSequence) + "}";
|
||||
++m_rpcSequence;
|
||||
|
||||
BOOST_TEST_MESSAGE("Request: " + request);
|
||||
string reply = m_ipcSocket.sendRequest(request);
|
||||
BOOST_TEST_MESSAGE("Reply: " + reply);
|
||||
|
||||
Json::Value result;
|
||||
string errorMsg;
|
||||
if (!jsonParseStrict(reply, result, &errorMsg))
|
||||
BOOST_FAIL("Failed to parse JSON-RPC response: " + errorMsg);
|
||||
|
||||
if (!result.isMember("id") || !result["id"].isUInt())
|
||||
BOOST_FAIL("Badly formatted JSON-RPC response (missing or non-integer \"id\")");
|
||||
if (result["id"].asUInt() != (m_rpcSequence - 1))
|
||||
BOOST_FAIL(
|
||||
"Response identifier mismatch. "
|
||||
"Expected " + to_string(m_rpcSequence - 1) + " but got " + to_string(result["id"].asUInt()) + "."
|
||||
);
|
||||
|
||||
if (result.isMember("error"))
|
||||
{
|
||||
if (_canFail)
|
||||
return Json::Value();
|
||||
|
||||
BOOST_FAIL("Error on JSON-RPC call: " + result["error"]["message"].asString());
|
||||
}
|
||||
|
||||
if (!result.isMember("result") || result["result"].isNull())
|
||||
BOOST_FAIL(
|
||||
"Missing result for JSON-RPC call: " +
|
||||
result.toStyledString() +
|
||||
"\nRequest was " +
|
||||
request
|
||||
);
|
||||
|
||||
return result["result"];
|
||||
}
|
||||
|
||||
string const& RPCSession::accountCreate()
|
||||
{
|
||||
m_accounts.push_back(personal_newAccount(""));
|
||||
personal_unlockAccount(m_accounts.back(), "", 100000);
|
||||
return m_accounts.back();
|
||||
}
|
||||
|
||||
string const& RPCSession::accountCreateIfNotExists(size_t _id)
|
||||
{
|
||||
while ((_id + 1) > m_accounts.size())
|
||||
accountCreate();
|
||||
return m_accounts[_id];
|
||||
}
|
||||
|
||||
RPCSession::RPCSession(string const& _path):
|
||||
m_ipcSocket(_path)
|
||||
{
|
||||
accountCreate();
|
||||
// This will pre-fund the accounts create prior.
|
||||
test_setChainParams(m_accounts);
|
||||
}
|
||||
|
||||
string RPCSession::TransactionData::toJson() const
|
||||
{
|
||||
Json::Value json;
|
||||
json["from"] = (from.length() == 20) ? "0x" + from : from;
|
||||
json["to"] = (to.length() == 20 || to == "") ? "0x" + to : to;
|
||||
json["gas"] = gas;
|
||||
json["gasprice"] = gasPrice;
|
||||
json["value"] = value;
|
||||
json["data"] = data;
|
||||
return jsonCompactPrint(json);
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
/** @file RPCSession.h
|
||||
* @author Dimtiry Khokhlov <dimitry@ethdev.com>
|
||||
* @date 2016
|
||||
*/
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
#include <json/value.h>
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <map>
|
||||
|
||||
#if defined(_WIN32)
|
||||
class IPCSocket : public boost::noncopyable
|
||||
{
|
||||
public:
|
||||
explicit IPCSocket(std::string const& _path);
|
||||
std::string sendRequest(std::string const& _req);
|
||||
~IPCSocket() { CloseHandle(m_socket); }
|
||||
|
||||
std::string const& path() const { return m_path; }
|
||||
|
||||
private:
|
||||
std::string m_path;
|
||||
HANDLE m_socket;
|
||||
TCHAR m_readBuf[512000];
|
||||
};
|
||||
#else
|
||||
class IPCSocket: public boost::noncopyable
|
||||
{
|
||||
public:
|
||||
explicit IPCSocket(std::string const& _path);
|
||||
std::string sendRequest(std::string const& _req);
|
||||
~IPCSocket() {
|
||||
shutdown(m_socket, SHUT_RDWR);
|
||||
close(m_socket);
|
||||
}
|
||||
|
||||
std::string const& path() const { return m_path; }
|
||||
|
||||
private:
|
||||
|
||||
std::string m_path;
|
||||
int m_socket;
|
||||
/// Socket read timeout in milliseconds. Needs to be large because the key generation routine
|
||||
/// might take long.
|
||||
unsigned static constexpr m_readTimeOutMS = 300000;
|
||||
char m_readBuf[512000];
|
||||
};
|
||||
#endif
|
||||
|
||||
class RPCSession: public boost::noncopyable
|
||||
{
|
||||
public:
|
||||
struct TransactionData
|
||||
{
|
||||
std::string from;
|
||||
std::string to;
|
||||
std::string gas;
|
||||
std::string gasPrice;
|
||||
std::string value;
|
||||
std::string data;
|
||||
|
||||
std::string toJson() const;
|
||||
};
|
||||
|
||||
struct LogEntry {
|
||||
std::string address;
|
||||
std::vector<std::string> topics;
|
||||
std::string data;
|
||||
};
|
||||
|
||||
struct TransactionReceipt
|
||||
{
|
||||
std::string gasUsed;
|
||||
std::string contractAddress;
|
||||
std::vector<LogEntry> logEntries;
|
||||
std::string blockNumber;
|
||||
/// note: pre-byzantium the status field will be empty
|
||||
std::string status;
|
||||
};
|
||||
|
||||
static RPCSession& instance(std::string const& _path);
|
||||
|
||||
std::string eth_getCode(std::string const& _address, std::string const& _blockNumber);
|
||||
Json::Value eth_getBlockByNumber(std::string const& _blockNumber, bool _fullObjects);
|
||||
std::string eth_call(TransactionData const& _td, std::string const& _blockNumber);
|
||||
TransactionReceipt eth_getTransactionReceipt(std::string const& _transactionHash);
|
||||
std::string eth_sendTransaction(TransactionData const& _td);
|
||||
std::string eth_sendTransaction(std::string const& _transaction);
|
||||
std::string eth_getBalance(std::string const& _address, std::string const& _blockNumber);
|
||||
std::string eth_getStorageRoot(std::string const& _address, std::string const& _blockNumber);
|
||||
std::string eth_gasPrice();
|
||||
std::string personal_newAccount(std::string const& _password);
|
||||
void personal_unlockAccount(std::string const& _address, std::string const& _password, int _duration);
|
||||
void test_setChainParams(std::vector<std::string> const& _accounts);
|
||||
void test_setChainParams(std::string const& _config);
|
||||
void test_rewindToBlock(size_t _blockNr);
|
||||
void test_modifyTimestamp(size_t _timestamp);
|
||||
void test_mineBlocks(int _number);
|
||||
Json::Value rpcCall(std::string const& _methodName, std::vector<std::string> const& _args = std::vector<std::string>(), bool _canFail = false);
|
||||
|
||||
std::string const& account(size_t _id) const { return m_accounts.at(_id); }
|
||||
std::string const& accountCreate();
|
||||
std::string const& accountCreateIfNotExists(size_t _id);
|
||||
|
||||
private:
|
||||
explicit RPCSession(std::string const& _path);
|
||||
|
||||
inline std::string quote(std::string const& _arg) { return "\"" + _arg + "\""; }
|
||||
/// Parse std::string replacing keywords to values
|
||||
void parseString(std::string& _string, std::map<std::string, std::string> const& _varMap);
|
||||
|
||||
IPCSocket m_ipcSocket;
|
||||
size_t m_rpcSequence = 1;
|
||||
bool m_receiptHasStatusField = false;
|
||||
|
||||
std::vector<std::string> m_accounts;
|
||||
};
|
||||
|
@ -44,7 +44,6 @@ public:
|
||||
struct Config
|
||||
{
|
||||
std::string filename;
|
||||
std::string ipcPath;
|
||||
langutil::EVMVersion evmVersion;
|
||||
};
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include <test/InteractiveTests.h>
|
||||
#include <test/Options.h>
|
||||
#include <test/EVMHost.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
@ -74,13 +75,12 @@ int registerTests(
|
||||
boost::unit_test::test_suite& _suite,
|
||||
boost::filesystem::path const& _basepath,
|
||||
boost::filesystem::path const& _path,
|
||||
std::string const& _ipcPath,
|
||||
TestCase::TestCaseCreator _testCaseCreator
|
||||
)
|
||||
{
|
||||
int numTestsAdded = 0;
|
||||
fs::path fullpath = _basepath / _path;
|
||||
TestCase::Config config{fullpath.string(), _ipcPath, dev::test::Options::get().evmVersion()};
|
||||
TestCase::Config config{fullpath.string(), dev::test::Options::get().evmVersion()};
|
||||
if (fs::is_directory(fullpath))
|
||||
{
|
||||
test_suite* sub_suite = BOOST_TEST_SUITE(_path.filename().string());
|
||||
@ -89,7 +89,7 @@ int registerTests(
|
||||
fs::directory_iterator()
|
||||
))
|
||||
if (fs::is_directory(entry.path()) || TestCase::isTestFilename(entry.path().filename()))
|
||||
numTestsAdded += registerTests(*sub_suite, _basepath, _path / entry.path().filename(), _ipcPath, _testCaseCreator);
|
||||
numTestsAdded += registerTests(*sub_suite, _basepath, _path / entry.path().filename(), _testCaseCreator);
|
||||
_suite.add(sub_suite);
|
||||
}
|
||||
else
|
||||
@ -140,6 +140,14 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] )
|
||||
master.p_name.value = "SolidityTests";
|
||||
dev::test::Options::get().validate();
|
||||
|
||||
bool disableSemantics = !dev::test::EVMHost::getVM(dev::test::Options::get().evmonePath.string());
|
||||
if (disableSemantics)
|
||||
{
|
||||
cout << "Unable to find libevmone.so. Please provide the path using -- --evmonepath <path>." << endl;
|
||||
cout << "You can download it at" << endl;
|
||||
cout << "https://github.com/ethereum/evmone/releases/download/v0.1.0/evmone-0.1.0-linux-x86_64.tar.gz" << endl;
|
||||
cout << endl << "--- SKIPPING ALL SEMANTICS TESTS ---" << endl << endl;
|
||||
}
|
||||
// Include the interactive tests in the automatic tests as well
|
||||
for (auto const& ts: g_interactiveTestsuites)
|
||||
{
|
||||
@ -148,19 +156,18 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] )
|
||||
if (ts.smt && options.disableSMT)
|
||||
continue;
|
||||
|
||||
if (ts.ipc && options.disableIPC)
|
||||
if (ts.needsVM && disableSemantics)
|
||||
continue;
|
||||
|
||||
solAssert(registerTests(
|
||||
master,
|
||||
options.testPath / ts.path,
|
||||
ts.subpath,
|
||||
options.ipcPath.string(),
|
||||
ts.testCaseCreator
|
||||
) > 0, std::string("no ") + ts.title + " tests found");
|
||||
}
|
||||
|
||||
if (dev::test::Options::get().disableIPC)
|
||||
if (disableSemantics)
|
||||
{
|
||||
for (auto suite: {
|
||||
"ABIDecoderTest",
|
||||
|
@ -20,11 +20,14 @@
|
||||
* Tests for a fixed fee registrar contract.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <test/libsolidity/SolidityExecutionFramework.h>
|
||||
#include <test/contracts/ContractInterface.h>
|
||||
#include <test/EVMHost.h>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
using namespace std;
|
||||
using namespace dev::test;
|
||||
@ -413,7 +416,8 @@ BOOST_AUTO_TEST_CASE(auction_simple)
|
||||
registrar.reserve(name);
|
||||
BOOST_CHECK_EQUAL(registrar.owner(name), 0);
|
||||
// "wait" until auction end
|
||||
m_rpc.test_modifyTimestamp(currentTimestamp() + m_biddingTime + 10);
|
||||
|
||||
m_evmHost->m_state.timestamp += m_biddingTime + 10;
|
||||
// trigger auction again
|
||||
registrar.reserve(name);
|
||||
BOOST_CHECK_EQUAL(registrar.owner(name), m_sender);
|
||||
@ -425,7 +429,7 @@ BOOST_AUTO_TEST_CASE(auction_bidding)
|
||||
string name = "x";
|
||||
|
||||
unsigned startTime = 0x776347e2;
|
||||
m_rpc.test_modifyTimestamp(startTime);
|
||||
m_evmHost->m_state.timestamp = startTime;
|
||||
|
||||
RegistrarInterface registrar(*this);
|
||||
// initiate auction
|
||||
@ -433,55 +437,24 @@ BOOST_AUTO_TEST_CASE(auction_bidding)
|
||||
registrar.reserve(name);
|
||||
BOOST_CHECK_EQUAL(registrar.owner(name), 0);
|
||||
// overbid self
|
||||
m_rpc.test_modifyTimestamp(startTime + m_biddingTime - 10);
|
||||
m_evmHost->m_state.timestamp = startTime + m_biddingTime - 10;
|
||||
registrar.setNextValue(12);
|
||||
registrar.reserve(name);
|
||||
// another bid by someone else
|
||||
sendEther(account(1), 10 * ether);
|
||||
m_sender = account(1);
|
||||
m_rpc.test_modifyTimestamp(startTime + 2 * m_biddingTime - 50);
|
||||
m_evmHost->m_state.timestamp = startTime + 2 * m_biddingTime - 50;
|
||||
registrar.setNextValue(13);
|
||||
registrar.reserve(name);
|
||||
BOOST_CHECK_EQUAL(registrar.owner(name), 0);
|
||||
// end auction by first bidder (which is not highest) trying to overbid again (too late)
|
||||
m_sender = account(0);
|
||||
m_rpc.test_modifyTimestamp(startTime + 4 * m_biddingTime);
|
||||
m_evmHost->m_state.timestamp = startTime + 4 * m_biddingTime;
|
||||
registrar.setNextValue(20);
|
||||
registrar.reserve(name);
|
||||
BOOST_CHECK_EQUAL(registrar.owner(name), account(1));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(auction_renewal)
|
||||
{
|
||||
deployRegistrar();
|
||||
|
||||
string name = "x";
|
||||
RegistrarInterface registrar(*this);
|
||||
size_t startTime = currentTimestamp();
|
||||
// register name by auction
|
||||
registrar.setNextValue(8);
|
||||
registrar.reserve(name);
|
||||
m_rpc.test_modifyTimestamp(startTime + 4 * m_biddingTime);
|
||||
registrar.reserve(name);
|
||||
BOOST_CHECK_EQUAL(registrar.owner(name), m_sender);
|
||||
|
||||
// try to re-register before interval end
|
||||
sendEther(account(1), 10 * ether);
|
||||
m_sender = account(1);
|
||||
m_rpc.test_modifyTimestamp(currentTimestamp() + m_renewalInterval - 1);
|
||||
registrar.setNextValue(80);
|
||||
registrar.reserve(name);
|
||||
m_rpc.test_modifyTimestamp(currentTimestamp() + m_biddingTime);
|
||||
// if there is a bug in the renewal logic, this would transfer the ownership to account(1),
|
||||
// but if there is no bug, this will initiate the auction, albeit with a zero bid
|
||||
registrar.reserve(name);
|
||||
BOOST_CHECK_EQUAL(registrar.owner(name), account(0));
|
||||
|
||||
registrar.setNextValue(80);
|
||||
registrar.reserve(name);
|
||||
BOOST_CHECK_EQUAL(registrar.owner(name), account(1));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
}
|
||||
|
@ -974,12 +974,12 @@ struct evmc_instance
|
||||
evmc_execute_fn execute;
|
||||
|
||||
/**
|
||||
* Pointer to function returning capabilities supported by the VM instance.
|
||||
* A method returning capabilities supported by the VM instance.
|
||||
*
|
||||
* The value returned might change when different options are requested via set_option.
|
||||
* The value returned MAY change when different options are set via the set_option() method.
|
||||
*
|
||||
* A Client SHOULD only rely on the value returned here if it has queried it after
|
||||
* it has called set_option.
|
||||
* A Client SHOULD only rely on the value returned if it has queried it after
|
||||
* it has called the set_option().
|
||||
*
|
||||
* This is a mandatory method and MUST NOT be set to NULL.
|
||||
*/
|
||||
|
@ -2,6 +2,7 @@
|
||||
* Copyright 2018-2019 The EVMC Authors.
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <evmc/evmc.h>
|
||||
#include <evmc/helpers.h>
|
||||
@ -104,6 +105,12 @@ public:
|
||||
/// @copydoc evmc_instance::version
|
||||
char const* version() const noexcept { return m_instance->version; }
|
||||
|
||||
/// @copydoc evmc::instance::get_capabilities
|
||||
evmc_capabilities_flagset get_capabilities() const noexcept
|
||||
{
|
||||
return m_instance->get_capabilities(m_instance);
|
||||
}
|
||||
|
||||
/// @copydoc evmc_set_option()
|
||||
evmc_set_option_result set_option(const char name[], const char value[]) noexcept
|
||||
{
|
||||
|
@ -42,18 +42,33 @@
|
||||
#define ATTR_FORMAT(...)
|
||||
#endif
|
||||
|
||||
#if !_WIN32
|
||||
#if _WIN32
|
||||
#define strcpy_sx strcpy_s
|
||||
#else
|
||||
/*
|
||||
* Provide strcpy_s() for GNU libc.
|
||||
* Limited variant of strcpy_s().
|
||||
*
|
||||
* Provided for C standard libraries where strcpy_s() is not available.
|
||||
* The availability check might need to adjusted for other C standard library implementations.
|
||||
*/
|
||||
static void strcpy_s(char* dest, size_t destsz, const char* src)
|
||||
#if !defined(EVMC_LOADER_MOCK)
|
||||
static
|
||||
#endif
|
||||
int
|
||||
strcpy_sx(char* restrict dest, size_t destsz, const char* restrict src)
|
||||
{
|
||||
size_t len = strlen(src);
|
||||
if (len > destsz - 1)
|
||||
len = destsz - 1;
|
||||
if (len >= destsz)
|
||||
{
|
||||
// The input src will not fit into the dest buffer.
|
||||
// Set the first byte of the dest to null to make it effectively empty string
|
||||
// and return error.
|
||||
dest[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
memcpy(dest, src, len);
|
||||
dest[len] = 0;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -124,7 +139,7 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro
|
||||
const char prefix[] = "evmc_create_";
|
||||
const size_t prefix_length = strlen(prefix);
|
||||
char prefixed_name[sizeof(prefix) + PATH_MAX_LENGTH];
|
||||
strcpy_s(prefixed_name, sizeof(prefixed_name), prefix);
|
||||
strcpy_sx(prefixed_name, sizeof(prefixed_name), prefix);
|
||||
|
||||
// Find filename in the path.
|
||||
const char* sep_pos = strrchr(filename, '/');
|
||||
@ -142,7 +157,7 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro
|
||||
name_pos += lib_prefix_length;
|
||||
|
||||
char* base_name = prefixed_name + prefix_length;
|
||||
strcpy_s(base_name, PATH_MAX_LENGTH, name_pos);
|
||||
strcpy_sx(base_name, PATH_MAX_LENGTH, name_pos);
|
||||
|
||||
// Trim the file extension.
|
||||
char* ext_pos = strrchr(prefixed_name, '.');
|
||||
@ -197,21 +212,29 @@ struct evmc_instance* evmc_load_and_create(const char* filename,
|
||||
if (!create_fn)
|
||||
return NULL;
|
||||
|
||||
enum evmc_loader_error_code ec = EVMC_LOADER_SUCCESS;
|
||||
|
||||
struct evmc_instance* instance = create_fn();
|
||||
if (!instance)
|
||||
{
|
||||
*error_code = set_error(EVMC_LOADER_INSTANCE_CREATION_FAILURE,
|
||||
"creating EVMC instance of %s has failed", filename);
|
||||
return NULL;
|
||||
ec = set_error(EVMC_LOADER_INSTANCE_CREATION_FAILURE,
|
||||
"creating EVMC instance of %s has failed", filename);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!evmc_is_abi_compatible(instance))
|
||||
{
|
||||
*error_code = set_error(EVMC_LOADER_ABI_VERSION_MISMATCH,
|
||||
"EVMC ABI version %d of %s mismatches the expected version %d",
|
||||
instance->abi_version, filename, EVMC_ABI_VERSION);
|
||||
return NULL;
|
||||
ec = set_error(EVMC_LOADER_ABI_VERSION_MISMATCH,
|
||||
"EVMC ABI version %d of %s mismatches the expected version %d",
|
||||
instance->abi_version, filename, EVMC_ABI_VERSION);
|
||||
evmc_destroy(instance);
|
||||
instance = NULL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (error_code)
|
||||
*error_code = ec;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
@ -44,10 +44,10 @@ enum evmc_loader_error_code
|
||||
};
|
||||
|
||||
/**
|
||||
* Dynamically loads the shared object (DLL) with an EVM implementation.
|
||||
* Dynamically loads the EVMC module with a VM implementation.
|
||||
*
|
||||
* This function tries to open a DLL at the given `filename`. On UNIX-like systems dlopen() function
|
||||
* is used. On Windows LoadLibrary() function is used.
|
||||
* This function tries to open a dynamically loaded library (DLL) at the given `filename`.
|
||||
* On UNIX-like systems dlopen() function is used. On Windows LoadLibrary() function is used.
|
||||
*
|
||||
* If the file does not exist or is not a valid shared library the ::EVMC_LOADER_CANNOT_OPEN error
|
||||
* code is signaled and NULL is returned.
|
||||
@ -77,28 +77,36 @@ enum evmc_loader_error_code
|
||||
* It is safe to call this function with the same filename argument multiple times
|
||||
* (the DLL is not going to be loaded multiple times).
|
||||
*
|
||||
* @param filename The null terminated path (absolute or relative) to the shared library
|
||||
* containing the EVM implementation. If the value is NULL, an empty C-string
|
||||
* or longer than the path maximum length the ::EVMC_LOADER_INVALID_ARGUMENT is
|
||||
* signaled.
|
||||
* @param filename The null terminated path (absolute or relative) to an EVMC module
|
||||
* (dynamically loaded library) containing the VM implementation.
|
||||
* If the value is NULL, an empty C-string or longer than the path maximum length
|
||||
* the ::EVMC_LOADER_INVALID_ARGUMENT is signaled.
|
||||
* @param error_code The pointer to the error code. If not NULL the value is set to
|
||||
* ::EVMC_LOADER_SUCCESS on success or any other error code as described above.
|
||||
* @return The pointer to the EVM create function or NULL.
|
||||
* @return The pointer to the EVM create function or NULL in case of error.
|
||||
*/
|
||||
evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* error_code);
|
||||
|
||||
/**
|
||||
* Dynamically loads the VM DLL and creates the VM instance.
|
||||
* Dynamically loads the EVMC module and creates the VM instance.
|
||||
*
|
||||
* This is a macro for creating the VM instance with the function returned from evmc_load().
|
||||
* The function signals the same errors as evmc_load() and additionally:
|
||||
* - ::EVMC_LOADER_INSTANCE_CREATION_FAILURE when the create function returns NULL,
|
||||
* - ::EVMC_LOADER_ABI_VERSION_MISMATCH when the created VM instance has ABI version different
|
||||
* from the ABI version of this library (::EVMC_ABI_VERSION).
|
||||
* - ::EVMC_LOADER_INSTANCE_CREATION_FAILURE when the create function returns NULL,
|
||||
* - ::EVMC_LOADER_ABI_VERSION_MISMATCH when the created VM instance has ABI version different
|
||||
* from the ABI version of this library (::EVMC_ABI_VERSION).
|
||||
*
|
||||
* It is safe to call this function with the same filename argument multiple times:
|
||||
* the DLL is not going to be loaded multiple times, but the function will return new VM instance
|
||||
* each time.
|
||||
*
|
||||
* @param filename The null terminated path (absolute or relative) to an EVMC module
|
||||
* (dynamically loaded library) containing the VM implementation.
|
||||
* If the value is NULL, an empty C-string or longer than the path maximum length
|
||||
* the ::EVMC_LOADER_INVALID_ARGUMENT is signaled.
|
||||
* @param error_code The pointer to the error code. If not NULL the value is set to
|
||||
* ::EVMC_LOADER_SUCCESS on success or any other error code as described above.
|
||||
* @return The pointer to the created VM or NULL in case of error.
|
||||
*/
|
||||
struct evmc_instance* evmc_load_and_create(const char* filename,
|
||||
enum evmc_loader_error_code* error_code);
|
||||
|
@ -377,11 +377,11 @@ BOOST_AUTO_TEST_CASE(transfer_ownership)
|
||||
BOOST_REQUIRE(callContractFunction("setOwner(bytes32,address)", 0x00, ACCOUNT(1)) == encodeArgs());
|
||||
|
||||
// Check that an event was raised and contents are correct.
|
||||
BOOST_REQUIRE(m_logs.size() == 1);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(ACCOUNT(1)));
|
||||
BOOST_REQUIRE(m_logs[0].topics.size() == 2);
|
||||
BOOST_CHECK(m_logs[0].topics[0] == keccak256(string("Transfer(bytes32,address)")));
|
||||
BOOST_CHECK(m_logs[0].topics[1] == u256(0x00));
|
||||
BOOST_REQUIRE(numLogs() == 1);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(ACCOUNT(1)));
|
||||
BOOST_REQUIRE(numLogTopics(0) == 2);
|
||||
BOOST_CHECK(logTopic(0, 0) == keccak256(string("Transfer(bytes32,address)")));
|
||||
BOOST_CHECK(logTopic(0, 1) == u256(0x00));
|
||||
|
||||
// Verify that owner of 0x00 is now account(1).
|
||||
BOOST_CHECK(callContractFunction("owner(bytes32)", 0x00) == encodeArgs(ACCOUNT(1)));
|
||||
@ -406,11 +406,11 @@ BOOST_AUTO_TEST_CASE(set_resolver)
|
||||
BOOST_REQUIRE(callContractFunction("setResolver(bytes32,address)", 0x00, ACCOUNT(1)) == encodeArgs());
|
||||
|
||||
// Check that an event was raised and contents are correct.
|
||||
BOOST_REQUIRE(m_logs.size() == 1);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(ACCOUNT(1)));
|
||||
BOOST_REQUIRE(m_logs[0].topics.size() == 2);
|
||||
BOOST_CHECK(m_logs[0].topics[0] == keccak256(string("NewResolver(bytes32,address)")));
|
||||
BOOST_CHECK(m_logs[0].topics[1] == u256(0x00));
|
||||
BOOST_REQUIRE(numLogs() == 1);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(ACCOUNT(1)));
|
||||
BOOST_REQUIRE(numLogTopics(0) == 2);
|
||||
BOOST_CHECK(logTopic(0, 0) == keccak256(string("NewResolver(bytes32,address)")));
|
||||
BOOST_CHECK(logTopic(0, 1) == u256(0x00));
|
||||
|
||||
// Verify that the resolver is changed to account(1).
|
||||
BOOST_CHECK(callContractFunction("resolver(bytes32)", 0x00) == encodeArgs(ACCOUNT(1)));
|
||||
@ -435,11 +435,11 @@ BOOST_AUTO_TEST_CASE(set_ttl)
|
||||
BOOST_REQUIRE(callContractFunction("setTTL(bytes32,uint64)", 0x00, 3600) == encodeArgs());
|
||||
|
||||
// Check that an event was raised and contents are correct.
|
||||
BOOST_REQUIRE(m_logs.size() == 1);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(3600));
|
||||
BOOST_REQUIRE(m_logs[0].topics.size() == 2);
|
||||
BOOST_CHECK(m_logs[0].topics[0] == keccak256(string("NewTTL(bytes32,uint64)")));
|
||||
BOOST_CHECK(m_logs[0].topics[1] == u256(0x00));
|
||||
BOOST_REQUIRE(numLogs() == 1);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(3600));
|
||||
BOOST_REQUIRE(numLogTopics(0) == 2);
|
||||
BOOST_CHECK(logTopic(0, 0) == keccak256(string("NewTTL(bytes32,uint64)")));
|
||||
BOOST_CHECK(logTopic(0, 1) == u256(0x00));
|
||||
|
||||
// Verify that the TTL has been set.
|
||||
BOOST_CHECK(callContractFunction("ttl(bytes32)", 0x00) == encodeArgs(3600));
|
||||
@ -464,12 +464,12 @@ BOOST_AUTO_TEST_CASE(create_subnode)
|
||||
BOOST_REQUIRE(callContractFunction("setSubnodeOwner(bytes32,bytes32,address)", 0x00, keccak256(string("eth")), ACCOUNT(1)) == encodeArgs());
|
||||
|
||||
// Check that an event was raised and contents are correct.
|
||||
BOOST_REQUIRE(m_logs.size() == 1);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(ACCOUNT(1)));
|
||||
BOOST_REQUIRE(m_logs[0].topics.size() == 3);
|
||||
BOOST_CHECK(m_logs[0].topics[0] == keccak256(string("NewOwner(bytes32,bytes32,address)")));
|
||||
BOOST_CHECK(m_logs[0].topics[1] == u256(0x00));
|
||||
BOOST_CHECK(m_logs[0].topics[2] == keccak256(string("eth")));
|
||||
BOOST_REQUIRE(numLogs() == 1);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(ACCOUNT(1)));
|
||||
BOOST_REQUIRE(numLogTopics(0) == 3);
|
||||
BOOST_CHECK(logTopic(0, 0) == keccak256(string("NewOwner(bytes32,bytes32,address)")));
|
||||
BOOST_CHECK(logTopic(0, 1) == u256(0x00));
|
||||
BOOST_CHECK(logTopic(0, 2) == keccak256(string("eth")));
|
||||
|
||||
// Verify that the sub-node owner is now account(1).
|
||||
u256 namehash = keccak256(h256(0x00).asBytes() + keccak256("eth").asBytes());
|
||||
|
@ -494,12 +494,12 @@ BOOST_AUTO_TEST_CASE(transfer_event)
|
||||
BOOST_REQUIRE(callContractFunction("transfer(address,uint256)", ACCOUNT(1), u256(transfer)) == SUCCESS);
|
||||
|
||||
// Check that a Transfer event was recorded and contents are correct.
|
||||
BOOST_REQUIRE(m_logs.size() == 1);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(transfer));
|
||||
BOOST_REQUIRE(m_logs[0].topics.size() == 3);
|
||||
BOOST_CHECK(m_logs[0].topics[0] == keccak256(string("Transfer(address,address,uint256)")));
|
||||
BOOST_CHECK(m_logs[0].topics[1] == ACCOUNT(0));
|
||||
BOOST_CHECK(m_logs[0].topics[2] == ACCOUNT(1));
|
||||
BOOST_REQUIRE(numLogs() == 1);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(transfer));
|
||||
BOOST_REQUIRE(numLogTopics(0) == 3);
|
||||
BOOST_CHECK(logTopic(0, 0) == keccak256(string("Transfer(address,address,uint256)")));
|
||||
BOOST_CHECK(logTopic(0, 1) == ACCOUNT(0));
|
||||
BOOST_CHECK(logTopic(0, 2) == ACCOUNT(1));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(transfer_zero_no_event)
|
||||
@ -512,7 +512,7 @@ BOOST_AUTO_TEST_CASE(transfer_zero_no_event)
|
||||
BOOST_REQUIRE(callContractFunction("transfer(address,uint256)", ACCOUNT(1), u256(transfer)) == SUCCESS);
|
||||
|
||||
// Check that no Event was recorded.
|
||||
BOOST_CHECK(m_logs.size() == 0);
|
||||
BOOST_CHECK(numLogs() == 0);
|
||||
|
||||
// Check that balances have not changed.
|
||||
BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(0)) == encodeArgs(TOKENSUPPLY - transfer));
|
||||
@ -529,12 +529,12 @@ BOOST_AUTO_TEST_CASE(approval_and_transfer_events)
|
||||
BOOST_REQUIRE(callContractFunction("approve(address,uint256)", ACCOUNT(1), u256(allow)) == SUCCESS);
|
||||
|
||||
// Check that an Approval event was recorded and contents are correct.
|
||||
BOOST_REQUIRE(m_logs.size() == 1);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(allow));
|
||||
BOOST_REQUIRE(m_logs[0].topics.size() == 3);
|
||||
BOOST_CHECK(m_logs[0].topics[0] == keccak256(string("Approval(address,address,uint256)")));
|
||||
BOOST_CHECK(m_logs[0].topics[1] == ACCOUNT(0));
|
||||
BOOST_CHECK(m_logs[0].topics[2] == ACCOUNT(1));
|
||||
BOOST_REQUIRE(numLogs() == 1);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(allow));
|
||||
BOOST_REQUIRE(numLogTopics(0) == 3);
|
||||
BOOST_CHECK(logTopic(0, 0) == keccak256(string("Approval(address,address,uint256)")));
|
||||
BOOST_CHECK(logTopic(0, 1) == ACCOUNT(0));
|
||||
BOOST_CHECK(logTopic(0, 2) == ACCOUNT(1));
|
||||
|
||||
// Send account(1) some ether for gas.
|
||||
sendEther(account(1), 1000 * ether);
|
||||
@ -546,12 +546,12 @@ BOOST_AUTO_TEST_CASE(approval_and_transfer_events)
|
||||
BOOST_REQUIRE(callContractFunction("transferFrom(address,address,uint256)", ACCOUNT(0), ACCOUNT(2), u256(transfer)) == SUCCESS);
|
||||
|
||||
// Check that a Transfer event was recorded and contents are correct.
|
||||
BOOST_REQUIRE(m_logs.size() == 1);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(transfer));
|
||||
BOOST_REQUIRE(m_logs[0].topics.size() == 3);
|
||||
BOOST_CHECK(m_logs[0].topics[0] == keccak256(string("Transfer(address,address,uint256)")));
|
||||
BOOST_CHECK(m_logs[0].topics[1] == ACCOUNT(0));
|
||||
BOOST_CHECK(m_logs[0].topics[2] == ACCOUNT(2));
|
||||
BOOST_REQUIRE(numLogs() == 1);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(transfer));
|
||||
BOOST_REQUIRE(numLogTopics(0) == 3);
|
||||
BOOST_CHECK(logTopic(0, 0) == keccak256(string("Transfer(address,address,uint256)")));
|
||||
BOOST_CHECK(logTopic(0, 1) == ACCOUNT(0));
|
||||
BOOST_CHECK(logTopic(0, 2) == ACCOUNT(2));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(invalid_transfer_1)
|
||||
|
@ -43,9 +43,9 @@ namespace test
|
||||
{
|
||||
|
||||
#define REQUIRE_LOG_DATA(DATA) do { \
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1); \
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); \
|
||||
ABI_CHECK(m_logs[0].data, DATA); \
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1); \
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); \
|
||||
ABI_CHECK(logData(0), DATA); \
|
||||
} while (false)
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(ABIEncoderTest, SolidityExecutionFramework)
|
||||
@ -451,7 +451,7 @@ BOOST_AUTO_TEST_CASE(structs)
|
||||
);
|
||||
BOOST_CHECK(callContractFunction("f()") == encoded);
|
||||
REQUIRE_LOG_DATA(encoded);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("e(uint16,(uint16,uint16,(uint64[2])[],uint16))")));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("e(uint16,(uint16,uint16,(uint64[2])[],uint16))")));
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -36,8 +36,8 @@ using namespace boost::unit_test;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
|
||||
SemanticTest::SemanticTest(string const& _filename, string const& _ipcPath, langutil::EVMVersion _evmVersion):
|
||||
SolidityExecutionFramework(_ipcPath, _evmVersion)
|
||||
SemanticTest::SemanticTest(string const& _filename, langutil::EVMVersion _evmVersion):
|
||||
SolidityExecutionFramework(_evmVersion)
|
||||
{
|
||||
ifstream file(_filename);
|
||||
soltestAssert(file, "Cannot open test contract: \"" + _filename + "\".");
|
||||
|
@ -44,9 +44,9 @@ class SemanticTest: public SolidityExecutionFramework, public EVMVersionRestrict
|
||||
{
|
||||
public:
|
||||
static std::unique_ptr<TestCase> create(Config const& _options)
|
||||
{ return std::make_unique<SemanticTest>(_options.filename, _options.ipcPath, _options.evmVersion); }
|
||||
{ return std::make_unique<SemanticTest>(_options.filename, _options.evmVersion); }
|
||||
|
||||
explicit SemanticTest(std::string const& _filename, std::string const& _ipcPath, langutil::EVMVersion _evmVersion);
|
||||
explicit SemanticTest(std::string const& _filename, langutil::EVMVersion _evmVersion);
|
||||
|
||||
TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool _formatted = false) override;
|
||||
void printSource(std::ostream &_stream, std::string const& _linePrefix = "", bool _formatted = false) const override;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <test/libsolidity/SolidityExecutionFramework.h>
|
||||
|
||||
#include <test/Options.h>
|
||||
#include <test/EVMHost.h>
|
||||
|
||||
#include <liblangutil/Exceptions.h>
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
@ -1133,8 +1134,12 @@ BOOST_AUTO_TEST_CASE(blockchain)
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(m_rpc.rpcCall("miner_setEtherbase", {"\"0x1212121212121212121212121212121212121212\""}).asBool() == true);
|
||||
m_rpc.test_mineBlocks(5);
|
||||
m_evmHost->m_coinbase = EVMHost::convertToEVMC(Address("0x1212121212121212121212121212121212121212"));
|
||||
m_evmHost->newBlock();
|
||||
m_evmHost->newBlock();
|
||||
m_evmHost->newBlock();
|
||||
m_evmHost->newBlock();
|
||||
m_evmHost->newBlock();
|
||||
compileAndRun(sourceCode, 27);
|
||||
ABI_CHECK(callContractFunctionWithValue("someInfo()", 28), encodeArgs(28, u256("0x1212121212121212121212121212121212121212"), 7));
|
||||
}
|
||||
@ -1184,10 +1189,10 @@ BOOST_AUTO_TEST_CASE(now)
|
||||
)";
|
||||
ALSO_VIA_YUL(
|
||||
compileAndRun(sourceCode);
|
||||
u256 startBlock = m_blockNumber;
|
||||
u256 startBlock = blockNumber();
|
||||
size_t startTime = blockTimestamp(startBlock);
|
||||
auto ret = callContractFunction("someInfo()");
|
||||
u256 endBlock = m_blockNumber;
|
||||
u256 endBlock = blockNumber();
|
||||
size_t endTime = blockTimestamp(endBlock);
|
||||
BOOST_CHECK(startBlock != endBlock);
|
||||
BOOST_CHECK(startTime != endTime);
|
||||
@ -1276,10 +1281,10 @@ BOOST_AUTO_TEST_CASE(log0)
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
callContractFunction("a()");
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1)));
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics.size(), 0);
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
|
||||
BOOST_CHECK_EQUAL(numLogTopics(0), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(log1)
|
||||
@ -1293,11 +1298,11 @@ BOOST_AUTO_TEST_CASE(log1)
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
callContractFunction("a()");
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1)));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], h256(u256(2)));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), h256(u256(2)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(log2)
|
||||
@ -1311,12 +1316,12 @@ BOOST_AUTO_TEST_CASE(log2)
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
callContractFunction("a()");
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1)));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
|
||||
for (unsigned i = 0; i < 2; ++i)
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[i], h256(u256(i + 2)));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(log3)
|
||||
@ -1330,12 +1335,12 @@ BOOST_AUTO_TEST_CASE(log3)
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
callContractFunction("a()");
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1)));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 3);
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 3);
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[i], h256(u256(i + 2)));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(log4)
|
||||
@ -1349,12 +1354,12 @@ BOOST_AUTO_TEST_CASE(log4)
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
callContractFunction("a()");
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1)));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 4);
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 4);
|
||||
for (unsigned i = 0; i < 4; ++i)
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[i], h256(u256(i + 2)));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(log_in_constructor)
|
||||
@ -1367,11 +1372,11 @@ BOOST_AUTO_TEST_CASE(log_in_constructor)
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1)));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], h256(u256(2)));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), h256(u256(2)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(selfdestruct)
|
||||
@ -2615,13 +2620,13 @@ BOOST_AUTO_TEST_CASE(event)
|
||||
for (bool manually: {true, false})
|
||||
{
|
||||
callContractFunctionWithValue("deposit(bytes32,bool)", value, id, manually);
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(value)));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 3);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,bytes32,uint256)")));
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[1], h256(m_sender, h256::AlignRight));
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[2], h256(id));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(value)));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 3);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address,bytes32,uint256)")));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 1), h256(m_sender, h256::AlignRight));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 2), h256(id));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2640,13 +2645,13 @@ BOOST_AUTO_TEST_CASE(event_emit)
|
||||
u256 value(18);
|
||||
u256 id(0x1234);
|
||||
callContractFunctionWithValue("deposit(bytes32)", value, id);
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(value)));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 3);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,bytes32,uint256)")));
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[1], h256(m_sender, h256::AlignRight));
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[2], h256(id));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(value)));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 3);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address,bytes32,uint256)")));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 1), h256(m_sender, h256::AlignRight));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 2), h256(id));
|
||||
)
|
||||
}
|
||||
|
||||
@ -2664,11 +2669,11 @@ BOOST_AUTO_TEST_CASE(event_no_arguments)
|
||||
ALSO_VIA_YUL(
|
||||
compileAndRun(sourceCode);
|
||||
callContractFunction("deposit()");
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data.empty());
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit()")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0).empty());
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit()")));
|
||||
)
|
||||
}
|
||||
|
||||
@ -2687,11 +2692,11 @@ BOOST_AUTO_TEST_CASE(event_access_through_base_name_emit)
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
callContractFunction("f()");
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data.empty());
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("x()")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0).empty());
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("x()")));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(events_with_same_name)
|
||||
@ -2725,32 +2730,32 @@ BOOST_AUTO_TEST_CASE(events_with_same_name)
|
||||
ALSO_VIA_YUL(
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("deposit()"), encodeArgs(u256(1)));
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data.empty());
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit()")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0).empty());
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit()")));
|
||||
|
||||
ABI_CHECK(callContractFunction("deposit(address)", c_loggedAddress), encodeArgs(u256(2)));
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
ABI_CHECK(m_logs[0].data, encodeArgs(c_loggedAddress));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address)")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
ABI_CHECK(logData(0), encodeArgs(c_loggedAddress));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address)")));
|
||||
|
||||
ABI_CHECK(callContractFunction("deposit(address,uint256)", c_loggedAddress, u256(100)), encodeArgs(u256(3)));
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
ABI_CHECK(m_logs[0].data, encodeArgs(c_loggedAddress, 100));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,uint256)")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
ABI_CHECK(logData(0), encodeArgs(c_loggedAddress, 100));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address,uint256)")));
|
||||
|
||||
ABI_CHECK(callContractFunction("deposit(address,bool)", c_loggedAddress, false), encodeArgs(u256(4)));
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
ABI_CHECK(m_logs[0].data, encodeArgs(c_loggedAddress, false));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,bool)")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
ABI_CHECK(logData(0), encodeArgs(c_loggedAddress, false));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address,bool)")));
|
||||
)
|
||||
}
|
||||
|
||||
@ -2786,25 +2791,25 @@ BOOST_AUTO_TEST_CASE(events_with_same_name_inherited_emit)
|
||||
ALSO_VIA_YUL(
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("deposit()"), encodeArgs(u256(1)));
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data.empty());
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit()")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0).empty());
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit()")));
|
||||
|
||||
ABI_CHECK(callContractFunction("deposit(address)", c_loggedAddress), encodeArgs(u256(1)));
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(c_loggedAddress));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address)")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(c_loggedAddress));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address)")));
|
||||
|
||||
ABI_CHECK(callContractFunction("deposit(address,uint256)", c_loggedAddress, u256(100)), encodeArgs(u256(1)));
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
ABI_CHECK(m_logs[0].data, encodeArgs(c_loggedAddress, 100));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,uint256)")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
ABI_CHECK(logData(0), encodeArgs(c_loggedAddress, 100));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address,uint256)")));
|
||||
)
|
||||
}
|
||||
|
||||
@ -2821,7 +2826,7 @@ BOOST_AUTO_TEST_CASE(event_anonymous)
|
||||
ALSO_VIA_YUL(
|
||||
compileAndRun(sourceCode);
|
||||
callContractFunction("deposit()");
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 0);
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 0);
|
||||
)
|
||||
}
|
||||
|
||||
@ -2840,14 +2845,14 @@ BOOST_AUTO_TEST_CASE(event_anonymous_with_topics)
|
||||
u256 value(18);
|
||||
u256 id(0x1234);
|
||||
callContractFunctionWithValue("deposit(bytes32)", value, id);
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs("abc"));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 4);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], h256(m_sender, h256::AlignRight));
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[1], h256(id));
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[2], h256(value));
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[3], h256(2));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0) == encodeArgs("abc"));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 4);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), h256(m_sender, h256::AlignRight));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 1), h256(id));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 2), h256(value));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 3), h256(2));
|
||||
)
|
||||
}
|
||||
|
||||
@ -2866,11 +2871,11 @@ BOOST_AUTO_TEST_CASE(event_lots_of_data)
|
||||
u256 value(18);
|
||||
u256 id(0x1234);
|
||||
callContractFunctionWithValue("deposit(bytes32)", value, id);
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs((u160)m_sender, id, value, true));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,bytes32,uint256,bool)")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0) == encodeArgs((u160)m_sender, id, value, true));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address,bytes32,uint256,bool)")));
|
||||
)
|
||||
}
|
||||
|
||||
@ -2886,11 +2891,11 @@ BOOST_AUTO_TEST_CASE(event_really_lots_of_data)
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
callContractFunction("deposit()");
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(toHex(m_logs[0].data), toHex(encodeArgs(10, 0x60, 15, 4, asString(FixedHash<4>(dev::keccak256("deposit()")).asBytes()))));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(toHex(logData(0)), toHex(encodeArgs(10, 0x60, 15, 4, asString(FixedHash<4>(dev::keccak256("deposit()")).asBytes()))));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(event_really_lots_of_data_from_storage)
|
||||
@ -2910,11 +2915,11 @@ BOOST_AUTO_TEST_CASE(event_really_lots_of_data_from_storage)
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
callContractFunction("deposit()");
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(toHex(m_logs[0].data), toHex(encodeArgs(10, 0x60, 15, 3, string("ABC"))));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK_EQUAL(toHex(logData(0)), toHex(encodeArgs(10, 0x60, 15, 3, string("ABC"))));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(event_really_really_lots_of_data_from_storage)
|
||||
@ -2935,11 +2940,11 @@ BOOST_AUTO_TEST_CASE(event_really_really_lots_of_data_from_storage)
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
callContractFunction("deposit()");
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(10, 0x60, 15, 31, string("ABC") + string(27, 0) + "Z"));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(10, 0x60, 15, 31, string("ABC") + string(27, 0) + "Z"));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(event_struct_memory_v2)
|
||||
@ -2957,11 +2962,11 @@ BOOST_AUTO_TEST_CASE(event_struct_memory_v2)
|
||||
compileAndRun(sourceCode);
|
||||
u256 x(42);
|
||||
callContractFunction("createEvent(uint256)", x);
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(x));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint256))")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(x));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E((uint256))")));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(event_struct_storage_v2)
|
||||
@ -2981,11 +2986,11 @@ BOOST_AUTO_TEST_CASE(event_struct_storage_v2)
|
||||
compileAndRun(sourceCode);
|
||||
u256 x(42);
|
||||
callContractFunction("createEvent(uint256)", x);
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(x));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint256))")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(x));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E((uint256))")));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(event_dynamic_array_memory)
|
||||
@ -3005,11 +3010,11 @@ BOOST_AUTO_TEST_CASE(event_dynamic_array_memory)
|
||||
compileAndRun(sourceCode);
|
||||
u256 x(42);
|
||||
callContractFunction("createEvent(uint256)", x);
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(0x20, 3, x, x + 1, x + 2));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(uint256[])")));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(event_dynamic_array_memory_v2)
|
||||
@ -3030,11 +3035,11 @@ BOOST_AUTO_TEST_CASE(event_dynamic_array_memory_v2)
|
||||
compileAndRun(sourceCode);
|
||||
u256 x(42);
|
||||
callContractFunction("createEvent(uint256)", x);
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(0x20, 3, x, x + 1, x + 2));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(uint256[])")));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(event_dynamic_nested_array_memory_v2)
|
||||
@ -3058,11 +3063,11 @@ BOOST_AUTO_TEST_CASE(event_dynamic_nested_array_memory_v2)
|
||||
compileAndRun(sourceCode);
|
||||
u256 x(42);
|
||||
callContractFunction("createEvent(uint256)", x);
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 2, 0x40, 0xa0, 2, x, x + 1, 2, x + 2, x + 3));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[][])")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(0x20, 2, 0x40, 0xa0, 2, x, x + 1, 2, x + 2, x + 3));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(uint256[][])")));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(event_dynamic_array_storage)
|
||||
@ -3084,11 +3089,11 @@ BOOST_AUTO_TEST_CASE(event_dynamic_array_storage)
|
||||
compileAndRun(sourceCode);
|
||||
u256 x(42);
|
||||
callContractFunction("createEvent(uint256)", x);
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(0x20, 3, x, x + 1, x + 2));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(uint256[])")));
|
||||
)
|
||||
}
|
||||
|
||||
@ -3112,11 +3117,11 @@ BOOST_AUTO_TEST_CASE(event_dynamic_array_storage_v2)
|
||||
compileAndRun(sourceCode);
|
||||
u256 x(42);
|
||||
callContractFunction("createEvent(uint256)", x);
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(0x20, 3, x, x + 1, x + 2));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(uint256[])")));
|
||||
)
|
||||
}
|
||||
|
||||
@ -3143,11 +3148,11 @@ BOOST_AUTO_TEST_CASE(event_dynamic_nested_array_storage_v2)
|
||||
compileAndRun(sourceCode);
|
||||
u256 x(42);
|
||||
callContractFunction("createEvent(uint256)", x);
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 2, 0x40, 0xa0, 2, x, x + 1, 2, x + 2, x + 3));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[][])")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(0x20, 2, 0x40, 0xa0, 2, x, x + 1, 2, x + 2, x + 3));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(uint256[][])")));
|
||||
);
|
||||
}
|
||||
|
||||
@ -3172,18 +3177,18 @@ BOOST_AUTO_TEST_CASE(event_indexed_string)
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
callContractFunction("deposit()");
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
string dynx(90, 0);
|
||||
for (size_t i = 0; i < dynx.size(); ++i)
|
||||
dynx[i] = i;
|
||||
BOOST_CHECK(m_logs[0].data == bytes());
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 3);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(dynx));
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[2], dev::keccak256(
|
||||
BOOST_CHECK(logData(0) == bytes());
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 3);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 1), dev::keccak256(dynx));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 2), dev::keccak256(
|
||||
encodeArgs(u256(4), u256(5), u256(6), u256(7))
|
||||
));
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(string,uint256[4])")));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(string,uint256[4])")));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
|
||||
@ -3981,11 +3986,11 @@ BOOST_AUTO_TEST_CASE(storing_invalid_boolean)
|
||||
ABI_CHECK(callContractFunction("perm()"), encodeArgs(1));
|
||||
ABI_CHECK(callContractFunction("ret()"), encodeArgs(1));
|
||||
ABI_CHECK(callContractFunction("ev()"), encodeArgs(1));
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_CHECK(m_logs[0].data == encodeArgs(1));
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Ev(bool)")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_CHECK(logData(0) == encodeArgs(1));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Ev(bool)")));
|
||||
}
|
||||
|
||||
|
||||
@ -5907,11 +5912,11 @@ BOOST_AUTO_TEST_CASE(invalid_enum_logged)
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "C");
|
||||
ABI_CHECK(callContractFunction("test_log_ok()"), encodeArgs(u256(1)));
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Log(uint8)")));
|
||||
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(0)));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
|
||||
BOOST_REQUIRE_EQUAL(logTopic(0, 0), dev::keccak256(string("Log(uint8)")));
|
||||
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(0)));
|
||||
|
||||
// should throw
|
||||
ABI_CHECK(callContractFunction("test_log()"), encodeArgs());
|
||||
@ -13554,13 +13559,13 @@ BOOST_AUTO_TEST_CASE(abi_encodePackedV2_structs)
|
||||
compileAndRun(sourceCode, 0, "C");
|
||||
bytes structEnc = encodeArgs(int(0x12), u256(-7), int(2), int(3), u256(-7), u256(-8));
|
||||
ABI_CHECK(callContractFunction("testStorage()"), encodeArgs());
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint8,int16,uint8[2],int16[]))")));
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(structEnc)));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E((uint8,int16,uint8[2],int16[]))")));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 1), dev::keccak256(asString(structEnc)));
|
||||
ABI_CHECK(callContractFunction("testMemory()"), encodeArgs());
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint8,int16,uint8[2],int16[]))")));
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(structEnc)));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E((uint8,int16,uint8[2],int16[]))")));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 1), dev::keccak256(asString(structEnc)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(abi_encodePackedV2_nestedArray)
|
||||
@ -13587,9 +13592,9 @@ BOOST_AUTO_TEST_CASE(abi_encodePackedV2_nestedArray)
|
||||
compileAndRun(sourceCode, 0, "C");
|
||||
bytes structEnc = encodeArgs(1, 2, 3, 0, 0, 0, 0, 4);
|
||||
ABI_CHECK(callContractFunction("testNestedArrays()"), encodeArgs());
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint8,int16)[2][][3])")));
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(structEnc)));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E((uint8,int16)[2][][3])")));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 1), dev::keccak256(asString(structEnc)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(abi_encodePackedV2_arrayOfStrings)
|
||||
@ -13616,13 +13621,13 @@ BOOST_AUTO_TEST_CASE(abi_encodePackedV2_arrayOfStrings)
|
||||
compileAndRun(sourceCode, 0, "C");
|
||||
bytes arrayEncoding = encodeArgs("abc", "0123456789012345678901234567890123456789");
|
||||
ABI_CHECK(callContractFunction("testStorage()"), encodeArgs());
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(string[])")));
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(arrayEncoding)));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(string[])")));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 1), dev::keccak256(asString(arrayEncoding)));
|
||||
ABI_CHECK(callContractFunction("testMemory()"), encodeArgs());
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(string[])")));
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(arrayEncoding)));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(string[])")));
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 1), dev::keccak256(asString(arrayEncoding)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(event_signature_in_library)
|
||||
@ -13649,8 +13654,8 @@ BOOST_AUTO_TEST_CASE(event_signature_in_library)
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "C");
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint8,int16),(uint8,int16))")));
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E((uint8,int16),(uint8,int16))")));
|
||||
}
|
||||
|
||||
|
||||
@ -14730,10 +14735,10 @@ BOOST_AUTO_TEST_CASE(event_wrong_abi_name)
|
||||
u256 id(0x1234);
|
||||
|
||||
callContractFunction("f()");
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 3);
|
||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,bytes32,uint256)")));
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
|
||||
BOOST_REQUIRE_EQUAL(numLogTopics(0), 3);
|
||||
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address,bytes32,uint256)")));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(uninitialized_internal_storage_function)
|
||||
@ -14801,10 +14806,10 @@ BOOST_AUTO_TEST_CASE(dirty_scratch_space_prior_to_constant_optimiser)
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "C");
|
||||
BOOST_REQUIRE_EQUAL(m_logs.size(), 2);
|
||||
BOOST_CHECK_EQUAL(m_logs[1].address, m_contractAddress);
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 2);
|
||||
BOOST_CHECK_EQUAL(logAddress(1), m_contractAddress);
|
||||
ABI_CHECK(
|
||||
m_logs[1].data,
|
||||
logData(1),
|
||||
encodeArgs(u256("0x0000000000001234123412431234123412412342112341234124312341234124"))
|
||||
);
|
||||
}
|
||||
|
@ -30,16 +30,6 @@ using namespace dev::solidity;
|
||||
using namespace dev::solidity::test;
|
||||
using namespace std;
|
||||
|
||||
SolidityExecutionFramework::SolidityExecutionFramework():
|
||||
ExecutionFramework()
|
||||
{
|
||||
}
|
||||
|
||||
SolidityExecutionFramework::SolidityExecutionFramework(std::string const& _ipcPath, langutil::EVMVersion _evmVersion):
|
||||
ExecutionFramework(_ipcPath, _evmVersion)
|
||||
{
|
||||
}
|
||||
|
||||
bytes SolidityExecutionFramework::compileContract(
|
||||
string const& _sourceCode,
|
||||
string const& _contractName,
|
||||
|
@ -45,8 +45,10 @@ class SolidityExecutionFramework: public dev::test::ExecutionFramework
|
||||
{
|
||||
|
||||
public:
|
||||
SolidityExecutionFramework();
|
||||
SolidityExecutionFramework(std::string const& _ipcPath, langutil::EVMVersion _evmVersion);
|
||||
SolidityExecutionFramework() {}
|
||||
explicit SolidityExecutionFramework(langutil::EVMVersion _evmVersion):
|
||||
ExecutionFramework(_evmVersion)
|
||||
{}
|
||||
|
||||
virtual bytes const& compileAndRunWithoutCheck(
|
||||
std::string const& _sourceCode,
|
||||
|
@ -485,7 +485,15 @@ BOOST_AUTO_TEST_CASE(constant_optimization_early_exit)
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
compileBothVersions(sourceCode);
|
||||
double duration = std::chrono::duration<double>(std::chrono::steady_clock::now() - start).count();
|
||||
BOOST_CHECK_MESSAGE(duration < 20, "Compilation of constants took longer than 20 seconds.");
|
||||
// Since run time on an ASan build is not really realistic, we disable this test for those builds.
|
||||
size_t maxDuration = 20;
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(address_sanitizer)
|
||||
maxDuration = size_t(-1);
|
||||
BOOST_TEST_MESSAGE("Disabled constant optimizer run time check for address sanitizer build.");
|
||||
#endif
|
||||
#endif
|
||||
BOOST_CHECK_MESSAGE(duration <= maxDuration, "Compilation of constants took longer than 20 seconds.");
|
||||
compareVersions("hexEncodeTest(address)", u256(0x123456789));
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@ add_executable(isoltest
|
||||
IsolTestOptions.cpp
|
||||
../Options.cpp
|
||||
../Common.cpp
|
||||
../EVMHost.cpp
|
||||
../TestCase.cpp
|
||||
../libsolidity/util/BytesUtils.cpp
|
||||
../libsolidity/util/ContractABIUtils.cpp
|
||||
@ -26,7 +27,6 @@ add_executable(isoltest
|
||||
../libsolidity/AnalysisFramework.cpp
|
||||
../libsolidity/SolidityExecutionFramework.cpp
|
||||
../ExecutionFramework.cpp
|
||||
../RPCSession.cpp
|
||||
../libsolidity/ABIJsonTest.cpp
|
||||
../libsolidity/ASTJSONTest.cpp
|
||||
../libsolidity/SMTCheckerJSONTest.cpp
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <test/tools/IsolTestOptions.h>
|
||||
#include <test/libsolidity/AnalysisFramework.h>
|
||||
#include <test/InteractiveTests.h>
|
||||
#include <test/EVMHost.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
@ -156,7 +157,7 @@ TestTool::Result TestTool::process()
|
||||
{
|
||||
(AnsiColorized(cout, formatted, {BOLD}) << m_name << ": ").flush();
|
||||
|
||||
m_test = m_testCaseCreator(TestCase::Config{m_path.string(), m_options.ipcPath.string(), m_options.evmVersion()});
|
||||
m_test = m_testCaseCreator(TestCase::Config{m_path.string(), m_options.evmVersion()});
|
||||
if (m_test->validateSettings(m_options.evmVersion()))
|
||||
switch (TestCase::TestResult result = m_test->run(outputMessages, " ", formatted))
|
||||
{
|
||||
@ -413,6 +414,15 @@ int main(int argc, char const *argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool disableSemantics = !dev::test::EVMHost::getVM(options.evmonePath.string());
|
||||
if (disableSemantics)
|
||||
{
|
||||
cout << "Unable to find libevmone.so. Please provide the path using --evmonepath <path>." << endl;
|
||||
cout << "You can download it at" << endl;
|
||||
cout << "https://github.com/ethereum/evmone/releases/download/v0.1.0/evmone-0.1.0-linux-x86_64.tar.gz" << endl;
|
||||
cout << endl << "--- SKIPPING ALL SEMANTICS TESTS ---" << endl << endl;
|
||||
}
|
||||
|
||||
TestStats global_stats{0, 0};
|
||||
cout << "Running tests..." << endl << endl;
|
||||
|
||||
@ -420,7 +430,7 @@ int main(int argc, char const *argv[])
|
||||
// Interactive tests are added in InteractiveTests.h
|
||||
for (auto const& ts: g_interactiveTestsuites)
|
||||
{
|
||||
if (ts.ipc && options.disableIPC)
|
||||
if (ts.needsVM && disableSemantics)
|
||||
continue;
|
||||
|
||||
if (ts.smt && options.disableSMT)
|
||||
@ -451,5 +461,8 @@ int main(int argc, char const *argv[])
|
||||
}
|
||||
cout << "." << endl;
|
||||
|
||||
if (disableSemantics)
|
||||
cout << "\nNOTE: Skipped semantics tests because libevmone.so could not be found.\n" << endl;
|
||||
|
||||
return global_stats ? 0 : 1;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ if (OSSFUZZ)
|
||||
/usr/include/libprotobuf-mutator
|
||||
)
|
||||
target_link_libraries(abiv2_proto_ossfuzz PRIVATE solidity
|
||||
evmone intx ethash evmc-instructions
|
||||
evmc evmone intx ethash evmc-instructions
|
||||
protobuf-mutator-libfuzzer.a
|
||||
protobuf-mutator.a
|
||||
protobuf.a
|
||||
|
@ -142,7 +142,7 @@ DEFINE_PROTO_FUZZER(Contract const& _input)
|
||||
|
||||
// We target the default EVM which is the latest
|
||||
langutil::EVMVersion version = {};
|
||||
EVMHost hostContext(version, evmone);
|
||||
EVMHost hostContext(version, &evmone);
|
||||
|
||||
// Deploy contract and signal failure if deploy failed
|
||||
evmc::result createResult = deployContract(hostContext, byteCode);
|
||||
|
Loading…
Reference in New Issue
Block a user