Decentralised Art Server
High-performance C++ backend that exposes HTML interface and a secure REST API for managing Performative Transactions entities
 
Loading...
Searching...
No Matches
evm.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <string>
5#include <cstring>
6#include <filesystem>
7#include <vector>
8#include <expected>
9#include <fstream>
10#include <istream>
11
12// Undefine the conflicting macro
13#ifdef interface
14 #undef interface
15#endif
16
17#include <evmc/evmc.h>
18#include <evmc/evmc.hpp>
19#include <evmc/mocked_host.hpp>
20
21#include <evmc/hex.hpp>
22
23#include <evmone/evmone.h>
24
25#ifndef interface
26 #define interface __STRUCT__
27#endif
28
29#include "native.h"
30#include <asio.hpp>
31#include <spdlog/spdlog.h>
32#include <absl/container/flat_hash_map.h>
33
34#include "utils.hpp"
35#include "file.hpp"
36#include "keccak256.hpp"
37#include "pt.hpp"
38
39#include "evm_storage.hpp"
40#include "evm_formatter.hpp"
41
42namespace dcn::evm
43{
44 using Address = evmc::address;
45
79
81 {
82 enum class Kind : std::uint8_t
83 {
84 UNKNOWN = 0,
86
88
89 evmc_bytes32 a{}; // first bytes32 (or zero)
90 };
91
92 class EVM
93 {
94 public:
95 EVM(asio::io_context & io_context, evmc_revision rev, std::filesystem::path solc_path, std::filesystem::path pt_path);
96 ~EVM() = default;
97
98 EVM(const EVM&) = delete;
99 EVM& operator=(const EVM&) = delete;
100
101 EVM(EVM&&) = delete;
102 EVM& operator=(EVM&&) = delete;
103
104 asio::awaitable<bool> addAccount(Address address, std::uint64_t initial_gas) noexcept;
105 asio::awaitable<bool> setGas(Address address, std::uint64_t gas) noexcept;
106
107 asio::awaitable<bool> compile(std::filesystem::path code_path,
108 std::filesystem::path out_dir,
109 std::filesystem::path base_path = {},
110 std::filesystem::path includes = {}) const noexcept;
111
112 asio::awaitable<std::expected<Address, DeployError>> deploy(
113 std::istream & code_stream,
114 Address sender,
115 std::vector<std::uint8_t> constructor_args,
116 std::uint64_t gas_limit,
117 std::uint64_t value) noexcept;
118
119 asio::awaitable<std::expected<Address, DeployError>> deploy(
120 std::filesystem::path code_path,
121 Address sender,
122 std::vector<uint8_t> constructor_args,
123 std::uint64_t gas_limit,
124 std::uint64_t value) noexcept;
125
126 asio::awaitable<std::expected<std::vector<std::uint8_t>, ExecuteError>> execute(
127 Address sender,
128 Address recipient,
129 std::vector<std::uint8_t> input_bytes,
130 std::uint64_t gas_limit,
131 std::uint64_t value) noexcept;
132
135
136 const std::filesystem::path & getSolcPath() const;
137 const std::filesystem::path & getPTPath() const;
138
139 protected:
140 asio::awaitable<bool> loadPT();
141
142 private:
143 asio::strand<asio::io_context::executor_type> _strand;
144
145 evmc::VM _vm;
146 evmc_revision _rev;
147
148 std::filesystem::path _solc_path;
149 std::filesystem::path _pt_path;
150
151 EVMStorage _storage;
152
153 Address _genesis_address;
154 Address _console_log_address;
155
156 Address _registry_address;
157 Address _runner_address;
158 };
159 asio::awaitable<std::expected<std::vector<std::uint8_t>, ExecuteError>> fetchOwner(EVM & evm, const Address & address);
160
161 std::vector<std::uint8_t> constructSelector(std::string signature);
162
163 template<class T>
164 std::vector<std::uint8_t> encodeAsArg(const T & val);
165
166 template<>
167 std::vector<std::uint8_t> encodeAsArg<Address>(const Address & address);
168
169 template<>
170 std::vector<std::uint8_t> encodeAsArg<std::uint32_t>(const std::uint32_t & value);
171
172 template<>
173 std::vector<std::uint8_t> encodeAsArg<std::vector<std::uint32_t>>(const std::vector<std::uint32_t> & vec);
174
175 template<>
176 std::vector<std::uint8_t> encodeAsArg<std::vector<std::tuple<std::uint32_t, std::uint32_t>>>(const std::vector<std::tuple<std::uint32_t, std::uint32_t>>& vec);
177
178 template<>
179 std::vector<std::uint8_t> encodeAsArg<std::string>(const std::string& str);
180
181
182 template<class T>
183 T decodeReturnedValue(const std::vector<std::uint8_t> & bytes);
184
185
186 template<>
187 std::vector<std::vector<std::uint32_t>> decodeReturnedValue(const std::vector<std::uint8_t> & bytes);
188
189 template<>
190 Address decodeReturnedValue(const std::vector<std::uint8_t> & bytes);
191
192 template<>
193 std::vector<Samples> decodeReturnedValue(const std::vector<uint8_t> & bytes);
194}
195
196template <>
197struct std::formatter<dcn::evm::DeployError::Kind> : std::formatter<std::string> {
198 auto format(const dcn::evm::DeployError::Kind & err, format_context& ctx) const {
199 switch(err)
200 {
201 case dcn::evm::DeployError::Kind::INVALID_BYTECODE : return formatter<string>::format("Invalid bytecode", ctx);
202 case dcn::evm::DeployError::Kind::INVALID_ADDRESS : return formatter<string>::format("Invalid address", ctx);
203 case dcn::evm::DeployError::Kind::INVALID_DATA : return formatter<string>::format("Invalid data", ctx);
204 case dcn::evm::DeployError::Kind::COMPILATION_ERROR : return formatter<string>::format("Compilation error", ctx);
205
206 case dcn::evm::DeployError::Kind::PARTICLE_ALREADY_REGISTERED : return formatter<string>::format("Particle already registered", ctx);
207 case dcn::evm::DeployError::Kind::PARTICLE_MISSING : return formatter<string>::format("Particle missing", ctx);
208 case dcn::evm::DeployError::Kind::PARTICLE_DIMENSIONS_MISMATCH : return formatter<string>::format("Particle dimensions mismatch", ctx);
209
210 case dcn::evm::DeployError::Kind::FEATURE_ALREADY_REGISTERED : return formatter<string>::format("Feature already registered", ctx);
211 case dcn::evm::DeployError::Kind::FEATURE_MISSING : return formatter<string>::format("Feature missing", ctx);
212
213 case dcn::evm::DeployError::Kind::TRANSFORMATION_ALREADY_REGISTERED : return formatter<string>::format("Transformation already registered", ctx);
214 case dcn::evm::DeployError::Kind::TRANSFORMATION_ARGUMENTS_MISMATCH : return formatter<string>::format("Transformation arguments mismatch", ctx);
215 case dcn::evm::DeployError::Kind::TRANSFORMATION_MISSING : return formatter<string>::format("Transformation missing", ctx);
216
217 case dcn::evm::DeployError::Kind::CONDITION_ALREADY_REGISTERED : return formatter<string>::format("Condition already registered", ctx);
218 case dcn::evm::DeployError::Kind::CONDITION_ARGUMENTS_MISMATCH : return formatter<string>::format("Condition arguments mismatch", ctx);
219 case dcn::evm::DeployError::Kind::CONDITION_MISSING : return formatter<string>::format("Condition missing", ctx);
220
221 default: return formatter<string>::format("Unknown", ctx);
222 }
223 return formatter<string>::format("", ctx);
224 }
225};
226
227template <>
228struct std::formatter<dcn::evm::ExecuteError::Kind> : std::formatter<std::string> {
229 auto format(const dcn::evm::ExecuteError::Kind & err, format_context& ctx) const {
230 switch(err)
231 {
232 case dcn::evm::ExecuteError::Kind::CONDITION_NOT_MET : return formatter<string>::format("Condition not met", ctx);
233
234 default: return formatter<string>::format("Unknown", ctx);
235 }
236 return formatter<string>::format("", ctx);
237 }
238};
Definition evm.hpp:93
asio::awaitable< std::expected< std::vector< std::uint8_t >, ExecuteError > > execute(Address sender, Address recipient, std::vector< std::uint8_t > input_bytes, std::uint64_t gas_limit, std::uint64_t value) noexcept
Definition evm.cpp:593
Address getRunnerAddress() const
Definition evm.cpp:404
asio::awaitable< bool > loadPT()
Definition evm.cpp:648
const std::filesystem::path & getPTPath() const
Definition evm.cpp:414
EVM(EVM &&)=delete
~EVM()=default
EVM & operator=(EVM &&)=delete
asio::awaitable< bool > addAccount(Address address, std::uint64_t initial_gas) noexcept
Definition evm.cpp:419
asio::awaitable< std::expected< Address, DeployError > > deploy(std::istream &code_stream, Address sender, std::vector< std::uint8_t > constructor_args, std::uint64_t gas_limit, std::uint64_t value) noexcept
Definition evm.cpp:503
EVM(const EVM &)=delete
Address getRegistryAddress() const
Definition evm.cpp:399
asio::awaitable< bool > compile(std::filesystem::path code_path, std::filesystem::path out_dir, std::filesystem::path base_path={}, std::filesystem::path includes={}) const noexcept
Definition evm.cpp:455
const std::filesystem::path & getSolcPath() const
Definition evm.cpp:409
asio::awaitable< bool > setGas(Address address, std::uint64_t gas) noexcept
Definition evm.cpp:441
EVM & operator=(const EVM &)=delete
Definition evm.hpp:43
std::vector< std::uint8_t > constructSelector(std::string signature)
Definition evm.cpp:5
T decodeReturnedValue(const std::vector< std::uint8_t > &bytes)
std::vector< std::uint8_t > encodeAsArg< std::string >(const std::string &str)
Definition evm.cpp:104
std::vector< std::uint8_t > encodeAsArg< Address >(const Address &address)
Definition evm.cpp:13
std::vector< std::uint8_t > encodeAsArg(const T &val)
std::vector< std::uint8_t > encodeAsArg< std::uint32_t >(const std::uint32_t &value)
Definition evm.cpp:21
evmc::address Address
Definition evm.hpp:44
asio::awaitable< std::expected< std::vector< std::uint8_t >, ExecuteError > > fetchOwner(EVM &evm, const Address &address)
Definition evm.cpp:357
Definition decentralised_art.hpp:30
Definition evm.hpp:47
enum dcn::evm::DeployError::Kind kind
Kind
Definition evm.hpp:49
uint32_t code
Definition evm.hpp:77
evmc_bytes32 a
Definition evm.hpp:76
Definition evm.hpp:81
Kind
Definition evm.hpp:83
evmc_bytes32 a
Definition evm.hpp:89
enum dcn::evm::ExecuteError::Kind kind
auto format(const dcn::evm::DeployError::Kind &err, format_context &ctx) const
Definition evm.hpp:198
auto format(const dcn::evm::ExecuteError::Kind &err, format_context &ctx) const
Definition evm.hpp:229