Browse Source

Merge branch 'develop-evmcc' into pr-jit

cl-refactor
Paweł Bylica 10 years ago
parent
commit
4ac6ebb790
  1. 3
      alethzero/CMakeLists.txt
  2. 7
      alethzero/MainWin.cpp
  3. 12
      eth/main.cpp
  4. 2
      libdevcore/Common.cpp
  5. 18
      libethcore/BlockInfo.cpp
  6. 4
      libethcore/BlockInfo.h
  7. 4
      libethcore/CommonEth.cpp
  8. 21
      libethereum/BlockChain.cpp
  9. 12
      libethereum/BlockChain.h
  10. 22
      libethereum/BlockDetails.h
  11. 3
      libethereum/CMakeLists.txt
  12. 18
      libethereum/Executive.cpp
  13. 2
      libethereum/Interface.h
  14. 7
      libethereum/State.cpp
  15. 8
      libethereum/State.h
  16. 28
      libethereum/VMFactory.cpp
  17. 28
      libethereum/VMFactory.h
  18. 6
      libevm/FeeStructure.cpp
  19. 6
      libevm/FeeStructure.h
  20. 17
      libevm/VM.h
  21. 12
      libevm/VMFace.cpp
  22. 6
      libevm/VMFace.h
  23. 3
      libevmjit/Compiler.cpp
  24. 8
      libevmjit/Ext.cpp
  25. 18
      libevmjit/GasMeter.cpp
  26. 3
      libevmjit/GasMeter.h
  27. 1
      libevmjit/VM.cpp
  28. 8
      libevmjit/VM.h
  29. 2
      libsolidity/ExpressionCompiler.cpp
  30. 2
      libsolidity/GlobalContext.cpp
  31. 2
      libsolidity/Types.cpp
  32. 1
      libweb3jsonrpc/WebThreeStubServer.cpp
  33. 6
      libwhisper/WhisperHost.cpp
  34. 9
      libwhisper/WhisperHost.h
  35. 14
      libwhisper/WhisperPeer.cpp
  36. 2
      libwhisper/WhisperPeer.h
  37. 18
      neth/main.cpp
  38. 3
      test/createRandomTest.cpp
  39. 10
      test/vm.cpp

3
alethzero/CMakeLists.txt

@ -54,6 +54,9 @@ endif ()
qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets)
target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 gmp ${CRYPTOPP_LS} serpent lll solidity evmcore devcore web3jsonrpc jsqrc)
if (EVMJIT)
target_link_libraries(${EXECUTEABLE} evmjit)
endif()
if (APPLE)
# First have qt5 install plugins and frameworks

7
alethzero/MainWin.cpp

@ -1259,7 +1259,6 @@ void Main::on_blocks_currentItemChanged()
s << "<br/>D/TD: <b>2^" << log2((double)info.difficulty) << "</b>/<b>2^" << log2((double)details.totalDifficulty) << "</b>";
s << "&nbsp;&emsp;&nbsp;Children: <b>" << details.children.size() << "</b></h5>";
s << "<br/>Gas used/limit: <b>" << info.gasUsed << "</b>/<b>" << info.gasLimit << "</b>";
s << "&nbsp;&emsp;&nbsp;Minimum gas price: <b>" << formatBalance(info.minGasPrice) << "</b>";
s << "<br/>Coinbase: <b>" << pretty(info.coinbaseAddress).toHtmlEscaped().toStdString() << "</b> " << info.coinbaseAddress;
s << "<br/>Nonce: <b>" << info.nonce << "</b>";
s << "<br/>Parent: <b>" << info.parentHash << "</b>";
@ -1665,7 +1664,7 @@ void Main::on_data_textChanged()
errs.append("<div style=\"border-left: 6px solid #c00; margin-top: 2px\">" + QString::fromStdString(i).toHtmlEscaped() + "</div>");
}
ui->code->setHtml(errs + lll + solidity + "<h4>Code</h4>" + QString::fromStdString(disassemble(m_data)).toHtmlEscaped());
ui->gas->setMinimum((qint64)Client::txGas(m_data.size(), 0));
ui->gas->setMinimum((qint64)Client::txGas(m_data, 0));
if (!ui->gas->isEnabled())
ui->gas->setValue(m_backupGas);
ui->gas->setEnabled(true);
@ -1676,7 +1675,7 @@ void Main::on_data_textChanged()
ui->code->setHtml(QString::fromStdString(dev::memDump(m_data, 8, true)));
if (ethereum()->codeAt(fromString(ui->destination->currentText()), 0).size())
{
ui->gas->setMinimum((qint64)Client::txGas(m_data.size(), 1));
ui->gas->setMinimum((qint64)Client::txGas(m_data, 1));
if (!ui->gas->isEnabled())
ui->gas->setValue(m_backupGas);
ui->gas->setEnabled(true);
@ -1685,7 +1684,7 @@ void Main::on_data_textChanged()
{
if (ui->gas->isEnabled())
m_backupGas = ui->gas->value();
ui->gas->setValue((qint64)Client::txGas(m_data.size()));
ui->gas->setValue((qint64)Client::txGas(m_data));
ui->gas->setEnabled(false);
}
}

12
eth/main.cpp

@ -492,14 +492,12 @@ int main(int argc, char** argv)
cnote << ssbd.str();
int ssize = sechex.length();
int size = hexAddr.length();
u256 minGas = (u256)Client::txGas(data.size(), 0);
u256 minGas = (u256)Client::txGas(data, 0);
if (size < 40)
{
if (size > 0)
cwarn << "Invalid address length:" << size;
}
else if (gasPrice < info.minGasPrice)
cwarn << "Minimum gas price is" << info.minGasPrice;
else if (gas < minGas)
cwarn << "Minimum gas amount is" << minGas;
else if (ssize < 40)
@ -559,9 +557,9 @@ int main(int argc, char** argv)
auto h = bc.currentHash();
auto blockData = bc.block(h);
BlockInfo info(blockData);
u256 minGas = (u256)Client::txGas(0, 0);
u256 minGas = (u256)Client::txGas(bytes(), 0);
Address dest = h160(fromHex(hexAddr));
c->transact(us.secret(), amount, dest, bytes(), minGas, info.minGasPrice);
c->transact(us.secret(), amount, dest, bytes(), minGas);
}
}
else
@ -598,11 +596,9 @@ int main(int argc, char** argv)
cnote << "Init:";
cnote << ssc.str();
}
u256 minGas = (u256)Client::txGas(init.size(), 0);
u256 minGas = (u256)Client::txGas(init, 0);
if (endowment < 0)
cwarn << "Invalid endowment";
else if (gasPrice < info.minGasPrice)
cwarn << "Minimum gas price is" << info.minGasPrice;
else if (gas < minGas)
cwarn << "Minimum gas amount is" << minGas;
else

2
libdevcore/Common.cpp

@ -27,7 +27,7 @@ using namespace dev;
namespace dev
{
char const* Version = "0.7.10";
char const* Version = "0.7.11";
}

18
libethcore/BlockInfo.cpp

@ -58,9 +58,9 @@ h256 BlockInfo::headerHashWithoutNonce() const
void BlockInfo::streamRLP(RLPStream& _s, bool _nonce) const
{
_s.appendList(_nonce ? 15 : 14)
_s.appendList(_nonce ? 14 : 13)
<< parentHash << sha3Uncles << coinbaseAddress << stateRoot << transactionsRoot << receiptsRoot << logBloom
<< difficulty << number << minGasPrice << gasLimit << gasUsed << timestamp << extraData;
<< difficulty << number << gasLimit << gasUsed << timestamp << extraData;
if (_nonce)
_s << nonce;
}
@ -86,12 +86,11 @@ void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce)
logBloom = _header[field = 6].toHash<h512>();
difficulty = _header[field = 7].toInt<u256>();
number = _header[field = 8].toInt<u256>();
minGasPrice = _header[field = 9].toInt<u256>();
gasLimit = _header[field = 10].toInt<u256>();
gasUsed = _header[field = 11].toInt<u256>();
timestamp = _header[field = 12].toInt<u256>();
extraData = _header[field = 13].toBytes();
nonce = _header[field = 14].toHash<h256>();
gasLimit = _header[field = 9].toInt<u256>();
gasUsed = _header[field = 10].toInt<u256>();
timestamp = _header[field = 11].toInt<u256>();
extraData = _header[field = 12].toBytes();
nonce = _header[field = 13].toHash<h256>();
}
catch (Exception const& _e)
@ -147,9 +146,6 @@ void BlockInfo::verifyInternals(bytesConstRef _block) const
if (transactionsRoot != t.root())
BOOST_THROW_EXCEPTION(InvalidTransactionsHash(t.root(), transactionsRoot));
if (minGasPrice > mgp)
BOOST_THROW_EXCEPTION(InvalidMinGasPrice(minGasPrice, mgp));
if (sha3Uncles != sha3(root[2].data()))
BOOST_THROW_EXCEPTION(InvalidUnclesHash());
}

4
libethcore/BlockInfo.h

@ -66,7 +66,6 @@ public:
h512 logBloom; // TODO LogBloom - get include
u256 difficulty;
u256 number;
u256 minGasPrice;
u256 gasLimit;
u256 gasUsed;
u256 timestamp;
@ -95,7 +94,6 @@ public:
logBloom == _cmp.logBloom &&
difficulty == _cmp.difficulty &&
number == _cmp.number &&
minGasPrice == _cmp.minGasPrice &&
gasLimit == _cmp.gasLimit &&
gasUsed == _cmp.gasUsed &&
timestamp == _cmp.timestamp &&
@ -122,7 +120,7 @@ public:
inline std::ostream& operator<<(std::ostream& _out, BlockInfo const& _bi)
{
_out << _bi.hash << " " << _bi.parentHash << " " << _bi.sha3Uncles << " " << _bi.coinbaseAddress << " " << _bi.stateRoot << " " << _bi.transactionsRoot << " " <<
_bi.receiptsRoot << " " << _bi.logBloom << " " << _bi.difficulty << " " << _bi.number << " " << _bi.minGasPrice << " " << _bi.gasLimit << " " <<
_bi.receiptsRoot << " " << _bi.logBloom << " " << _bi.difficulty << " " << _bi.number << " " << _bi.gasLimit << " " <<
_bi.gasUsed << " " << _bi.timestamp << " " << _bi.nonce;
return _out;
}

4
libethcore/CommonEth.cpp

@ -33,8 +33,8 @@ namespace dev
namespace eth
{
const unsigned c_protocolVersion = 44;
const unsigned c_databaseVersion = 4;
const unsigned c_protocolVersion = 45;
const unsigned c_databaseVersion = 5;
static const vector<pair<u256, string>> g_units =
{

21
libethereum/BlockChain.cpp

@ -101,9 +101,8 @@ bytes BlockChain::createGenesisBlock()
stateRoot = state.root();
}
block.appendList(15)
// TODO: maybe make logbloom correct?
<< h256() << EmptyListSHA3 << h160() << stateRoot << EmptyTrie << EmptyTrie << LogBloom() << c_genesisDifficulty << 0 << 0 << 1000000 << 0 << (unsigned)0 << string() << sha3(bytes(1, 42));
block.appendList(14)
<< h256() << EmptyListSHA3 << h160() << stateRoot << EmptyTrie << EmptyTrie << LogBloom() << c_genesisDifficulty << 0 << 1000000 << 0 << (unsigned)0 << string() << sha3(bytes(1, 42));
block.appendRaw(RLPEmptyList);
block.appendRaw(RLPEmptyList);
return block.out();
@ -169,8 +168,6 @@ void BlockChain::close()
delete m_db;
m_lastBlockHash = m_genesisHash;
m_details.clear();
m_blooms.clear();
m_traces.clear();
m_cache.clear();
}
@ -307,14 +304,10 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
State s(bi.coinbaseAddress, _db);
auto tdIncrease = s.enactOn(&_block, bi, *this);
auto b = s.oldBloom();
BlockBlooms bb;
BlockTraces bt;
BlockLogBlooms blb;
BlockReceipts br;
for (unsigned i = 0; i < s.pending().size(); ++i)
{
bb.blooms.push_back(s.changesFromPending(i).bloom());
bt.traces.push_back(s.changesFromPending(i));
blb.blooms.push_back(s.receipt(i).bloom());
br.receipts.push_back(s.receipt(i));
}
@ -330,14 +323,6 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
m_details[newHash] = BlockDetails((unsigned)pd.number + 1, td, bi.parentHash, {}, b);
m_details[bi.parentHash].children.push_back(newHash);
}
{
WriteGuard l(x_blooms);
m_blooms[newHash] = bb;
}
{
WriteGuard l(x_traces);
m_traces[newHash] = bt;
}
{
WriteGuard l(x_logBlooms);
m_logBlooms[newHash] = blb;
@ -349,8 +334,6 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
m_extrasDB->Put(m_writeOptions, toSlice(newHash), (ldb::Slice)dev::ref(m_details[newHash].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(bi.parentHash), (ldb::Slice)dev::ref(m_details[bi.parentHash].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(newHash, 1), (ldb::Slice)dev::ref(m_blooms[newHash].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(newHash, 2), (ldb::Slice)dev::ref(m_traces[newHash].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(newHash, 3), (ldb::Slice)dev::ref(m_logBlooms[newHash].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(newHash, 4), (ldb::Slice)dev::ref(m_receipts[newHash].rlp()));
m_db->Put(m_writeOptions, toSlice(newHash), (ldb::Slice)ref(_block));

12
libethereum/BlockChain.h

@ -101,14 +101,6 @@ public:
BlockDetails details(h256 _hash) const { return queryExtras<BlockDetails, 0>(_hash, m_details, x_details, NullBlockDetails); }
BlockDetails details() const { return details(currentHash()); }
/// Get the transactions' bloom filters of a block (or the most recent mined if none given). Thread-safe.
BlockBlooms blooms(h256 _hash) const { return queryExtras<BlockBlooms, 1>(_hash, m_blooms, x_blooms, NullBlockBlooms); }
BlockBlooms blooms() const { return blooms(currentHash()); }
/// Get the transactions' trace manifests of a block (or the most recent mined if none given). Thread-safe.
BlockTraces traces(h256 _hash) const { return queryExtras<BlockTraces, 2>(_hash, m_traces, x_traces, NullBlockTraces); }
BlockTraces traces() const { return traces(currentHash()); }
/// Get the transactions' log blooms of a block (or the most recent mined if none given). Thread-safe.
BlockLogBlooms logBlooms(h256 _hash) const { return queryExtras<BlockLogBlooms, 3>(_hash, m_logBlooms, x_logBlooms, NullBlockLogBlooms); }
BlockLogBlooms logBlooms() const { return logBlooms(currentHash()); }
@ -193,10 +185,6 @@ private:
/// The caches of the disk DB and their locks.
mutable boost::shared_mutex x_details;
mutable BlockDetailsHash m_details;
mutable boost::shared_mutex x_blooms;
mutable BlockBloomsHash m_blooms;
mutable boost::shared_mutex x_traces;
mutable BlockTracesHash m_traces;
mutable boost::shared_mutex x_logBlooms;
mutable BlockLogBloomsHash m_logBlooms;
mutable boost::shared_mutex x_receipts;

22
libethereum/BlockDetails.h

@ -54,24 +54,6 @@ struct BlockDetails
h256 bloom;
};
struct BlockBlooms
{
BlockBlooms() {}
BlockBlooms(RLP const& _r) { blooms = _r.toVector<h256>(); }
bytes rlp() const { RLPStream s; s << blooms; return s.out(); }
h256s blooms;
};
struct BlockTraces
{
BlockTraces() {}
BlockTraces(RLP const& _r) { for (auto const& i: _r) traces.emplace_back(i.data()); }
bytes rlp() const { RLPStream s(traces.size()); for (auto const& i: traces) i.streamRLP(s); return s.out(); }
Manifests traces;
};
struct BlockLogBlooms
{
BlockLogBlooms() {}
@ -91,14 +73,10 @@ struct BlockReceipts
};
typedef std::map<h256, BlockDetails> BlockDetailsHash;
typedef std::map<h256, BlockBlooms> BlockBloomsHash;
typedef std::map<h256, BlockTraces> BlockTracesHash;
typedef std::map<h256, BlockLogBlooms> BlockLogBloomsHash;
typedef std::map<h256, BlockReceipts> BlockReceiptsHash;
static const BlockDetails NullBlockDetails;
static const BlockBlooms NullBlockBlooms;
static const BlockTraces NullBlockTraces;
static const BlockLogBlooms NullBlockLogBlooms;
static const BlockReceipts NullBlockReceipts;

3
libethereum/CMakeLists.txt

@ -28,6 +28,9 @@ endif()
target_link_libraries(${EXECUTABLE} ${LEVELDB_LS})
target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS})
target_link_libraries(${EXECUTABLE} gmp)
if (EVMJIT)
target_link_libraries(${EXECUTABLE} evmjit)
endif()
if("${TARGET_PLATFORM}" STREQUAL "w64")
target_link_libraries(${EXECUTABLE} boost_system-mt-s)

18
libethereum/Executive.cpp

@ -22,6 +22,7 @@
#include <boost/timer.hpp>
#include <libdevcore/CommonIO.h>
#include <libevm/VM.h>
#include "Interface.h"
#include "Executive.h"
#include "State.h"
#include "ExtVM.h"
@ -58,15 +59,8 @@ bool Executive::setup(bytesConstRef _rlp)
BOOST_THROW_EXCEPTION(InvalidNonce(nonceReq, m_t.nonce()));
}
// Don't like transactions whose gas price is too low. NOTE: this won't stay here forever - it's just until we get a proper gas price discovery protocol going.
if (m_t.gasPrice() < m_s.m_currentBlock.minGasPrice)
{
clog(StateDetail) << "Offered gas-price is too low: Require >" << m_s.m_currentBlock.minGasPrice << " Got" << m_t.gasPrice();
BOOST_THROW_EXCEPTION(GasPriceTooLow());
}
// Check gas cost is enough.
u256 gasCost = m_t.data().size() * c_txDataGas + c_txGas;
auto gasCost = Interface::txGas(m_t.data());
if (m_t.gas() < gasCost)
{
@ -106,9 +100,9 @@ bool Executive::setup(bytesConstRef _rlp)
}
if (m_t.isCreation())
return create(m_sender, m_t.value(), m_t.gasPrice(), m_t.gas() - gasCost, &m_t.data(), m_sender);
return create(m_sender, m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)gasCost, &m_t.data(), m_sender);
else
return call(m_t.receiveAddress(), m_sender, m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - gasCost, m_sender);
return call(m_t.receiveAddress(), m_sender, m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)gasCost, m_sender);
}
bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256 _gas, Address _originAddress)
@ -118,7 +112,7 @@ bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _valu
if (m_s.addressHasCode(_receiveAddress))
{
m_vm = VMFace::create(VMFace::Interpreter, _gas).release();
m_vm = VMFactory::create(VMFactory::Interpreter, _gas).release();
bytes const& c = m_s.code(_receiveAddress);
m_ext = new ExtVM(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_ms);
}
@ -137,7 +131,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g
m_s.m_cache[m_newAddress] = Account(m_s.balance(m_newAddress) + _endowment, Account::ContractConception);
// Execute _init.
m_vm = VMFace::create(VMFace::Interpreter, _gas).release();
m_vm = VMFactory::create(VMFactory::Interpreter, _gas).release();
m_ext = new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, m_ms);
return _init.empty();
}

2
libethereum/Interface.h

@ -128,7 +128,7 @@ public:
virtual Addresses addresses(int _block) const = 0;
/// Get the fee associated for a transaction with the given data.
static u256 txGas(unsigned _dataCount, u256 _gas = 0) { return c_txDataGas * _dataCount + c_txGas + _gas; }
template <class T> static bigint txGas(T const& _data, u256 _gas = 0) { bigint ret = c_txGas + _gas; for (auto i: _data) ret += i ? c_txDataNonZeroGas : c_txDataZeroGas; return ret; }
/// Get the remaining gas limit in this block.
virtual u256 gasLimitRemaining() const = 0;

7
libethereum/State.cpp

@ -54,7 +54,7 @@ void ecrecoverCode(bytesConstRef _in, bytesRef _out)
memcpy(&in, _in.data(), min(_in.size(), sizeof(in)));
memset(_out.data(), 0, _out.size());
if (in.v > 28)
if ((u256)in.v > 28)
return;
SignatureStruct sig{in.r, in.s, (byte)((int)(u256)in.v - 27)};
if (!sig.isValid())
@ -503,7 +503,6 @@ void State::resetCurrent()
m_currentBlock.timestamp = time(0);
m_currentBlock.transactionsRoot = h256();
m_currentBlock.sha3Uncles = h256();
m_currentBlock.minGasPrice = 10 * szabo;
m_currentBlock.populateFromParent(m_previousBlock);
// Update timestamp according to clock.
@ -1216,7 +1215,7 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA
}
else if (addressHasCode(_codeAddress))
{
auto vmObj = VMFace::create(getVMKind(), *_gas);
auto vmObj = VMFactory::create(getVMKind(), *_gas);
auto& vm = *vmObj;
ExtVM evm(*this, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &code(_codeAddress), o_ms, _level);
bool revert = false;
@ -1276,7 +1275,7 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas,
m_cache[newAddress] = Account(balance(newAddress) + _endowment, Account::ContractConception);
// Execute init code.
auto vmObj = VMFace::create(getVMKind(), *_gas);
auto vmObj = VMFactory::create(getVMKind(), *_gas);
auto& vm = *vmObj;
ExtVM evm(*this, newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level);
bool revert = false;

8
libethereum/State.h

@ -30,6 +30,7 @@
#include <libethcore/Exceptions.h>
#include <libethcore/BlockInfo.h>
#include <libethcore/ProofOfWork.h>
#include <libethereum/VMFactory.h>
#include <libevm/FeeStructure.h>
#include <libevm/ExtVMFace.h>
#include <libevm/VMFace.h>
@ -39,6 +40,7 @@
#include "TransactionReceipt.h"
#include "Executive.h"
#include "AccountDiff.h"
#include "VMFactory.h"
namespace dev
{
@ -261,10 +263,10 @@ public:
void cleanup(bool _fullCommit);
/// Sets VM kind to be used by the state
void setVMKind(VMFace::Kind _kind) { m_vmKind = _kind; }
void setVMKind(VMFactory::Kind _kind) { m_vmKind = _kind; }
/// Get the kind of VM used by the state
VMFace::Kind getVMKind() const { return m_vmKind; }
VMFactory::Kind getVMKind() const { return m_vmKind; }
private:
/// Undo the changes to the state for committing to mine.
@ -333,7 +335,7 @@ private:
u256 m_blockReward;
VMFace::Kind m_vmKind = VMFace::Interpreter; ///< The kind of VM used by the state
VMFactory::Kind m_vmKind = VMFactory::Interpreter; ///< The kind of VM used by the state
static std::string c_defaultPath;

28
libethereum/VMFactory.cpp

@ -0,0 +1,28 @@
#include <libevm/VM.h>
#if ETH_EVMJIT
#include<libevmjit/VM.h>
#endif
#include "VMFactory.h"
namespace dev
{
namespace eth
{
std::unique_ptr<VMFace> VMFactory::create(VMFactory::Kind _kind, u256 _gas)
{
#if ETH_EVMJIT
auto vm = _kind == Kind::JIT ? static_cast<VMFace*>(new jit::VM)
: static_cast<VMFace*>(new VM);
#else
VMFace* vm = new VM;
#endif
vm->reset(_gas);
return std::unique_ptr<VMFace>(vm);
}
}
}

28
libethereum/VMFactory.h

@ -0,0 +1,28 @@
#pragma once
#include <libevm/VMFace.h>
namespace dev
{
namespace eth
{
/**
*/
class VMFactory
{
public:
enum Kind: bool {
Interpreter,
#if ETH_EVMJIT
JIT
#endif
};
static std::unique_ptr<VMFace> create(Kind, u256 _gas = 0);
};
}
}

6
libevm/FeeStructure.cpp

@ -34,9 +34,13 @@ u256 const dev::eth::c_sstoreResetGas = 100;
u256 const dev::eth::c_sstoreRefundGas = 100;
u256 const dev::eth::c_createGas = 100;
u256 const dev::eth::c_callGas = 20;
u256 const dev::eth::c_expGas = 1;
u256 const dev::eth::c_expByteGas = 1;
u256 const dev::eth::c_memoryGas = 1;
u256 const dev::eth::c_txDataGas = 5;
u256 const dev::eth::c_txDataZeroGas = 1;
u256 const dev::eth::c_txDataNonZeroGas = 5;
u256 const dev::eth::c_txGas = 500;
u256 const dev::eth::c_logGas = 32;
u256 const dev::eth::c_logDataGas = 1;
u256 const dev::eth::c_logTopicGas = 32;
u256 const dev::eth::c_copyGas = 1;

6
libevm/FeeStructure.h

@ -37,12 +37,16 @@ extern u256 const c_sstoreResetGas; ///< Once per SSTORE operation if the zeron
extern u256 const c_sstoreRefundGas; ///< Refunded gas, once per SSTORE operation if the zeroness changes to zero.
extern u256 const c_createGas; ///< Once per CREATE operation & contract-creation transaction.
extern u256 const c_callGas; ///< Once per CALL operation & message call transaction.
extern u256 const c_expGas; ///< Once per EXP instuction.
extern u256 const c_expByteGas; ///< Times ceil(log256(exponent)) for the EXP instruction.
extern u256 const c_memoryGas; ///< Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
extern u256 const c_txDataGas; ///< Per byte of data attached to a transaction. NOTE: Not payable on data of calls between transactions.
extern u256 const c_txDataZeroGas; ///< Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions.
extern u256 const c_txDataNonZeroGas; ///< Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions.
extern u256 const c_txGas; ///< Per transaction. NOTE: Not payable on data of calls between transactions.
extern u256 const c_logGas; ///< Per LOG* operation.
extern u256 const c_logDataGas; ///< Per byte in a LOG* operation's data.
extern u256 const c_logTopicGas; ///< Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas.
extern u256 const c_copyGas; ///< Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
}
}

17
libevm/VM.h

@ -36,6 +36,8 @@ namespace dev
namespace eth
{
class VMFactory;
/**
*/
class VM : public VMFace
@ -53,7 +55,7 @@ public:
u256s const& stack() const { return m_stack; }
private:
friend VMFace;
friend VMFactory;
explicit VM(u256 _gas = 0): VMFace(_gas) {}
template <class Ext>
@ -108,6 +110,7 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
// FEES...
bigint runGas = c_stepGas;
bigint newTempSize = m_temp.size();
bigint copySize = 0;
auto onOperation = [&]()
{
@ -170,14 +173,17 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break;
case Instruction::CALLDATACOPY:
require(3);
copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break;
case Instruction::CODECOPY:
require(3);
copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break;
case Instruction::EXTCODECOPY:
require(4);
copySize = m_stack[m_stack.size() - 4];
newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 4]);
break;
@ -215,6 +221,13 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
runGas = c_createGas;
break;
}
case Instruction::EXP:
{
require(2);
auto expon = m_stack[m_stack.size() - 2];
runGas = c_expGas + c_expByteGas * (32 - (h256(expon).firstBitSet() / 8));
break;
}
case Instruction::PC:
case Instruction::MSIZE:
@ -281,7 +294,6 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
case Instruction::SDIV:
case Instruction::MOD:
case Instruction::SMOD:
case Instruction::EXP:
case Instruction::LT:
case Instruction::GT:
case Instruction::SLT:
@ -342,6 +354,7 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
newTempSize = (newTempSize + 31) / 32 * 32;
if (newTempSize > m_temp.size())
runGas += c_memoryGas * (newTempSize - m_temp.size()) / 32;
runGas += c_copyGas * (copySize + 31) / 32;
onOperation();
// if (_onOp)

12
libevm/VMFace.cpp

@ -22,15 +22,7 @@
using namespace dev;
using namespace dev::eth;
std::unique_ptr<VMFace> VMFace::create(VMFace::Kind _kind, u256 _gas)
void VMFace::reset(u256 _gas) noexcept
{
std::unique_ptr<VMFace> vm;
#if ETH_EVMJIT
vm.reset(_kind == Kind::JIT ? static_cast<VMFace*>(new jit::VM) : new VM);
#else
(void) _kind; // suppress unused var warning
vm.reset(new VM);
#endif
vm->reset(_gas);
return vm;
m_gas = _gas;
}

6
libevm/VMFace.h

@ -62,16 +62,12 @@ public:
VMFace(VMFace const&) = delete;
void operator=(VMFace const&) = delete;
virtual void reset(u256 _gas = 0) noexcept { m_gas = _gas; }
virtual void reset(u256 _gas = 0) noexcept;
virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) = 0;
u256 gas() const { return m_gas; }
enum Kind: bool { Interpreter, JIT };
static std::unique_ptr<VMFace> create(Kind, u256 _gas = 0);
protected:
u256 m_gas = 0;
};

3
libevmjit/Compiler.cpp

@ -805,6 +805,9 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode
auto numBytes = stack.pop();
_memory.require(beginIdx, numBytes);
// This will commit the current cost block
_gasMeter.countLogData(numBytes);
std::array<llvm::Value*,4> topics;
auto numTopics = static_cast<size_t>(inst) - static_cast<size_t>(Instruction::LOG0);
for (size_t i = 0; i < numTopics; ++i)

8
libevmjit/Ext.cpp

@ -167,8 +167,8 @@ llvm::Value* Ext::codesizeAt(llvm::Value* _addr)
void Ext::log(llvm::Value* _memIdx, llvm::Value* _numBytes, size_t _numTopics, std::array<llvm::Value*,4> const& _topics)
{
static llvm::Value* args[] = {nullptr, m_args[0], m_args[1], m_arg2, m_arg3, m_arg4, m_arg5};
static llvm::Value* funcs[] = {m_log0, m_log1, m_log2, m_log3, m_log4};
llvm::Value* args[] = {nullptr, m_args[0], m_args[1], m_arg2, m_arg3, m_arg4, m_arg5};
llvm::Value* funcs[] = {m_log0, m_log1, m_log2, m_log3, m_log4};
args[0] = getRuntimeManager().getRuntimePtr();
m_builder.CreateStore(_memIdx, m_args[0]);
@ -320,8 +320,8 @@ extern "C"
{
auto&& ext = _rt->getExt();
auto memIdx = static_cast<size_t>(llvm2eth(*_memIdx));
auto numBytes = static_cast<size_t>(llvm2eth(*_numBytes));
auto memIdx = llvm2eth(*_memIdx).convert_to<size_t>();
auto numBytes = llvm2eth(*_numBytes).convert_to<size_t>();
auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes);
ext.log({}, dataRef);

18
libevmjit/GasMeter.cpp

@ -47,6 +47,16 @@ uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure
case Instruction::CREATE:
return static_cast<uint64_t>(c_createGas);
case Instruction::LOG0:
case Instruction::LOG1:
case Instruction::LOG2:
case Instruction::LOG3:
case Instruction::LOG4:
{
auto numTopics = static_cast<uint64_t>(inst) - static_cast<uint64_t>(Instruction::LOG0);
return static_cast<uint64_t>(c_logGas) + numTopics * static_cast<uint64_t>(c_logTopicGas);
}
default: // Assumes instruction code is valid
return static_cast<uint64_t>(c_stepGas);
}
@ -138,6 +148,14 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu
createCall(m_gasCheckFunc, cost);
}
void GasMeter::countLogData(llvm::Value* _dataLength)
{
assert(m_checkCall);
assert(m_blockCost > 0); // LOGn instruction is already counted
auto cost = m_builder.CreateMul(_dataLength, Constant::get(c_logDataGas), "logdata_cost");
commitCostBlock(cost);
}
void GasMeter::giveBack(llvm::Value* _gas)
{
m_runtimeManager.setGas(m_builder.CreateAdd(m_runtimeManager.getGas(), _gas));

3
libevmjit/GasMeter.h

@ -24,6 +24,9 @@ public:
/// Calculate & count gas cost for SSTORE instruction
void countSStore(class Ext& _ext, llvm::Value* _index, llvm::Value* _newValue);
/// Count gas cost of LOG data
void countLogData(llvm::Value* _dataLength);
/// Finalize cost-block by checking gas needed for the block before the block
/// @param _additionalCost adds additional cost to cost-block before commit
void commitCostBlock(llvm::Value* _additionalCost = nullptr);

1
libevmjit/VM.cpp

@ -2,6 +2,7 @@
#include "VM.h"
#include <libevm/VMFace.h>
#include <libevm/VM.h>
#include "ExecutionEngine.h"
#include "Compiler.h"

8
libevmjit/VM.h

@ -9,6 +9,9 @@ namespace dev
{
namespace eth
{
class VMFactory;
namespace jit
{
@ -16,8 +19,11 @@ class VM: public VMFace
{
virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final;
enum Kind: bool { Interpreter, JIT };
static std::unique_ptr<VMFace> create(Kind, u256 _gas = 0);
private:
friend VMFace;
friend VMFactory;
explicit VM(u256 _gas = 0): VMFace(_gas) {}
bytes m_output;

2
libsolidity/ExpressionCompiler.cpp

@ -363,7 +363,7 @@ void ExpressionCompiler::endVisit(Identifier& _identifier)
m_context << m_context.getFunctionEntryLabel(*functionDef).pushTag();
return;
}
if (VariableDeclaration* varDef = dynamic_cast<VariableDeclaration*>(declaration))
if (/*VariableDeclaration* varDef = */dynamic_cast<VariableDeclaration*>(declaration))
{
m_currentLValue.fromIdentifier(_identifier, *_identifier.getReferencedDeclaration());
m_currentLValue.retrieveValueIfLValueNotRequested(_identifier);

2
libsolidity/GlobalContext.cpp

@ -58,7 +58,7 @@ GlobalContext::GlobalContext():
FunctionType::Location::ECRECOVER)),
make_shared<MagicVariableDeclaration>("ripemd160",
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
TypePointers({std::make_shared<IntegerType>(160, IntegerType::Modifier::HASH)}),
FunctionType::Location::RIPEMD160))}
{
}

2
libsolidity/Types.cpp

@ -397,11 +397,11 @@ MagicType::MagicType(MagicType::Kind _kind):
break;
case Kind::MSG:
m_members = MemberList({{"sender", make_shared<IntegerType const>(0, IntegerType::Modifier::ADDRESS)},
{"gas", make_shared<IntegerType const>(256)},
{"value", make_shared<IntegerType const>(256)}});
break;
case Kind::TX:
m_members = MemberList({{"origin", make_shared<IntegerType const>(0, IntegerType::Modifier::ADDRESS)},
{"gas", make_shared<IntegerType const>(256)},
{"gasprice", make_shared<IntegerType const>(256)}});
break;
default:

1
libweb3jsonrpc/WebThreeStubServer.cpp

@ -51,7 +51,6 @@ static Json::Value toJson(dev::eth::BlockInfo const& _bi)
res["transactionsRoot"] = toJS(_bi.transactionsRoot);
res["difficulty"] = toJS(_bi.difficulty);
res["number"] = (int)_bi.number;
res["minGasPrice"] = toJS(_bi.minGasPrice);
res["gasLimit"] = (int)_bi.gasLimit;
res["timestamp"] = (int)_bi.timestamp;
res["extraData"] = jsFromBinary(_bi.extraData);

6
libwhisper/WhisperHost.cpp

@ -156,6 +156,12 @@ void WhisperHost::uninstallWatch(unsigned _i)
m_filters.erase(fit);
}
void WhisperHost::doWork()
{
for (auto& i: peers())
i->cap<WhisperPeer>()->sendMessages();
}
void WhisperHost::cleanup()
{
// remove old messages.

9
libwhisper/WhisperHost.h

@ -27,6 +27,7 @@
#include <memory>
#include <utility>
#include <libdevcore/RLP.h>
#include <libdevcore/Worker.h>
#include <libdevcore/Guards.h>
#include <libdevcrypto/SHA3.h>
#include "Common.h"
@ -38,7 +39,7 @@ namespace dev
namespace shh
{
class WhisperHost: public HostCapability<WhisperPeer>, public Interface
class WhisperHost: public HostCapability<WhisperPeer>, public Interface, public Worker
{
friend class WhisperPeer;
@ -64,7 +65,13 @@ public:
void cleanup();
protected:
void doWork();
private:
virtual void onStarting() { startWorking(); }
virtual void onStopping() { stopWorking(); }
void streamMessage(h256 _m, RLPStream& _s) const;
void noteChanged(h256 _messageHash, h256 _filter);

14
libwhisper/WhisperPeer.cpp

@ -72,7 +72,6 @@ bool WhisperPeer::interpret(unsigned _id, RLP const& _r)
for (auto i: _r)
if (n++)
host()->inject(Envelope(i), this);
sendMessages();
break;
}
default:
@ -97,10 +96,15 @@ void WhisperPeer::sendMessages()
}
}
if (!n)
// pause for a bit if no messages to send - this is horrible and broken.
// the message subsystem should really just keep pumping out messages while m_unseen.size() and there's bandwidth for them.
this_thread::sleep_for(chrono::milliseconds(20));
// the message subsystem should really just keep pumping out messages while m_unseen.size() and there's bandwidth for them.
auto diff = chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now() - m_timer);
if (n || diff.count() > 0)
{
RLPStream s;
prep(s, MessagesPacket, n).appendRaw(amalg.out(), n);
sealAndSend(s);
m_timer = chrono::system_clock::now();
}
{
RLPStream s;

2
libwhisper/WhisperPeer.h

@ -68,6 +68,8 @@ private:
mutable dev::Mutex x_unseen;
std::map<unsigned, h256> m_unseen; ///< Rated according to what they want.
std::chrono::system_clock::time_point m_timer = std::chrono::system_clock::now();
};
}

18
neth/main.cpp

@ -603,7 +603,7 @@ int main(int argc, char** argv)
vector<string> l;
l.push_back("Amount");
stringstream label;
label << "Gas price (" << info.minGasPrice << ")";
label << "Gas price";
l.push_back(label.str());
l.push_back("Gas");
vector<string> b;
@ -646,14 +646,12 @@ int main(int argc, char** argv)
ssbd << bbd;
cnote << ssbd.str();
int ssize = fields[4].length();
u256 minGas = (u256)Client::txGas(data.size(), 0);
u256 minGas = (u256)Client::txGas(data, 0);
if (size < 40)
{
if (size > 0)
cwarn << "Invalid address length:" << size;
}
else if (gasPrice < info.minGasPrice)
cwarn << "Minimum gas price is" << info.minGasPrice;
else if (gas < minGas)
cwarn << "Minimum gas amount is" << minGas;
else if (ssize < 40)
@ -702,9 +700,9 @@ int main(int argc, char** argv)
auto h = bc.currentHash();
auto blockData = bc.block(h);
BlockInfo info(blockData);
u256 minGas = (u256)Client::txGas(0, 0);
u256 minGas = (u256)Client::txGas(bytes(), 0);
Address dest = h160(fromHex(fields[0]));
c.transact(us.secret(), amount, dest, bytes(), minGas, info.minGasPrice);
c.transact(us.secret(), amount, dest, bytes(), minGas);
}
}
}
@ -718,7 +716,7 @@ int main(int argc, char** argv)
vector<string> l;
l.push_back("Endowment");
stringstream label;
label << "Gas price (" << info.minGasPrice << ")";
label << "Gas price";
l.push_back(label.str());
l.push_back("Gas");
vector<string> b;
@ -763,16 +761,14 @@ int main(int argc, char** argv)
cnote << "Init:";
cnote << ssc.str();
}
u256 minGas = (u256)Client::txGas(init.size(), 0);
u256 minGas = (u256)Client::txGas(init, 0);
if (endowment < 0)
cwarn << "Invalid endowment";
else if (gasPrice < info.minGasPrice)
cwarn << "Minimum gas price is" << info.minGasPrice;
else if (gas < minGas)
cwarn << "Minimum gas amount is" << minGas;
else
{
c.transact(us.secret(), endowment, init, gas, gasPrice);
c.transact(us.secret(), endowment, init, gas);
}
}
}

3
test/createRandomTest.cpp

@ -31,6 +31,7 @@
#include <json_spirit/json_spirit_writer_template.h>
#include <libdevcore/CommonIO.h>
#include <libdevcore/CommonData.h>
#include <libethereum/VMFactory.h>
#include <libevmcore/Instruction.h>
#include <libevm/VM.h>
#include "vm.h"
@ -128,7 +129,7 @@ void doMyTests(json_spirit::mValue& v)
assert(o.count("exec") > 0);
auto vmObj = eth::VMFace::create(eth::VMFace::Interpreter);
auto vmObj = eth::VMFactory::create(eth::VMFactory::Interpreter);
auto& vm = *vmObj;
test::FakeExtVM fev;
fev.importEnv(o["env"].get_obj());

10
test/vm.cpp

@ -22,6 +22,7 @@
#include <chrono>
#include <boost/filesystem.hpp>
#include <libethereum/VMFactory.h>
#include "vm.h"
using namespace std;
using namespace json_spirit;
@ -322,8 +323,11 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
auto useJit = false;
for (auto i = 0; i < argc && !useJit; ++i)
useJit |= std::string(argv[i]) == "--jit";
auto vmKind = useJit ? VMFace::JIT : VMFace::Interpreter;
#if ETH_EVMJIT
auto vmKind = useJit ? VMFactory::JIT : VMFactory::Interpreter;
#else
auto vmKind == VMFactory::Interpreter;
#endif
dev::test::FakeExtVM fev;
fev.importEnv(o["env"].get_obj());
@ -339,7 +343,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
fev.code = fev.thisTxCode;
}
auto vm = VMFace::create(vmKind, fev.gas);
auto vm = VMFactory::create(vmKind, fev.gas);
bytes output;
auto startTime = std::chrono::high_resolution_clock::now();

Loading…
Cancel
Save