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