1 /*
2 	This file is part of solidity.
3 
4 	solidity is free software: you can redistribute it and/or modify
5 	it under the terms of the GNU General Public License as published by
6 	the Free Software Foundation, either version 3 of the License, or
7 	(at your option) any later version.
8 
9 	solidity is distributed in the hope that it will be useful,
10 	but WITHOUT ANY WARRANTY; without even the implied warranty of
11 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 	GNU General Public License for more details.
13 
14 	You should have received a copy of the GNU General Public License
15 	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 // SPDX-License-Identifier: GPL-3.0
18 
19 #pragma once
20 
21 #include <test/EVMHost.h>
22 
23 #include <libsolidity/interface/CompilerStack.h>
24 
25 #include <libyul/AssemblyStack.h>
26 
27 #include <libsolutil/Keccak256.h>
28 
29 #include <evmone/evmone.h>
30 
31 namespace solidity::test::fuzzer
32 {
33 struct CompilerOutput
34 {
35 	/// EVM bytecode returned by compiler
36 	solidity::bytes byteCode;
37 	/// Method identifiers in a contract
38 	Json::Value methodIdentifiersInContract;
39 };
40 
41 struct CompilerInput
42 {
43 	CompilerInput(
44 		langutil::EVMVersion _evmVersion,
45 		StringMap const& _sourceCode,
46 		std::string const& _contractName,
47 		frontend::OptimiserSettings _optimiserSettings,
48 		std::map<std::string, solidity::util::h160> _libraryAddresses,
49 		bool _debugFailure = false,
50 		bool _viaIR = false
51 	):
evmVersionCompilerInput52 		evmVersion(_evmVersion),
53 		sourceCode(_sourceCode),
54 		contractName(_contractName),
55 		optimiserSettings(_optimiserSettings),
56 		libraryAddresses(_libraryAddresses),
57 		debugFailure(_debugFailure),
58 		viaIR(_viaIR)
59 	{}
60 	/// EVM target version
61 	langutil::EVMVersion evmVersion;
62 	/// Source code to be compiled
63 	StringMap const& sourceCode;
64 	/// Contract name without a colon prefix
65 	std::string contractName;
66 	/// Optimiser setting to be used during compilation
67 	frontend::OptimiserSettings optimiserSettings;
68 	/// Information on which library is deployed where
69 	std::map<std::string, solidity::util::h160> libraryAddresses;
70 	/// Flag used for debugging
71 	bool debugFailure;
72 	/// Flag to enable new code generator.
73 	bool viaIR;
74 };
75 
76 class SolidityCompilationFramework
77 {
78 public:
SolidityCompilationFramework(CompilerInput _input)79 	SolidityCompilationFramework(CompilerInput _input): m_compilerInput(_input)
80 	{}
81 	/// Sets contract name to @param _contractName.
contractName(std::string const & _contractName)82 	void contractName(std::string const& _contractName)
83 	{
84 		m_compilerInput.contractName = _contractName;
85 	}
86 	/// Sets library addresses to @param _libraryAddresses.
libraryAddresses(std::map<std::string,solidity::util::h160> _libraryAddresses)87 	void libraryAddresses(std::map<std::string, solidity::util::h160> _libraryAddresses)
88 	{
89 		m_compilerInput.libraryAddresses = std::move(_libraryAddresses);
90 	}
91 	/// @returns method identifiers in contract called @param _contractName.
methodIdentifiers(std::string const & _contractName)92 	Json::Value methodIdentifiers(std::string const& _contractName)
93 	{
94 		return m_compiler.methodIdentifiers(_contractName);
95 	}
96 	/// @returns Compilation output comprising EVM bytecode and list of
97 	/// method identifiers in contract if compilation is successful,
98 	/// null value otherwise.
99 	std::optional<CompilerOutput> compileContract();
100 private:
101 	frontend::CompilerStack m_compiler;
102 	CompilerInput m_compilerInput;
103 };
104 
105 class EvmoneUtility
106 {
107 public:
EvmoneUtility(solidity::test::EVMHost & _evmHost,CompilerInput _compilerInput,std::string const & _contractName,std::string const & _libraryName,std::string const & _methodName)108 	EvmoneUtility(
109 		solidity::test::EVMHost& _evmHost,
110 		CompilerInput _compilerInput,
111 		std::string const& _contractName,
112 		std::string const& _libraryName,
113 		std::string const& _methodName
114 	):
115 		m_evmHost(_evmHost),
116 		m_compilationFramework(_compilerInput),
117 		m_contractName(_contractName),
118 		m_libraryName(_libraryName),
119 		m_methodName(_methodName)
120 	{}
121 	/// @returns the result returned by the EVM host on compiling, deploying,
122 	/// and executing test configuration.
123 	/// @param _isabelleData contains encoding data to be passed to the
124 	/// isabelle test entry point.
125 	std::optional<evmc::result> compileDeployAndExecute(std::string _isabelleData = {});
126 	/// Compares the contents of the memory address pointed to
127 	/// by `_result` of `_length` bytes to u256 zero.
128 	/// @returns true if `_result` is zero, false
129 	/// otherwise.
130 	static bool zeroWord(uint8_t const* _result, size_t _length);
131 	/// @returns an evmc_message with all of its fields zero
132 	/// initialized except gas and input fields.
133 	/// The gas field is set to the maximum permissible value so that we
134 	/// don't run into out of gas errors. The input field is copied from
135 	/// @param _input.
136 	static evmc_message initializeMessage(bytes const& _input);
137 private:
138 	/// @returns the result of the execution of the function whose
139 	/// keccak256 hash is @param _functionHash that is deployed at
140 	/// @param _deployedAddress in @param _hostContext.
141 	evmc::result executeContract(
142 		bytes const& _functionHash,
143 		evmc_address _deployedAddress
144 	);
145 	/// @returns the result of deployment of @param _code on @param _hostContext.
146 	evmc::result deployContract(bytes const& _code);
147 	/// Deploys and executes EVM byte code in @param _byteCode on
148 	/// EVM Host referenced by @param _hostContext. Input passed
149 	/// to execution context is @param _hexEncodedInput.
150 	/// @returns result returning by @param _hostContext.
151 	evmc::result deployAndExecute(
152 		bytes const& _byteCode,
153 		std::string const& _hexEncodedInput
154 	);
155 	/// Compiles contract named @param _contractName present in
156 	/// @param _sourceCode, optionally using a precompiled library
157 	/// specified via a library mapping and an optimisation setting.
158 	/// @returns a pair containing the generated byte code and method
159 	/// identifiers for methods in @param _contractName.
160 	std::optional<CompilerOutput> compileContract();
161 
162 	/// EVM Host implementation
163 	solidity::test::EVMHost& m_evmHost;
164 	/// Solidity compilation framework
165 	SolidityCompilationFramework m_compilationFramework;
166 	/// Contract name
167 	std::string m_contractName;
168 	/// Library name
169 	std::string m_libraryName;
170 	/// Method name
171 	std::string m_methodName;
172 };
173 
174 }
175