1 // Aleth: Ethereum C++ client, tools and libraries.
2 // Copyright 2015-2019 Aleth Authors.
3 // Licensed under the GNU General Public License, Version 3.
4
5
6 #include "ClientBase.h"
7 #include <algorithm>
8 #include "BlockChain.h"
9 #include "Executive.h"
10 #include "State.h"
11
12 using namespace std;
13 using namespace dev;
14 using namespace dev::eth;
15
16 static const int64_t c_maxGasEstimate = 50000000;
17
estimateGas(Address const & _from,u256 _value,Address _dest,bytes const & _data,int64_t _maxGas,u256 _gasPrice,BlockNumber _blockNumber,GasEstimationCallback const & _callback)18 std::pair<u256, ExecutionResult> ClientBase::estimateGas(Address const& _from, u256 _value, Address _dest, bytes const& _data, int64_t _maxGas, u256 _gasPrice, BlockNumber _blockNumber, GasEstimationCallback const& _callback)
19 {
20 try
21 {
22 int64_t upperBound = _maxGas;
23 if (upperBound == Invalid256 || upperBound > c_maxGasEstimate)
24 upperBound = c_maxGasEstimate;
25 int64_t lowerBound = Transaction::baseGasRequired(!_dest, &_data, EVMSchedule());
26 Block bk = blockByNumber(_blockNumber);
27 u256 gasPrice = _gasPrice == Invalid256 ? gasBidPrice() : _gasPrice;
28 ExecutionResult er;
29 ExecutionResult lastGood;
30 bool good = false;
31 while (upperBound != lowerBound)
32 {
33 int64_t mid = (lowerBound + upperBound) / 2;
34 u256 n = bk.transactionsFrom(_from);
35 Transaction t;
36 if (_dest)
37 t = Transaction(_value, gasPrice, mid, _dest, _data, n);
38 else
39 t = Transaction(_value, gasPrice, mid, _data, n);
40 t.forceSender(_from);
41 EnvInfo const env(bk.info(), bc().lastBlockHashes(), 0, mid);
42 State tempState(bk.state());
43 tempState.addBalance(_from, (u256)(t.gas() * t.gasPrice() + t.value()));
44 er = tempState.execute(env, *bc().sealEngine(), t, Permanence::Reverted).first;
45 if (er.excepted == TransactionException::OutOfGas ||
46 er.excepted == TransactionException::OutOfGasBase ||
47 er.excepted == TransactionException::OutOfGasIntrinsic ||
48 er.codeDeposit == CodeDeposit::Failed ||
49 er.excepted == TransactionException::BadJumpDestination)
50 lowerBound = lowerBound == mid ? upperBound : mid;
51 else
52 {
53 lastGood = er;
54 upperBound = upperBound == mid ? lowerBound : mid;
55 good = true;
56 }
57
58 if (_callback)
59 _callback(GasEstimationProgress { lowerBound, upperBound });
60 }
61 if (_callback)
62 _callback(GasEstimationProgress { lowerBound, upperBound });
63 return make_pair(upperBound, good ? lastGood : er);
64 }
65 catch (...)
66 {
67 // TODO: Some sort of notification of failure.
68 return make_pair(u256(), ExecutionResult());
69 }
70 }
71
injectBlock(bytes const & _block)72 ImportResult ClientBase::injectBlock(bytes const& _block)
73 {
74 return bc().attemptImport(_block, preSeal().db()).first;
75 }
76
balanceAt(Address _a,BlockNumber _block) const77 u256 ClientBase::balanceAt(Address _a, BlockNumber _block) const
78 {
79 return blockByNumber(_block).balance(_a);
80 }
81
countAt(Address _a,BlockNumber _block) const82 u256 ClientBase::countAt(Address _a, BlockNumber _block) const
83 {
84 return blockByNumber(_block).transactionsFrom(_a);
85 }
86
stateAt(Address _a,u256 _l,BlockNumber _block) const87 u256 ClientBase::stateAt(Address _a, u256 _l, BlockNumber _block) const
88 {
89 return blockByNumber(_block).storage(_a, _l);
90 }
91
stateRootAt(Address _a,BlockNumber _block) const92 h256 ClientBase::stateRootAt(Address _a, BlockNumber _block) const
93 {
94 return blockByNumber(_block).storageRoot(_a);
95 }
96
codeAt(Address _a,BlockNumber _block) const97 bytes ClientBase::codeAt(Address _a, BlockNumber _block) const
98 {
99 return blockByNumber(_block).code(_a);
100 }
101
codeHashAt(Address _a,BlockNumber _block) const102 h256 ClientBase::codeHashAt(Address _a, BlockNumber _block) const
103 {
104 return blockByNumber(_block).codeHash(_a);
105 }
106
storageAt(Address _a,BlockNumber _block) const107 map<h256, pair<u256, u256>> ClientBase::storageAt(Address _a, BlockNumber _block) const
108 {
109 return blockByNumber(_block).storage(_a);
110 }
111
112 // TODO: remove try/catch, allow exceptions
logs(unsigned _watchId) const113 LocalisedLogEntries ClientBase::logs(unsigned _watchId) const
114 {
115 LogFilter f;
116 try
117 {
118 Guard l(x_filtersWatches);
119 f = m_filters.at(m_watches.at(_watchId).id).filter;
120 }
121 catch (...)
122 {
123 return LocalisedLogEntries();
124 }
125 return logs(f);
126 }
127
logs(LogFilter const & _f) const128 LocalisedLogEntries ClientBase::logs(LogFilter const& _f) const
129 {
130 LocalisedLogEntries ret;
131 unsigned begin = min(bc().number() + 1, (unsigned)numberFromHash(_f.latest()));
132 unsigned end = min(bc().number(), min(begin, (unsigned)numberFromHash(_f.earliest())));
133
134 // Handle pending transactions differently as they're not on the block chain.
135 if (begin > bc().number())
136 {
137 Block temp = postSeal();
138 for (unsigned i = 0; i < temp.pending().size(); ++i)
139 {
140 // Might have a transaction that contains a matching log.
141 TransactionReceipt const& tr = temp.receipt(i);
142 LogEntries le = _f.matches(tr);
143 for (unsigned j = 0; j < le.size(); ++j)
144 ret.insert(ret.begin(), LocalisedLogEntry(le[j]));
145 }
146 begin = bc().number();
147 }
148
149 // Handle reverted blocks
150 // There are not so many, so let's iterate over them
151 h256s blocks;
152 h256 ancestor;
153 unsigned ancestorIndex;
154 tie(blocks, ancestor, ancestorIndex) = bc().treeRoute(_f.earliest(), _f.latest(), false);
155
156 for (size_t i = 0; i < ancestorIndex; i++)
157 prependLogsFromBlock(_f, blocks[i], BlockPolarity::Dead, ret);
158
159 // cause end is our earliest block, let's compare it with our ancestor
160 // if ancestor is smaller let's move our end to it
161 // example:
162 //
163 // 3b -> 2b -> 1b
164 // -> g
165 // 3a -> 2a -> 1a
166 //
167 // if earliest is at 2a and latest is a 3b, coverting them to numbers
168 // will give us pair (2, 3)
169 // and we want to get all logs from 1 (ancestor + 1) to 3
170 // so we have to move 2a to g + 1
171 end = min(end, (unsigned)numberFromHash(ancestor) + 1);
172
173 // Handle blocks from main chain
174 set<unsigned> matchingBlocks;
175 if (!_f.isRangeFilter())
176 for (auto const& i: _f.bloomPossibilities())
177 for (auto u: bc().withBlockBloom(i, end, begin))
178 matchingBlocks.insert(u);
179 else
180 // if it is a range filter, we want to get all logs from all blocks in given range
181 for (unsigned i = end; i <= begin; i++)
182 matchingBlocks.insert(i);
183
184 for (auto n: matchingBlocks)
185 prependLogsFromBlock(_f, bc().numberHash(n), BlockPolarity::Live, ret);
186
187 reverse(ret.begin(), ret.end());
188 return ret;
189 }
190
prependLogsFromBlock(LogFilter const & _f,h256 const & _blockHash,BlockPolarity _polarity,LocalisedLogEntries & io_logs) const191 void ClientBase::prependLogsFromBlock(LogFilter const& _f, h256 const& _blockHash, BlockPolarity _polarity, LocalisedLogEntries& io_logs) const
192 {
193 auto receipts = bc().receipts(_blockHash).receipts;
194 for (size_t i = 0; i < receipts.size(); i++)
195 {
196 TransactionReceipt receipt = receipts[i];
197 auto th = transaction(_blockHash, i).sha3();
198 LogEntries le = _f.matches(receipt);
199 for (unsigned j = 0; j < le.size(); ++j)
200 io_logs.insert(io_logs.begin(), LocalisedLogEntry(le[j], _blockHash, (BlockNumber)bc().number(_blockHash), th, i, 0, _polarity));
201 }
202 }
203
installWatch(LogFilter const & _f,Reaping _r)204 unsigned ClientBase::installWatch(LogFilter const& _f, Reaping _r)
205 {
206 h256 h = _f.sha3();
207 {
208 Guard l(x_filtersWatches);
209 if (!m_filters.count(h))
210 {
211 LOG(m_loggerWatch) << "FFF" << _f << h;
212 m_filters.insert(make_pair(h, _f));
213 }
214 }
215 return installWatch(h, _r);
216 }
217
installWatch(h256 _h,Reaping _r)218 unsigned ClientBase::installWatch(h256 _h, Reaping _r)
219 {
220 unsigned ret;
221 {
222 Guard l(x_filtersWatches);
223 ret = m_watches.size() ? m_watches.rbegin()->first + 1 : 0;
224 m_watches[ret] = ClientWatch(_h, _r);
225 LOG(m_loggerWatch) << "+++" << ret << _h;
226 }
227 #if INITIAL_STATE_AS_CHANGES
228 auto ch = logs(ret);
229 if (ch.empty())
230 ch.push_back(InitialChange);
231 {
232 Guard l(x_filtersWatches);
233 swap(m_watches[ret].changes, ch);
234 }
235 #endif
236 return ret;
237 }
238
uninstallWatch(unsigned _i)239 bool ClientBase::uninstallWatch(unsigned _i)
240 {
241 LOG(m_loggerWatch) << "XXX" << _i;
242
243 Guard l(x_filtersWatches);
244
245 auto it = m_watches.find(_i);
246 if (it == m_watches.end())
247 return false;
248 auto id = it->second.id;
249 m_watches.erase(it);
250
251 auto fit = m_filters.find(id);
252 if (fit != m_filters.end())
253 if (!--fit->second.refCount)
254 {
255 LOG(m_loggerWatch) << "*X*" << fit->first << ":" << fit->second.filter;
256 m_filters.erase(fit);
257 }
258 return true;
259 }
260
peekWatch(unsigned _watchId) const261 LocalisedLogEntries ClientBase::peekWatch(unsigned _watchId) const
262 {
263 Guard l(x_filtersWatches);
264
265 // LOG(m_loggerWatch) << "peekWatch" << _watchId;
266 auto& w = m_watches.at(_watchId);
267 // LOG(m_loggerWatch) << "lastPoll updated to " <<
268 //chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
269 if (w.lastPoll != chrono::system_clock::time_point::max())
270 w.lastPoll = chrono::system_clock::now();
271 return w.changes;
272 }
273
checkWatch(unsigned _watchId)274 LocalisedLogEntries ClientBase::checkWatch(unsigned _watchId)
275 {
276 Guard l(x_filtersWatches);
277 LocalisedLogEntries ret;
278
279 // LOG(m_loggerWatch) << "checkWatch" << _watchId;
280 auto& w = m_watches.at(_watchId);
281 // LOG(m_loggerWatch) << "lastPoll updated to " <<
282 //chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
283 std::swap(ret, w.changes);
284 if (w.lastPoll != chrono::system_clock::time_point::max())
285 w.lastPoll = chrono::system_clock::now();
286
287 return ret;
288 }
289
blockInfo(h256 _hash) const290 BlockHeader ClientBase::blockInfo(h256 _hash) const
291 {
292 if (_hash == PendingBlockHash)
293 return preSeal().info();
294 return BlockHeader(bc().block(_hash));
295 }
296
blockDetails(h256 _hash) const297 BlockDetails ClientBase::blockDetails(h256 _hash) const
298 {
299 return bc().details(_hash);
300 }
301
transaction(h256 _transactionHash) const302 Transaction ClientBase::transaction(h256 _transactionHash) const
303 {
304 return Transaction(bc().transaction(_transactionHash), CheckTransaction::Cheap);
305 }
306
localisedTransaction(h256 const & _transactionHash) const307 LocalisedTransaction ClientBase::localisedTransaction(h256 const& _transactionHash) const
308 {
309 std::pair<h256, unsigned> tl = bc().transactionLocation(_transactionHash);
310 return localisedTransaction(tl.first, tl.second);
311 }
312
transaction(h256 _blockHash,unsigned _i) const313 Transaction ClientBase::transaction(h256 _blockHash, unsigned _i) const
314 {
315 auto bl = bc().block(_blockHash);
316 RLP b(bl);
317 if (_i < b[1].itemCount())
318 return Transaction(b[1][_i].data(), CheckTransaction::Cheap);
319 else
320 return Transaction();
321 }
322
localisedTransaction(h256 const & _blockHash,unsigned _i) const323 LocalisedTransaction ClientBase::localisedTransaction(h256 const& _blockHash, unsigned _i) const
324 {
325 Transaction t = Transaction(bc().transaction(_blockHash, _i), CheckTransaction::Cheap);
326 return LocalisedTransaction(t, _blockHash, _i, numberFromHash(_blockHash));
327 }
328
transactionReceipt(h256 const & _transactionHash) const329 TransactionReceipt ClientBase::transactionReceipt(h256 const& _transactionHash) const
330 {
331 return bc().transactionReceipt(_transactionHash);
332 }
333
localisedTransactionReceipt(h256 const & _transactionHash) const334 LocalisedTransactionReceipt ClientBase::localisedTransactionReceipt(h256 const& _transactionHash) const
335 {
336 std::pair<h256, unsigned> tl = bc().transactionLocation(_transactionHash);
337 Transaction t = Transaction(bc().transaction(tl.first, tl.second), CheckTransaction::Cheap);
338 TransactionReceipt tr = bc().transactionReceipt(tl.first, tl.second);
339 u256 gasUsed = tr.cumulativeGasUsed();
340 if (tl.second > 0)
341 gasUsed -= bc().transactionReceipt(tl.first, tl.second - 1).cumulativeGasUsed();
342 return LocalisedTransactionReceipt(
343 tr,
344 t.sha3(),
345 tl.first,
346 numberFromHash(tl.first),
347 t.from(),
348 t.to(),
349 tl.second,
350 gasUsed,
351 toAddress(t.from(), t.nonce()));
352 }
353
transactionLocation(h256 const & _transactionHash) const354 pair<h256, unsigned> ClientBase::transactionLocation(h256 const& _transactionHash) const
355 {
356 return bc().transactionLocation(_transactionHash);
357 }
358
transactions(h256 _blockHash) const359 Transactions ClientBase::transactions(h256 _blockHash) const
360 {
361 auto bl = bc().block(_blockHash);
362 RLP b(bl);
363 Transactions res;
364 for (unsigned i = 0; i < b[1].itemCount(); i++)
365 res.emplace_back(b[1][i].data(), CheckTransaction::Cheap);
366 return res;
367 }
368
transactionHashes(h256 _blockHash) const369 TransactionHashes ClientBase::transactionHashes(h256 _blockHash) const
370 {
371 return bc().transactionHashes(_blockHash);
372 }
373
uncle(h256 _blockHash,unsigned _i) const374 BlockHeader ClientBase::uncle(h256 _blockHash, unsigned _i) const
375 {
376 auto bl = bc().block(_blockHash);
377 RLP b(bl);
378 if (_i < b[2].itemCount())
379 return BlockHeader(b[2][_i].data(), HeaderData);
380 else
381 return BlockHeader();
382 }
383
uncleHashes(h256 _blockHash) const384 UncleHashes ClientBase::uncleHashes(h256 _blockHash) const
385 {
386 return bc().uncleHashes(_blockHash);
387 }
388
transactionCount(h256 _blockHash) const389 unsigned ClientBase::transactionCount(h256 _blockHash) const
390 {
391 auto bl = bc().block(_blockHash);
392 RLP b(bl);
393 return b[1].itemCount();
394 }
395
uncleCount(h256 _blockHash) const396 unsigned ClientBase::uncleCount(h256 _blockHash) const
397 {
398 auto bl = bc().block(_blockHash);
399 RLP b(bl);
400 return b[2].itemCount();
401 }
402
number() const403 unsigned ClientBase::number() const
404 {
405 return bc().number();
406 }
407
pendingHashes() const408 h256s ClientBase::pendingHashes() const
409 {
410 return h256s() + postSeal().pendingHashes();
411 }
412
pendingInfo() const413 BlockHeader ClientBase::pendingInfo() const
414 {
415 return postSeal().info();
416 }
417
pendingDetails() const418 BlockDetails ClientBase::pendingDetails() const
419 {
420 auto const pendingHeader = postSeal().info();
421 auto const latestDetails = Interface::blockDetails(LatestBlock);
422 return BlockDetails{static_cast<unsigned>(pendingHeader.number()),
423 latestDetails.totalDifficulty + pendingHeader.difficulty(), pendingHeader.parentHash(),
424 h256s{} /* children */, postSeal().blockData().size()};
425 }
426
addresses(BlockNumber _block) const427 Addresses ClientBase::addresses(BlockNumber _block) const
428 {
429 Addresses ret;
430 for (auto const& i : blockByNumber(_block).addresses())
431 ret.push_back(i.first);
432 return ret;
433 }
434
gasLimitRemaining() const435 u256 ClientBase::gasLimitRemaining() const
436 {
437 return postSeal().gasLimitRemaining();
438 }
439
author() const440 Address ClientBase::author() const
441 {
442 return preSeal().author();
443 }
444
hashFromNumber(BlockNumber _number) const445 h256 ClientBase::hashFromNumber(BlockNumber _number) const
446 {
447 if (_number == PendingBlock)
448 return h256();
449 if (_number == LatestBlock)
450 return bc().currentHash();
451 return bc().numberHash(_number);
452 }
453
numberFromHash(h256 _blockHash) const454 BlockNumber ClientBase::numberFromHash(h256 _blockHash) const
455 {
456 if (_blockHash == PendingBlockHash)
457 return bc().number() + 1;
458 else if (_blockHash == LatestBlockHash)
459 return bc().number();
460 else if (_blockHash == EarliestBlockHash)
461 return 0;
462 return bc().number(_blockHash);
463 }
464
compareBlockHashes(h256 _h1,h256 _h2) const465 int ClientBase::compareBlockHashes(h256 _h1, h256 _h2) const
466 {
467 BlockNumber n1 = numberFromHash(_h1);
468 BlockNumber n2 = numberFromHash(_h2);
469
470 if (n1 > n2)
471 return 1;
472 else if (n1 == n2)
473 return 0;
474 return -1;
475 }
476
isKnown(h256 const & _hash) const477 bool ClientBase::isKnown(h256 const& _hash) const
478 {
479 return _hash == PendingBlockHash ||
480 _hash == LatestBlockHash ||
481 _hash == EarliestBlockHash ||
482 bc().isKnown(_hash);
483 }
484
isKnown(BlockNumber _block) const485 bool ClientBase::isKnown(BlockNumber _block) const
486 {
487 return _block == PendingBlock ||
488 _block == LatestBlock ||
489 bc().numberHash(_block) != h256();
490 }
491
isKnownTransaction(h256 const & _transactionHash) const492 bool ClientBase::isKnownTransaction(h256 const& _transactionHash) const
493 {
494 return bc().isKnownTransaction(_transactionHash);
495 }
496
isKnownTransaction(h256 const & _blockHash,unsigned _i) const497 bool ClientBase::isKnownTransaction(h256 const& _blockHash, unsigned _i) const
498 {
499 return isKnown(_blockHash) && block(_blockHash).pending().size() > _i;
500 }
501
blockByNumber(BlockNumber _h) const502 Block ClientBase::blockByNumber(BlockNumber _h) const
503 {
504 if (_h == PendingBlock)
505 return postSeal();
506 else if (_h == LatestBlock)
507 return block(bc().currentHash());
508 return block(bc().numberHash(_h));
509 }
510
chainId() const511 int ClientBase::chainId() const
512 {
513 return bc().chainParams().chainID;
514 }
515