This repository was archived by the owner on Apr 8, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 166
Expand file tree
/
Copy pathrun.cpp
More file actions
120 lines (100 loc) · 4.02 KB
/
run.cpp
File metadata and controls
120 lines (100 loc) · 4.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// EVMC: Ethereum Client-VM Connector API.
// Copyright 2019-2020 The EVMC Authors.
// Licensed under the Apache License, Version 2.0.
#include <evmc/evmc.hpp>
#include <evmc/hex.hpp>
#include <evmc/mocked_host.hpp>
#include <evmc/tooling.hpp>
#include <chrono>
#include <ostream>
namespace evmc::tooling
{
namespace
{
/// The address where a new contract is created with --create option.
constexpr auto create_address = 0xc9ea7ed000000000000000000000000000000001_address;
/// The gas limit for contract creation.
constexpr auto create_gas = 10'000'000;
auto bench(MockedHost& host,
evmc::VM& vm,
evmc_revision rev,
const evmc_message& msg,
const evmc::Result& expected_result,
std::ostream& out)
{
{
using clock = std::chrono::steady_clock;
using unit = std::chrono::nanoseconds;
constexpr auto unit_name = " ns";
constexpr auto target_bench_time = std::chrono::seconds{1};
constexpr auto warning =
"WARNING! Inconsistent execution result likely due to the use of storage ";
// Probe run: execute once again the already warm code to estimate a single run time.
const auto probe_start = clock::now();
const auto result = vm.execute(host, rev, msg);
const auto bench_start = clock::now();
const auto probe_time = bench_start - probe_start;
if (result.gas_left != expected_result.gas_left)
out << warning << "(gas used: " << (msg.gas - result.gas_left) << ")\n";
if (bytes_view{result.output_data, result.output_size} !=
bytes_view{expected_result.output_data, expected_result.output_size})
out << warning << "(output: " << hex({result.output_data, result.output_size}) << ")\n";
// Benchmark loop.
const auto num_iterations = std::max(static_cast<int>(target_bench_time / probe_time), 1);
for (int i = 0; i < num_iterations; ++i)
vm.execute(host, rev, msg);
const auto bench_time = (clock::now() - bench_start) / num_iterations;
out << "Time: " << std::chrono::duration_cast<unit>(bench_time).count() << unit_name
<< " (avg of " << num_iterations << " iterations)\n";
}
}
} // namespace
int run(VM& vm,
evmc_revision rev,
int64_t gas,
bytes_view code,
bytes_view input,
bool create,
bool bench,
std::ostream& out)
{
out << (create ? "Creating and executing on " : "Executing on ") << rev << " with " << gas
<< " gas limit\n";
MockedHost host;
evmc_message msg{};
msg.gas = gas;
msg.input_data = input.data();
msg.input_size = input.size();
msg.code = code.data();
msg.code_size = code.size();
if (create)
{
evmc_message create_msg{};
create_msg.kind = EVMC_CREATE;
create_msg.recipient = create_address;
create_msg.gas = create_gas;
create_msg.code = code.data();
create_msg.code_size = code.size();
const auto create_result = vm.execute(host, rev, create_msg);
if (create_result.status_code != EVMC_SUCCESS)
{
out << "Contract creation failed: " << create_result.status_code << "\n";
return create_result.status_code;
}
auto& created_account = host.accounts[create_address];
created_account.code = bytes(create_result.output_data, create_result.output_size);
msg.recipient = create_address;
msg.code = created_account.code.data();
msg.code_size = created_account.code.size();
}
out << "\n";
const auto result = vm.execute(host, rev, msg);
if (bench)
tooling::bench(host, vm, rev, msg, result, out);
const auto gas_used = msg.gas - result.gas_left;
out << "Result: " << result.status_code << "\nGas used: " << gas_used << "\n";
if (result.status_code == EVMC_SUCCESS || result.status_code == EVMC_REVERT)
out << "Output: " << hex({result.output_data, result.output_size}) << "\n";
return 0;
}
} // namespace evmc::tooling