1 #pragma once 2 3 #include <libdevcore/UndefMacros.h> 4 #include <libethereum/State.h> 5 #include <libevm/ExtVMFace.h> 6 #include <crypto/sha256.h> 7 #include <crypto/ripemd160.h> 8 #include <uint256.h> 9 #include <util/convert.h> 10 #include <primitives/transaction.h> 11 #include <qtum/qtumtransaction.h> 12 13 #include <libethereum/Executive.h> 14 #include <libethcore/SealEngine.h> 15 16 using OnOpFunc = std::function<void(uint64_t, uint64_t, dev::eth::Instruction, dev::bigint, dev::bigint, 17 dev::bigint, dev::eth::VMFace const*, dev::eth::ExtVMFace const*)>; 18 using plusAndMinus = std::pair<dev::u256, dev::u256>; 19 using valtype = std::vector<unsigned char>; 20 21 struct TransferInfo{ 22 dev::Address from; 23 dev::Address to; 24 dev::u256 value; 25 }; 26 27 struct Vin{ 28 dev::h256 hash; 29 uint32_t nVout; 30 dev::u256 value; 31 uint8_t alive; 32 }; 33 34 class QtumTransactionReceipt: public dev::eth::TransactionReceipt { 35 public: QtumTransactionReceipt(dev::h256 const & state_root,dev::h256 const & utxo_root,dev::u256 const & gas_used,dev::eth::LogEntries const & log)36 QtumTransactionReceipt(dev::h256 const& state_root, dev::h256 const& utxo_root, dev::u256 const& gas_used, dev::eth::LogEntries const& log) : dev::eth::TransactionReceipt(state_root, gas_used, log), m_utxoRoot(utxo_root) {} 37 utxoRoot()38 dev::h256 const& utxoRoot() const { 39 return m_utxoRoot; 40 } 41 private: 42 dev::h256 m_utxoRoot; 43 }; 44 45 struct ResultExecute{ 46 dev::eth::ExecutionResult execRes; 47 QtumTransactionReceipt txRec; 48 CTransaction tx; 49 }; 50 51 namespace qtum{ 52 template <class DB> commit(std::unordered_map<dev::Address,Vin> const & _cache,dev::eth::SecureTrieDB<dev::Address,DB> & _state,std::unordered_map<dev::Address,dev::eth::Account> const & _cacheAcc)53 dev::AddressHash commit(std::unordered_map<dev::Address, Vin> const& _cache, dev::eth::SecureTrieDB<dev::Address, DB>& _state, std::unordered_map<dev::Address, dev::eth::Account> const& _cacheAcc) 54 { 55 dev::AddressHash ret; 56 for (auto const& i: _cache){ 57 if(i.second.alive == 0){ 58 _state.remove(i.first); 59 } else { 60 dev::RLPStream s(4); 61 s << i.second.hash << i.second.nVout << i.second.value << i.second.alive; 62 _state.insert(i.first, &s.out()); 63 } 64 ret.insert(i.first); 65 } 66 return ret; 67 } 68 } 69 70 class CondensingTX; 71 72 class QtumState : public dev::eth::State { 73 74 public: 75 76 QtumState(); 77 78 QtumState(dev::u256 const& _accountStartNonce, dev::OverlayDB const& _db, const std::string& _path, dev::eth::BaseState _bs = dev::eth::BaseState::PreExisting); 79 80 ResultExecute execute(dev::eth::EnvInfo const& _envInfo, dev::eth::SealEngineFace const& _sealEngine, QtumTransaction const& _t, dev::eth::Permanence _p = dev::eth::Permanence::Committed, dev::eth::OnOpFunc const& _onOp = OnOpFunc()); 81 setRootUTXO(dev::h256 const & _r)82 void setRootUTXO(dev::h256 const& _r) { cacheUTXO.clear(); stateUTXO.setRoot(_r); } 83 setCacheUTXO(dev::Address const & address,Vin const & vin)84 void setCacheUTXO(dev::Address const& address, Vin const& vin) { cacheUTXO.insert(std::make_pair(address, vin)); } 85 rootHashUTXO()86 dev::h256 rootHashUTXO() const { return stateUTXO.root(); } 87 88 std::unordered_map<dev::Address, Vin> vins() const; // temp 89 dbUtxo()90 dev::OverlayDB const& dbUtxo() const { return dbUTXO; } 91 dbUtxo()92 dev::OverlayDB& dbUtxo() { return dbUTXO; } 93 createQtumAddress(dev::h256 hashTx,uint32_t voutNumber)94 static const dev::Address createQtumAddress(dev::h256 hashTx, uint32_t voutNumber){ 95 uint256 hashTXid(h256Touint(hashTx)); 96 std::vector<unsigned char> txIdAndVout(hashTXid.begin(), hashTXid.end()); 97 std::vector<unsigned char> voutNumberChrs; 98 if (voutNumberChrs.size() < sizeof(voutNumber))voutNumberChrs.resize(sizeof(voutNumber)); 99 std::memcpy(voutNumberChrs.data(), &voutNumber, sizeof(voutNumber)); 100 txIdAndVout.insert(txIdAndVout.end(),voutNumberChrs.begin(),voutNumberChrs.end()); 101 102 std::vector<unsigned char> SHA256TxVout(32); 103 CSHA256().Write(txIdAndVout.data(), txIdAndVout.size()).Finalize(SHA256TxVout.data()); 104 105 std::vector<unsigned char> hashTxIdAndVout(20); 106 CRIPEMD160().Write(SHA256TxVout.data(), SHA256TxVout.size()).Finalize(hashTxIdAndVout.data()); 107 108 return dev::Address(hashTxIdAndVout); 109 } 110 111 void deployDelegationsContract(); 112 ~QtumState()113 virtual ~QtumState(){} 114 115 friend CondensingTX; 116 117 private: 118 119 void transferBalance(dev::Address const& _from, dev::Address const& _to, dev::u256 const& _value); 120 121 Vin const* vin(dev::Address const& _a) const; 122 123 Vin* vin(dev::Address const& _addr); 124 125 // void commit(CommitBehaviour _commitBehaviour); 126 127 void kill(dev::Address _addr); 128 129 void addBalance(dev::Address const& _id, dev::u256 const& _amount); 130 131 void deleteAccounts(std::set<dev::Address>& addrs); 132 133 void updateUTXO(const std::unordered_map<dev::Address, Vin>& vins); 134 135 void printfErrorLog(const dev::eth::TransactionException er); 136 137 dev::Address newAddress; 138 139 std::vector<TransferInfo> transfers; 140 141 dev::OverlayDB dbUTXO; 142 143 dev::eth::SecureTrieDB<dev::Address, dev::OverlayDB> stateUTXO; 144 145 std::unordered_map<dev::Address, Vin> cacheUTXO; 146 147 void validateTransfersWithChangeLog(); 148 }; 149 150 151 struct TemporaryState{ 152 std::unique_ptr<QtumState>& globalStateRef; 153 dev::h256 oldHashStateRoot; 154 dev::h256 oldHashUTXORoot; 155 TemporaryStateTemporaryState156 TemporaryState(std::unique_ptr<QtumState>& _globalStateRef) : 157 globalStateRef(_globalStateRef), 158 oldHashStateRoot(globalStateRef->rootHash()), 159 oldHashUTXORoot(globalStateRef->rootHashUTXO()) {} 160 SetRootTemporaryState161 void SetRoot(dev::h256 newHashStateRoot, dev::h256 newHashUTXORoot) 162 { 163 globalStateRef->setRoot(newHashStateRoot); 164 globalStateRef->setRootUTXO(newHashUTXORoot); 165 } 166 ~TemporaryStateTemporaryState167 ~TemporaryState(){ 168 globalStateRef->setRoot(oldHashStateRoot); 169 globalStateRef->setRootUTXO(oldHashUTXORoot); 170 } 171 TemporaryState() = delete; 172 TemporaryState(const TemporaryState&) = delete; 173 TemporaryState& operator=(const TemporaryState&) = delete; 174 TemporaryState(TemporaryState&&) = delete; 175 TemporaryState& operator=(TemporaryState&&) = delete; 176 }; 177 178 179 /////////////////////////////////////////////////////////////////////////////////////////// 180 class CondensingTX{ 181 182 public: 183 transfers(_transfers)184 CondensingTX(QtumState* _state, const std::vector<TransferInfo>& _transfers, const QtumTransaction& _transaction, std::set<dev::Address> _deleteAddresses = std::set<dev::Address>()) : transfers(_transfers), deleteAddresses(_deleteAddresses), transaction(_transaction), state(_state){} 185 186 CTransaction createCondensingTX(); 187 188 std::unordered_map<dev::Address, Vin> createVin(const CTransaction& tx); 189 reachedVoutLimit()190 bool reachedVoutLimit(){ return voutOverflow; } 191 192 private: 193 194 void selectionVin(); 195 196 void calculatePlusAndMinus(); 197 198 bool createNewBalances(); 199 200 std::vector<CTxIn> createVins(); 201 202 std::vector<CTxOut> createVout(); 203 204 bool checkDeleteAddress(dev::Address addr); 205 206 std::map<dev::Address, plusAndMinus> plusMinusInfo; 207 208 std::map<dev::Address, dev::u256> balances; 209 210 std::map<dev::Address, uint32_t> nVouts; 211 212 std::map<dev::Address, Vin> vins; 213 214 const std::vector<TransferInfo>& transfers; 215 216 //We don't need the ordered nature of "set" here, but unordered_set's theoretical worst complexity is O(n), whereas set is O(log n) 217 //So, making this unordered_set could be an attack vector 218 const std::set<dev::Address> deleteAddresses; 219 220 const QtumTransaction& transaction; 221 222 QtumState* state; 223 224 bool voutOverflow = false; 225 226 }; 227 /////////////////////////////////////////////////////////////////////////////////////////// 228