1 #include <sstream>
2 #include <util/system.h>
3 #include <validation.h>
4 #include <chainparams.h>
5 #include <script/script.h>
6 #include <qtum/qtumstate.h>
7 #include <libevm/VMFace.h>
8
9 using namespace std;
10 using namespace dev;
11 using namespace dev::eth;
12
QtumState(u256 const & _accountStartNonce,OverlayDB const & _db,const string & _path,BaseState _bs)13 QtumState::QtumState(u256 const& _accountStartNonce, OverlayDB const& _db, const string& _path, BaseState _bs) :
14 State(_accountStartNonce, _db, _bs) {
15 dbUTXO = QtumState::openDB(_path + "/qtumDB", sha3(rlp("")), WithExisting::Trust);
16 stateUTXO = SecureTrieDB<Address, OverlayDB>(&dbUTXO);
17 }
18
QtumState()19 QtumState::QtumState() : dev::eth::State(dev::Invalid256, dev::OverlayDB(), dev::eth::BaseState::PreExisting) {
20 dbUTXO = OverlayDB();
21 stateUTXO = SecureTrieDB<Address, OverlayDB>(&dbUTXO);
22 }
23
execute(EnvInfo const & _envInfo,SealEngineFace const & _sealEngine,QtumTransaction const & _t,Permanence _p,OnOpFunc const & _onOp)24 ResultExecute QtumState::execute(EnvInfo const& _envInfo, SealEngineFace const& _sealEngine, QtumTransaction const& _t, Permanence _p, OnOpFunc const& _onOp){
25
26 assert(_t.getVersion().toRaw() == VersionVM::GetEVMDefault().toRaw());
27
28 addBalance(_t.sender(), _t.value() + (_t.gas() * _t.gasPrice()));
29 newAddress = _t.isCreation() ? createQtumAddress(_t.getHashWith(), _t.getNVout()) : dev::Address();
30
31 _sealEngine.deleteAddresses.insert({_t.sender(), _envInfo.author()});
32
33 h256 oldStateRoot = rootHash();
34 h256 oldUTXORoot = rootHashUTXO();
35 bool voutLimit = false;
36
37 auto onOp = _onOp;
38 #if ETH_VMTRACE
39 if (isChannelVisible<VMTraceChannel>())
40 onOp = Executive::simpleTrace(); // override tracer
41 #endif
42 // Create and initialize the executive. This will throw fairly cheaply and quickly if the
43 // transaction is bad in any way.
44 Executive e(*this, _envInfo, _sealEngine);
45 ExecutionResult res;
46 e.setResultRecipient(res);
47
48 CTransactionRef tx;
49 u256 startGasUsed;
50 const Consensus::Params& consensusParams = Params().GetConsensus();
51 try{
52 if (_t.isCreation() && _t.value())
53 BOOST_THROW_EXCEPTION(CreateWithValue());
54
55 e.initialize(_t);
56 // OK - transaction looks valid - execute.
57 startGasUsed = _envInfo.gasUsed();
58 if (!e.execute()){
59 e.go(onOp);
60 if(ChainActive().Height() >= consensusParams.QIP7Height){
61 validateTransfersWithChangeLog();
62 }
63 } else {
64 e.revert();
65 throw Exception();
66 }
67 e.finalize();
68 if (_p == Permanence::Reverted){
69 m_cache.clear();
70 cacheUTXO.clear();
71 } else {
72 deleteAccounts(_sealEngine.deleteAddresses);
73 if(res.excepted == TransactionException::None){
74 CondensingTX ctx(this, transfers, _t, _sealEngine.deleteAddresses);
75 tx = MakeTransactionRef(ctx.createCondensingTX());
76 if(ctx.reachedVoutLimit()){
77 voutLimit = true;
78 e.revert();
79 throw Exception();
80 }
81 std::unordered_map<dev::Address, Vin> vins = ctx.createVin(*tx);
82 updateUTXO(vins);
83 } else {
84 printfErrorLog(res.excepted);
85 }
86
87 qtum::commit(cacheUTXO, stateUTXO, m_cache);
88 cacheUTXO.clear();
89 bool removeEmptyAccounts = _envInfo.number() >= _sealEngine.chainParams().EIP158ForkBlock;
90 commit(removeEmptyAccounts ? State::CommitBehaviour::RemoveEmptyAccounts : State::CommitBehaviour::KeepEmptyAccounts);
91 }
92 }
93 catch(Exception const& _e){
94 printfErrorLog(dev::eth::toTransactionException(_e));
95 res.excepted = dev::eth::toTransactionException(_e);
96 res.gasUsed = _t.gas();
97 if(ChainActive().Height() < consensusParams.nFixUTXOCacheHFHeight && _p != Permanence::Reverted){
98 deleteAccounts(_sealEngine.deleteAddresses);
99 commit(CommitBehaviour::RemoveEmptyAccounts);
100 } else {
101 m_cache.clear();
102 cacheUTXO.clear();
103 }
104 }
105
106 if(!_t.isCreation())
107 res.newAddress = _t.receiveAddress();
108 newAddress = dev::Address();
109 transfers.clear();
110 if(voutLimit){
111 //use old and empty states to create virtual Out Of Gas exception
112 LogEntries logs;
113 u256 gas = _t.gas();
114 ExecutionResult ex;
115 ex.gasRefunded=0;
116 ex.gasUsed=gas;
117 ex.excepted=TransactionException();
118 //create a refund tx to send back any coins that were suppose to be sent to the contract
119 CMutableTransaction refund;
120 if(_t.value() > 0) {
121 refund.vin.push_back(CTxIn(h256Touint(_t.getHashWith()), _t.getNVout(), CScript() << OP_SPEND));
122 //note, if sender was a non-standard tx, this will send the coins to pubkeyhash 0x00, effectively destroying the coins
123 CScript script(CScript() << OP_DUP << OP_HASH160 << _t.sender().asBytes() << OP_EQUALVERIFY << OP_CHECKSIG);
124 refund.vout.push_back(CTxOut(CAmount(_t.value().convert_to<uint64_t>()), script));
125 }
126 //make sure to use empty transaction if no vouts made
127 return ResultExecute{ex, QtumTransactionReceipt(oldStateRoot, oldUTXORoot, gas, e.logs()), refund.vout.empty() ? CTransaction() : CTransaction(refund)};
128 }else{
129 return ResultExecute{res, QtumTransactionReceipt(rootHash(), rootHashUTXO(), startGasUsed + e.gasUsed(), e.logs()), tx ? *tx : CTransaction()};
130 }
131 }
132
vins() const133 std::unordered_map<dev::Address, Vin> QtumState::vins() const // temp
134 {
135 std::unordered_map<dev::Address, Vin> ret;
136 for (auto& i: cacheUTXO)
137 if (i.second.alive)
138 ret[i.first] = i.second;
139 auto addrs = addresses();
140 for (auto& i : addrs){
141 if (cacheUTXO.find(i.first) == cacheUTXO.end() && vin(i.first))
142 ret[i.first] = *vin(i.first);
143 }
144 return ret;
145 }
146
transferBalance(dev::Address const & _from,dev::Address const & _to,dev::u256 const & _value)147 void QtumState::transferBalance(dev::Address const& _from, dev::Address const& _to, dev::u256 const& _value) {
148 subBalance(_from, _value);
149 addBalance(_to, _value);
150 if (_value > 0)
151 transfers.push_back({_from, _to, _value});
152 }
153
vin(dev::Address const & _a) const154 Vin const* QtumState::vin(dev::Address const& _a) const
155 {
156 return const_cast<QtumState*>(this)->vin(_a);
157 }
158
vin(dev::Address const & _addr)159 Vin* QtumState::vin(dev::Address const& _addr)
160 {
161 auto it = cacheUTXO.find(_addr);
162 if (it == cacheUTXO.end()){
163 std::string stateBack = stateUTXO.at(_addr);
164 if (stateBack.empty())
165 return nullptr;
166
167 dev::RLP state(stateBack);
168 auto i = cacheUTXO.emplace(
169 std::piecewise_construct,
170 std::forward_as_tuple(_addr),
171 std::forward_as_tuple(Vin{state[0].toHash<dev::h256>(), state[1].toInt<uint32_t>(), state[2].toInt<dev::u256>(), state[3].toInt<uint8_t>()})
172 );
173 return &i.first->second;
174 }
175 return &it->second;
176 }
177
178 // void QtumState::commit(CommitBehaviour _commitBehaviour)
179 // {
180 // if (_commitBehaviour == CommitBehaviour::RemoveEmptyAccounts)
181 // removeEmptyAccounts();
182
183 // qtum::commit(cacheUTXO, stateUTXO, m_cache);
184 // cacheUTXO.clear();
185
186 // m_touched += dev::eth::commit(m_cache, m_state);
187 // m_changeLog.clear();
188 // m_cache.clear();
189 // m_unchangedCacheEntries.clear();
190 // }
191
kill(dev::Address _addr)192 void QtumState::kill(dev::Address _addr)
193 {
194 // If the account is not in the db, nothing to kill.
195 if (auto a = account(_addr))
196 a->kill();
197 if (auto v = vin(_addr))
198 v->alive = 0;
199 }
200
addBalance(dev::Address const & _id,dev::u256 const & _amount)201 void QtumState::addBalance(dev::Address const& _id, dev::u256 const& _amount)
202 {
203 if (dev::eth::Account* a = account(_id))
204 {
205 // Log empty account being touched. Empty touched accounts are cleared
206 // after the transaction, so this event must be also reverted.
207 // We only log the first touch (not dirty yet), and only for empty
208 // accounts, as other accounts does not matter.
209 // TODO: to save space we can combine this event with Balance by having
210 // Balance and Balance+Touch events.
211 if (!a->isDirty() && a->isEmpty())
212 m_changeLog.emplace_back(dev::eth::Change::Touch, _id);
213
214 // Increase the account balance. This also is done for value 0 to mark
215 // the account as dirty. Dirty account are not removed from the cache
216 // and are cleared if empty at the end of the transaction.
217 a->addBalance(_amount);
218 }
219 else
220 {
221 if(!addressInUse(newAddress) && newAddress != dev::Address()){
222 const_cast<dev::Address&>(_id) = newAddress;
223 newAddress = dev::Address();
224 }
225 createAccount(_id, {requireAccountStartNonce(), _amount});
226 }
227
228 if (_amount)
229 m_changeLog.emplace_back(dev::eth::Change::Balance, _id, _amount);
230 }
231
deleteAccounts(std::set<dev::Address> & addrs)232 void QtumState::deleteAccounts(std::set<dev::Address>& addrs){
233 for(dev::Address addr : addrs){
234 dev::eth::Account* acc = const_cast<dev::eth::Account*>(account(addr));
235 if(acc)
236 acc->kill();
237 Vin* in = const_cast<Vin*>(vin(addr));
238 if(in)
239 in->alive = 0;
240 }
241 }
242
updateUTXO(const std::unordered_map<dev::Address,Vin> & vins)243 void QtumState::updateUTXO(const std::unordered_map<dev::Address, Vin>& vins){
244 for(auto& v : vins){
245 Vin* vi = const_cast<Vin*>(vin(v.first));
246
247 if(vi){
248 vi->hash = v.second.hash;
249 vi->nVout = v.second.nVout;
250 vi->value = v.second.value;
251 vi->alive = v.second.alive;
252 } else if(v.second.alive > 0) {
253 cacheUTXO[v.first] = v.second;
254 }
255 }
256 }
257
printfErrorLog(const dev::eth::TransactionException er)258 void QtumState::printfErrorLog(const dev::eth::TransactionException er){
259 std::stringstream ss;
260 ss << er;
261 clog(dev::VerbosityWarning, "exec") << "VM exception:" << ss.str();
262 }
263
validateTransfersWithChangeLog()264 void QtumState::validateTransfersWithChangeLog(){
265 ChangeLog tmpChangeLog = m_changeLog;
266 std::vector<TransferInfo> validatedTransfers;
267
268 for(const TransferInfo& ti : transfers){
269 for(std::size_t i=0; i<tmpChangeLog.size(); ++i){
270 //find the log entry for the receiver of the transfer
271 if(tmpChangeLog[i].kind==Change::Balance && tmpChangeLog[i].address==ti.to && tmpChangeLog[i].value==ti.value){
272 for(std::size_t j=0; j<tmpChangeLog.size(); ++j){
273 //find the log entry for the sender of the transfer
274 if(tmpChangeLog[j].kind==Change::Balance && tmpChangeLog[j].address==ti.from && tmpChangeLog[j].value==0-ti.value){
275 // transfer is valid
276 validatedTransfers.push_back(ti);
277 // zero out found elements to avoid matching again
278 tmpChangeLog[i].address=dev::Address(0);
279 tmpChangeLog[j].address=dev::Address(0);
280 break;
281 }
282 }
283 break;
284 }
285 }
286 }
287
288 transfers=validatedTransfers;
289 }
290
deployDelegationsContract()291 void QtumState::deployDelegationsContract(){
292 dev::Address delegationsAddress = uintToh160(Params().GetConsensus().delegationsAddress);
293 if(!QtumState::addressInUse(delegationsAddress)){
294 QtumState::createContract(delegationsAddress);
295 QtumState::setCode(delegationsAddress, bytes{fromHex(DELEGATIONS_CONTRACT_CODE)}, QtumState::version(delegationsAddress));
296 commit(CommitBehaviour::RemoveEmptyAccounts);
297 db().commit();
298 }
299 }
300 ///////////////////////////////////////////////////////////////////////////////////////////
createCondensingTX()301 CTransaction CondensingTX::createCondensingTX(){
302 selectionVin();
303 calculatePlusAndMinus();
304 if(!createNewBalances())
305 return CTransaction();
306 CMutableTransaction tx;
307 tx.vin = createVins();;
308 tx.vout = createVout();
309 return !tx.vin.size() || !tx.vout.size() ? CTransaction() : CTransaction(tx);
310 }
311
createVin(const CTransaction & tx)312 std::unordered_map<dev::Address, Vin> CondensingTX::createVin(const CTransaction& tx){
313 std::unordered_map<dev::Address, Vin> vins;
314 for(auto& b : balances){
315 if(b.first == transaction.sender())
316 continue;
317
318 if(b.second > 0){
319 vins[b.first] = Vin{uintToh256(tx.GetHash()), nVouts[b.first], b.second, 1};
320 } else {
321 vins[b.first] = Vin{uintToh256(tx.GetHash()), 0, 0, 0};
322 }
323 }
324 return vins;
325 }
326
selectionVin()327 void CondensingTX::selectionVin(){
328 for(const TransferInfo& ti : transfers){
329 if(!vins.count(ti.from)){
330 if(auto a = state->vin(ti.from))
331 vins[ti.from] = *a;
332 if(ti.from == transaction.sender() && transaction.value() > 0){
333 vins[ti.from] = Vin{transaction.getHashWith(), transaction.getNVout(), transaction.value(), 1};
334 }
335 }
336
337 if(!vins.count(ti.to)){
338 if(auto a = state->vin(ti.to))
339 vins[ti.to] = *a;
340 }
341 }
342 }
343
calculatePlusAndMinus()344 void CondensingTX::calculatePlusAndMinus(){
345 for(const TransferInfo& ti : transfers){
346 if(!plusMinusInfo.count(ti.from)){
347 plusMinusInfo[ti.from] = std::make_pair(0, ti.value);
348 } else {
349 plusMinusInfo[ti.from] = std::make_pair(plusMinusInfo[ti.from].first, plusMinusInfo[ti.from].second + ti.value);
350 }
351
352 if(!plusMinusInfo.count(ti.to)){
353 plusMinusInfo[ti.to] = std::make_pair(ti.value, 0);
354 } else {
355 plusMinusInfo[ti.to] = std::make_pair(plusMinusInfo[ti.to].first + ti.value, plusMinusInfo[ti.to].second);
356 }
357 }
358 }
359
createNewBalances()360 bool CondensingTX::createNewBalances(){
361 for(auto& p : plusMinusInfo){
362 dev::u256 balance = 0;
363 if((vins.count(p.first) && vins[p.first].alive) || (!vins[p.first].alive && !checkDeleteAddress(p.first))){
364 balance = vins[p.first].value;
365 }
366 balance += p.second.first;
367 if(balance < p.second.second)
368 return false;
369 balance -= p.second.second;
370 balances[p.first] = balance;
371 }
372 return true;
373 }
374
createVins()375 std::vector<CTxIn> CondensingTX::createVins(){
376 std::vector<CTxIn> ins;
377 for(auto& v : vins){
378 if((v.second.value > 0 && v.second.alive) || (v.second.value > 0 && !vins[v.first].alive && !checkDeleteAddress(v.first)))
379 ins.push_back(CTxIn(h256Touint(v.second.hash), v.second.nVout, CScript() << OP_SPEND));
380 }
381 return ins;
382 }
383
createVout()384 std::vector<CTxOut> CondensingTX::createVout(){
385 size_t count = 0;
386 std::vector<CTxOut> outs;
387 for(auto& b : balances){
388 if(b.second > 0){
389 CScript script;
390 auto* a = state->account(b.first);
391 if(a && a->isAlive()){
392 //create a no-exec contract output
393 script = CScript() << valtype{0} << valtype{0} << valtype{0} << valtype{0} << b.first.asBytes() << OP_CALL;
394 } else {
395 script = CScript() << OP_DUP << OP_HASH160 << b.first.asBytes() << OP_EQUALVERIFY << OP_CHECKSIG;
396 }
397 outs.push_back(CTxOut(CAmount(b.second), script));
398 nVouts[b.first] = count;
399 count++;
400 }
401 if(count > MAX_CONTRACT_VOUTS){
402 voutOverflow=true;
403 return outs;
404 }
405 }
406 return outs;
407 }
408
checkDeleteAddress(dev::Address addr)409 bool CondensingTX::checkDeleteAddress(dev::Address addr){
410 return deleteAddresses.count(addr) != 0;
411 }
412 ///////////////////////////////////////////////////////////////////////////////////////////
413