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_storage.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <string>
5#include <cstring>
6#include <vector>
7#include <format>
8#include <stack>
9
10// Undefine the conflicting macro
11#ifdef interface
12 #undef interface
13#endif
14
15#include <evmc/evmc.h>
16#include <evmc/evmc.hpp>
17#include <evmc/hex.hpp>
18
19#ifndef interface
20 #define interface __STRUCT__
21#endif
22
23#include <spdlog/spdlog.h>
24#include <absl/container/flat_hash_map.h>
25
26#include "keccak256.hpp"
27
28#include "evm_formatter.hpp"
29
30namespace dcn::evm
31{
32 const std::uint64_t DEFAULT_GAS_LIMIT = 100'000'000;
33
34 class EVMStorage : public evmc::Host
35 {
36 public:
38 {
39 std::uint64_t seq = 0;
40 std::int64_t block_number = 0;
41 std::string block_hash;
42 std::string parent_hash;
43 std::int64_t tx_index = 0;
44 std::string tx_hash;
45 std::int64_t log_index = 0;
46 std::string address;
47 std::vector<std::string> topics;
48 std::string data_hex;
49 std::int64_t block_time = 0;
50 };
51
52 struct Account
53 {
54 evmc_uint256be balance;
55 std::vector<std::uint8_t> code;
56 absl::flat_hash_map<evmc::bytes32, evmc::bytes32> storage;
57
58 // Deployment metadata
59 evmc::address creator{};
60 uint64_t nonce = 0;
61 uint64_t timestamp = 0;
62 };
63
64 EVMStorage(evmc::VM & vm, evmc_revision rev);
65
66 bool add_account(const evmc::address& addr)
67 {
68 if(account_exists(addr) == true)
69 {
70 spdlog::error(std::format("add_account: Account {} already exists", addr));
71 return false;
72 }
73 _accounts.emplace(to_key(addr), Account{});
74 return true;
75 }
76
77 void set_balance(const evmc::address& addr, std::uint64_t x) noexcept
78 {
79 if(account_exists(addr) == false)
80 {
81 spdlog::error(std::format("set_balance : Account {} does not exist", addr));
82 return;
83 }
84 Account & acc = _accounts.at(to_key(addr));
85
86 acc.balance = evmc::uint256be{};
87 for (std::size_t i = 0; i < sizeof(x); ++i)
88 acc.balance.bytes[sizeof(acc.balance) - 1 - i] = static_cast<uint8_t>(x >> (8 * i));
89 }
90
91 bool account_exists(const evmc::address& addr) const noexcept override;
92
93 evmc::bytes32 get_storage(const evmc::address& addr, const evmc::bytes32& key) const noexcept override;
94
95 evmc_storage_status set_storage(const evmc::address& address, const evmc::bytes32& key, const evmc::bytes32& value) noexcept override;
96
97 evmc::uint256be get_balance(const evmc::address& addr) const noexcept override;
98
99 std::size_t get_code_size(const evmc::address& addr) const noexcept override;
100
101 evmc::bytes32 get_code_hash(const evmc::address& addr) const noexcept override;
102
103 std::size_t copy_code(const evmc::address& addr,
104 std::size_t code_offset,
105 std::uint8_t* buffer_data,
106 std::size_t buffer_size) const noexcept override;
107
108 bool selfdestruct(const evmc::address& addr, const evmc::address& beneficiary) noexcept override;
109
110 evmc::Result call(const evmc_message& msg) noexcept override;
111
112 evmc_tx_context get_tx_context() const noexcept override;
113
114 evmc::bytes32 get_block_hash(int64_t block_number) const noexcept override;
115 void emit_log(const evmc::address& addr,
116 const std::uint8_t* data,
117 size_t data_size,
118 const evmc::bytes32 topics[],
119 size_t num_topics) noexcept override;
120
121 evmc_access_status access_account(const evmc::address& addr) noexcept override;
122
123 evmc_access_status access_storage(const evmc::address& addr, const evmc::bytes32& key) noexcept override;
124
125 evmc::bytes32 get_transient_storage(const evmc::address& addr,
126 const evmc::bytes32& key) const noexcept override;
127
128 void set_transient_storage(const evmc::address& addr,
129 const evmc::bytes32& key,
130 const evmc::bytes32& value) noexcept override;
131
132 std::vector<EmittedLogRecord> get_logs_since(std::uint64_t after_seq, std::size_t limit) const;
133 std::int64_t head_block_number() const noexcept;
134
135 protected:
136 std::string to_key(const evmc::address& addr) const;
137
138 evmc_address derive_create_address(const evmc::address& sender, std::uint64_t nonce);
139
140 evmc_address derive_create2_address(const evmc::address& sender, const evmc::bytes32& salt, const std::vector<std::uint8_t>& code);
141
142 void deploy_contract(evmc::address addr, std::vector<std::uint8_t>&& code, evmc_uint256be value, evmc::address creator, std::uint64_t nonce);
143
144 private:
145 struct ActiveTxContext
146 {
147 std::int64_t block_number = 0;
148 std::int64_t block_time = 0;
149 evmc::bytes32 block_hash{};
150 evmc::bytes32 parent_hash{};
151 evmc::bytes32 tx_hash{};
152 std::int64_t tx_index = 0;
153 std::int64_t next_log_index = 0;
154 };
155
156 evmc::bytes32 make_pseudo_hash(
157 std::uint64_t value_a,
158 std::uint64_t value_b,
159 std::uint64_t value_c) const;
160
161 evmc::VM & _vm;
162 evmc_revision _revision;
163
164 absl::flat_hash_map<std::string, Account> _accounts;
165 absl::flat_hash_map<evmc::address, std::uint64_t> _create_nonce;
166
167 std::stack<evmc::address> _sender_stack;
168 std::vector<ActiveTxContext> _tx_context_stack;
169 std::vector<EmittedLogRecord> _emitted_logs;
170 std::int64_t _head_block_number = 0;
171 evmc::bytes32 _head_block_hash{};
172 std::uint64_t _next_tx_id = 1;
173 std::uint64_t _next_log_seq = 1;
174 };
175
176 template <typename H>
177 inline H AbslHashValue(H h, const evmc::address & addr)
178 {
179 return H::combine(std::move(h), addr.bytes);
180 }
181}
182
Definition evm_storage.hpp:35
void set_balance(const evmc::address &addr, std::uint64_t x) noexcept
Definition evm_storage.hpp:77
std::int64_t head_block_number() const noexcept
Definition evm_storage.cpp:621
void emit_log(const evmc::address &addr, const std::uint8_t *data, size_t data_size, const evmc::bytes32 topics[], size_t num_topics) noexcept override
Definition evm_storage.cpp:394
evmc::bytes32 get_block_hash(int64_t block_number) const noexcept override
Definition evm_storage.cpp:333
void set_transient_storage(const evmc::address &addr, const evmc::bytes32 &key, const evmc::bytes32 &value) noexcept override
Definition evm_storage.cpp:580
void deploy_contract(evmc::address addr, std::vector< std::uint8_t > &&code, evmc_uint256be value, evmc::address creator, std::uint64_t nonce)
Definition evm_storage.cpp:667
evmc_storage_status set_storage(const evmc::address &address, const evmc::bytes32 &key, const evmc::bytes32 &value) noexcept override
Definition evm_storage.cpp:50
evmc::uint256be get_balance(const evmc::address &addr) const noexcept override
Definition evm_storage.cpp:56
evmc::bytes32 get_transient_storage(const evmc::address &addr, const evmc::bytes32 &key) const noexcept override
Definition evm_storage.cpp:571
evmc_tx_context get_tx_context() const noexcept override
Definition evm_storage.cpp:286
evmc_address derive_create2_address(const evmc::address &sender, const evmc::bytes32 &salt, const std::vector< std::uint8_t > &code)
Definition evm_storage.cpp:646
std::size_t copy_code(const evmc::address &addr, std::size_t code_offset, std::uint8_t *buffer_data, std::size_t buffer_size) const noexcept override
Definition evm_storage.cpp:85
evmc::Result call(const evmc_message &msg) noexcept override
Definition evm_storage.cpp:115
std::vector< EmittedLogRecord > get_logs_since(std::uint64_t after_seq, std::size_t limit) const
Definition evm_storage.cpp:588
bool selfdestruct(const evmc::address &addr, const evmc::address &beneficiary) noexcept override
Definition evm_storage.cpp:102
evmc_access_status access_account(const evmc::address &addr) noexcept override
Definition evm_storage.cpp:557
evmc_access_status access_storage(const evmc::address &addr, const evmc::bytes32 &key) noexcept override
Definition evm_storage.cpp:564
evmc_address derive_create_address(const evmc::address &sender, std::uint64_t nonce)
Definition evm_storage.cpp:632
bool account_exists(const evmc::address &addr) const noexcept override
Definition evm_storage.cpp:34
bool add_account(const evmc::address &addr)
Definition evm_storage.hpp:66
std::string to_key(const evmc::address &addr) const
Definition evm_storage.cpp:627
evmc::bytes32 get_code_hash(const evmc::address &addr) const noexcept override
Definition evm_storage.cpp:71
evmc::bytes32 get_storage(const evmc::address &addr, const evmc::bytes32 &key) const noexcept override
Definition evm_storage.cpp:39
std::size_t get_code_size(const evmc::address &addr) const noexcept override
Definition evm_storage.cpp:66
Definition events_runtime.hpp:20
const std::uint64_t DEFAULT_GAS_LIMIT
Definition evm_storage.hpp:32
H AbslHashValue(H h, const evmc::address &addr)
Definition evm_storage.hpp:177
Definition evm_storage.hpp:53
uint64_t timestamp
Definition evm_storage.hpp:61
evmc::address creator
Definition evm_storage.hpp:59
std::vector< std::uint8_t > code
Definition evm_storage.hpp:55
uint64_t nonce
Definition evm_storage.hpp:60
evmc_uint256be balance
Definition evm_storage.hpp:54
absl::flat_hash_map< evmc::bytes32, evmc::bytes32 > storage
Definition evm_storage.hpp:56
Definition evm_storage.hpp:38
std::int64_t block_number
Definition evm_storage.hpp:40
std::int64_t tx_index
Definition evm_storage.hpp:43
std::vector< std::string > topics
Definition evm_storage.hpp:47
std::string parent_hash
Definition evm_storage.hpp:42
std::int64_t log_index
Definition evm_storage.hpp:45
std::string data_hex
Definition evm_storage.hpp:48
std::string block_hash
Definition evm_storage.hpp:41
std::string address
Definition evm_storage.hpp:46
std::string tx_hash
Definition evm_storage.hpp:44
std::uint64_t seq
Definition evm_storage.hpp:39
std::int64_t block_time
Definition evm_storage.hpp:49