forked from bcosorg/bcos
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathExtVMFace.h
332 lines (274 loc) · 9.6 KB
/
ExtVMFace.h
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
/*
This file is part of cpp-ethereum.
cpp-ethereum 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.
cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file ExtVMFace.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#include <set>
#include <functional>
#include <libdevcore/Common.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/RLP.h>
#include <libdevcore/SHA3.h>
#include <libevmcore/Instruction.h>
#include <libethcore/Common.h>
#include <libethcore/BlockHeader.h>
#include <libethcore/ChainOperationParams.h>
#include <libdevcore/CommonIO.h>
#include <libdevcore/FileSystem.h>
using namespace std;
namespace dev
{
namespace eth
{
enum class BlockPolarity
{
Unknown,
Dead,
Live
};
struct LogEntry
{
LogEntry() {}
LogEntry(RLP const& _r) { address = (Address)_r[0]; topics = _r[1].toVector<h256>(); data = _r[2].toBytes(); }
LogEntry(Address const& _address, h256s const& _ts, bytes&& _d): address(_address), topics(_ts), data(std::move(_d)) {}
void streamRLP(RLPStream& _s) const { _s.appendList(3) << address << topics << data; }
LogBloom bloom() const
{
LogBloom ret;
ret.shiftBloom<3>(sha3(address.ref()));
for (auto t: topics)
ret.shiftBloom<3>(sha3(t.ref()));
return ret;
}
Address address;
h256s topics;
bytes data;
};
using LogEntries = std::vector<LogEntry>;
struct LocalisedLogEntry: public LogEntry
{
LocalisedLogEntry() {}
explicit LocalisedLogEntry(LogEntry const& _le): LogEntry(_le) {}
explicit LocalisedLogEntry(
LogEntry const& _le,
h256 _special
):
LogEntry(_le),
isSpecial(true),
special(_special)
{}
explicit LocalisedLogEntry(
LogEntry const& _le,
h256 const& _blockHash,
BlockNumber _blockNumber,
h256 const& _transactionHash,
unsigned _transactionIndex,
unsigned _logIndex,
BlockPolarity _polarity = BlockPolarity::Unknown
):
LogEntry(_le),
blockHash(_blockHash),
blockNumber(_blockNumber),
transactionHash(_transactionHash),
transactionIndex(_transactionIndex),
logIndex(_logIndex),
polarity(_polarity),
mined(true)
{}
h256 blockHash;
BlockNumber blockNumber = 0;
h256 transactionHash;
unsigned transactionIndex = 0;
unsigned logIndex = 0;
BlockPolarity polarity = BlockPolarity::Unknown;
bool mined = false;
bool isSpecial = false;
h256 special;
};
using LocalisedLogEntries = std::vector<LocalisedLogEntry>;
inline LogBloom bloom(LogEntries const& _logs)
{
LogBloom ret;
for (auto const& l: _logs)
ret |= l.bloom();
return ret;
}
struct SubState
{
std::set<Address> suicides; ///< Any accounts that have suicided.
LogEntries logs; ///< Any logs.
u256 refunds; ///< Refund counter of SSTORE nonzero->zero.
SubState& operator+=(SubState const& _s)
{
suicides += _s.suicides;
refunds += _s.refunds;
logs += _s.logs;
return *this;
}
void clear()
{
suicides.clear();
logs.clear();
refunds = 0;
}
};
class ExtVMFace;
class VM;
using LastHashes = std::vector<h256>;
using OnOpFunc = std::function<void(uint64_t /*steps*/, uint64_t /* PC */, Instruction /*instr*/, bigint /*newMemSize*/, bigint /*gasCost*/, bigint /*gas*/, VM*, ExtVMFace const*)>;
struct CallParameters
{
Address senderAddress;
Address codeAddress;
Address receiveAddress;
u256 valueTransfer;
u256 apparentValue;
u256 gas;
bytesConstRef data;
bytesRef out;
OnOpFunc onOp;
};
class EnvInfo
{
public:
EnvInfo() {}
EnvInfo(BlockHeader const& _current, LastHashes const& _lh = LastHashes(), u256 const& _gasUsed = u256(),bool const & _cl=false,bool const & _el=false):
m_number(_current.number()),
m_author(_current.author()),
m_timestamp(_current.timestamp()),
m_difficulty(_current.difficulty()),
// Trim gas limit to int64. convert_to used explicitly instead of
// static_cast to be noticed when BlockHeader::gasLimit() will be
// changed to int64 too.
m_gasLimit(_current.gasLimit().convert_to<int64_t>()),
m_lastHashes(_lh),
m_gasUsed(_gasUsed),
m_coverlog(_cl),
m_eventlog(_el)
{
}
EnvInfo(BlockHeader const& _current, LastHashes&& _lh, u256 const& _gasUsed = u256(),bool const & _cl=false,bool const & _el=false):
m_number(_current.number()),
m_author(_current.author()),
m_timestamp(_current.timestamp()),
m_difficulty(_current.difficulty()),
// Trim gas limit to int64. convert_to used explicitly instead of
// static_cast to be noticed when BlockHeader::gasLimit() will be
// changed to int64 too.
m_gasLimit(_current.gasLimit().convert_to<int64_t>()),
m_lastHashes(_lh),
m_gasUsed(_gasUsed),
m_coverlog(_cl),
m_eventlog(_el)
{
}
u256 const& number() const { return m_number; }
Address const& author() const { return m_author; }
u256 const& timestamp() const { return m_timestamp; }
u256 const& difficulty() const { return m_difficulty; }
int64_t gasLimit() const { return m_gasLimit; }
LastHashes const& lastHashes() const { return m_lastHashes; }
u256 const& gasUsed() const { return m_gasUsed; }
void setNumber(u256 const& _v) { m_number = _v; }
void setAuthor(Address const& _v) { m_author = _v; }
void setTimestamp(u256 const& _v) { m_timestamp = _v; }
void setDifficulty(u256 const& _v) { m_difficulty = _v; }
void setGasLimit(int64_t _v) { m_gasLimit = _v; }
void setLastHashes(LastHashes const& _lh) { m_lastHashes = _lh; }
void setLastHashes(LastHashes&& _lh) { m_lastHashes = _lh; }
void setGasUsed(u256 const& _v) { m_gasUsed = _v; }
bool coverLog()const { return m_coverlog;}
bool eventLog()const { return m_eventlog;}
void setCoverLog(bool _cl){ m_coverlog=_cl;}
void setEventLog(bool _el){ m_eventlog=_el;}
private:
u256 m_number;
Address m_author;
u256 m_timestamp;
u256 m_difficulty;
int64_t m_gasLimit;
LastHashes m_lastHashes;
u256 m_gasUsed;
bool m_coverlog;//是否打印覆盖率日志
bool m_eventlog;//是否打印event log
};
/**
* @brief Interface and null implementation of the class for specifying VM externalities.
*/
class ExtVMFace
{
public:
/// Null constructor.
ExtVMFace() = default;
/// Full constructor.
ExtVMFace(EnvInfo const& _envInfo, Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytes _code, h256 const& _codeHash, unsigned _depth);
virtual ~ExtVMFace() = default;
ExtVMFace(ExtVMFace const&) = delete;
void operator=(ExtVMFace) = delete;
/// Read storage location.
virtual u256 store(u256) { return 0; }
/// Write a value in storage.
virtual void setStore(u256, u256) {}
/// Read address's balance.
virtual u256 balance(Address) { return 0; }
/// Read address's code.
virtual bytes const& codeAt(Address) { return NullBytes; }
/// @returns the size of the code in bytes at the given address.
virtual size_t codeSizeAt(Address) { return 0; }
/// Does the account exist?
virtual bool exists(Address) { return false; }
/// Suicide the associated contract and give proceeds to the given address.
virtual void suicide(Address) { sub.suicides.insert(myAddress); }
/// Create a new (contract) account.
virtual h160 create(u256, u256&, bytesConstRef, OnOpFunc const&) { return h160(); }
/// Make a new message call.
virtual bool call(CallParameters&) { return false; }
/// Revert any changes made (by any of the other calls).
virtual void log(h256s&& _topics, bytesConstRef _data)
{
if( envInfo().eventLog() )
{
std::stringstream smsg;
smsg<<"LOG 0x"<<myAddress<<" "<< toHex( _data )<<std::endl;
appendFile(getDataDir("ethereum") + "/event.log",smsg.str());
}//if
sub.logs.push_back(LogEntry(myAddress, std::move(_topics), _data.toBytes()));
}
/// Hash of a block if within the last 256 blocks, or h256() otherwise.
h256 blockHash(u256 _number) { return _number < envInfo().number() && _number >= (std::max<u256>(256, envInfo().number()) - 256) ? envInfo().lastHashes()[(unsigned)(envInfo().number() - 1 - _number)] : h256(); }
/// Get the code at the given location in code ROM.
byte getCode(u256 _n) const { return _n < code.size() ? code[(size_t)_n] : 0; }
/// Get the execution environment information.
EnvInfo const& envInfo() const { return m_envInfo; }
/// Return the EVM gas-price schedule for this execution context.
virtual EVMSchedule const& evmSchedule() const { return DefaultSchedule; }
private:
EnvInfo const& m_envInfo;
public:
// TODO: make private
Address myAddress; ///< Address associated with executing code (a contract, or contract-to-be).
Address caller; ///< Address which sent the message (either equal to origin or a contract).
Address origin; ///< Original transactor.
u256 value; ///< Value (in Wei) that was passed to this address.
u256 gasPrice; ///< Price of gas (that we already paid).
bytesConstRef data; ///< Current input data.
bytes code; ///< Current code that is executing.
h256 codeHash; ///< SHA3 hash of the executing code
SubState sub; ///< Sub-band VM state (suicides, refund counter, logs).
unsigned depth = 0; ///< Depth of the present call.
};
}
}