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