Browse Source

Merge remote-tracking branch 'ethereum/develop' into sol_contractCompiler

Conflicts:
	libsolidity/AST.cpp
	libsolidity/AST.h
	libsolidity/Compiler.cpp
	libsolidity/Compiler.h
	libsolidity/NameAndTypeResolver.h
	libsolidity/Types.cpp
	solc/main.cpp
	test/solidityCompiler.cpp
cl-refactor
Christian 10 years ago
parent
commit
d1c20619c2
  1. 2
      libdevcore/Exceptions.h
  2. 6
      libethereum/Account.cpp
  3. 190
      libethereum/Account.h
  4. 94
      libethereum/AddressState.h
  5. 2
      libethereum/All.h
  6. 6
      libethereum/BlockChain.cpp
  7. 4
      libethereum/BlockChain.h
  8. 2
      libethereum/Executive.cpp
  9. 2
      libethereum/ExtVM.h
  10. 32
      libethereum/State.cpp
  11. 20
      libethereum/State.h
  12. 24
      libevm/VM.h
  13. 8
      libevmface/Instruction.cpp
  14. 19
      libevmface/Instruction.h
  15. 2
      liblll/Assembly.cpp
  16. 14
      liblll/CodeFragment.cpp
  17. 215
      libserpent/opcodes.h
  18. 150
      libsolidity/AST.h
  19. 6
      libsolidity/ASTPrinter.h
  20. 14
      libsolidity/ASTVisitor.h
  21. 6
      libsolidity/BaseTypes.h
  22. 2
      libsolidity/Compiler.cpp
  23. 12
      libsolidity/ExpressionCompiler.cpp
  24. 23
      libsolidity/NameAndTypeResolver.h
  25. 4
      libsolidity/Scanner.h
  26. 6
      libsolidity/Scope.h
  27. 16
      libsolidity/Types.cpp
  28. 40
      libsolidity/Types.h
  29. 4
      test/solidityCompiler.cpp
  30. 12
      test/solidityExpressionCompiler.cpp
  31. 2
      test/solidityNameAndTypeResolution.cpp
  32. 2
      test/solidityParser.cpp
  33. 2
      test/vm.cpp
  34. 12
      test/vmArithmeticTestFiller.json
  35. 336
      test/vmBitwiseLogicOperationTestFiller.json
  36. 4
      windows/LibEthereum.vcxproj
  37. 12
      windows/LibEthereum.vcxproj.filters

2
libdevcore/Exceptions.h

@ -44,6 +44,6 @@ struct FileError: virtual Exception {};
// error information to be added to exceptions
typedef boost::error_info<struct tag_invalidSymbol, char> errinfo_invalidSymbol;
typedef boost::error_info<struct tag_comment, std::string> errinfo_wrongAddress;
typedef boost::error_info<struct tag_address, std::string> errinfo_wrongAddress;
typedef boost::error_info<struct tag_comment, std::string> errinfo_comment;
}

6
libethereum/AddressState.cpp → libethereum/Account.cpp

@ -14,17 +14,17 @@
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AddressState.cpp
/** @file Account.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "AddressState.h"
#include "Account.h"
#include <libethcore/CommonEth.h>
using namespace std;
using namespace dev;
using namespace dev::eth;
#pragma GCC diagnostic ignored "-Wunused-variable"
namespace { char dummy; };
const h256 Account::c_contractConceptionCodeHash;

190
libethereum/Account.h

@ -0,0 +1,190 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Account.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#include <libdevcore/Common.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/TrieDB.h>
#include <libdevcrypto/SHA3.h>
namespace dev
{
namespace eth
{
/**
* Models the state of a single Ethereum account.
* Used to cache a portion of the full Ethereum state. State keeps a mapping of Address's to Accounts.
*
* Aside from storing the nonce and balance, the account may also be "dead" (where isAlive() returns false).
* This allows State to explicitly store the notion of a deleted account in it's cache. kill() can be used
* for this.
*
* For the account's storage, the class operates a cache. baseRoot() specifies the base state of the storage
* given as the Trie root to be looked up in the state database. Alterations beyond this base are specified
* in the overlay, stored in this class and retrieved with storageOverlay(). setStorage allows the overlay
* to be altered.
*
* The code handling explicitly supports a two-stage commit model needed for contract-creation. When creating
* a contract (running the initialisation code), the code of the account is considered empty. The attribute
* of emptiness can be retrieved with codeBearing(). After initialisation one must set the code accordingly;
* the code of the Account can be set with setCode(). To validate a setCode() call, this class records the
* state of being in contract-creation (and thus in a state where setCode may validly be called). It can be
* determined through isFreshCode().
*
* The code can be retrieved through code(), and its hash through codeHash(). codeHash() is only valid when
* the account is not in the contract-creation phase (i.e. when isFreshCode() returns false). This class
* supports populating code on-demand from the state database. To determine if the code has been prepopulated
* call codeCacheValid(). To populate the code, look it up with codeHash() and populate with noteCode().
*
* @todo: need to make a noteCodeCommitted().
*
* The constructor allows you to create an one of a number of "types" of accounts. The default constructor
* makes a dead account (this is ignored by State when writing out the Trie). Another three allow a basic
* or contract account to be specified along with an initial balance. The fina two allow either a basic or
* a contract account to be created with arbitrary values.
*/
class Account
{
public:
/// Type of account to create.
enum NewAccountType
{
/// Normal account.
NormalCreation,
/// Contract account - we place this object into the contract-creation state (and as such we
/// expect setCode(), but codeHash() won't work).
ContractConception
};
/// Construct a dead Account.
Account() {}
/// Construct an alive Account, with given endowment, for either a normal (non-contract) account or for a
/// contract account in the
/// conception phase, where the code is not yet known.
Account(u256 _balance, NewAccountType _t): m_isAlive(true), m_balance(_balance), m_codeHash(_t == NormalCreation ? c_contractConceptionCodeHash : EmptySHA3) {}
/// Explicit constructor for wierd cases of construction of a normal account.
Account(u256 _nonce, u256 _balance): m_isAlive(true), m_nonce(_nonce), m_balance(_balance) {}
/// Explicit constructor for wierd cases of construction or a contract account.
Account(u256 _nonce, u256 _balance, h256 _contractRoot, h256 _codeHash): m_isAlive(true), m_nonce(_nonce), m_balance(_balance), m_storageRoot(_contractRoot), m_codeHash(_codeHash) { assert(_contractRoot); }
/// Kill this account. Useful for the suicide opcode. Following this call, isAlive() returns false.
void kill() { m_isAlive = false; m_storageOverlay.clear(); m_codeHash = EmptySHA3; m_storageRoot = EmptyTrie; m_balance = 0; m_nonce = 0; }
/// @returns true iff this object represents an account in the state. Returns false if this object
/// represents an account that should no longer exist in the trie (an account that never existed or was
/// suicided).
bool isAlive() const { return m_isAlive; }
/// @returns the balance of this account. Can be altered in place.
u256& balance() { return m_balance; }
/// @returns the balance of this account.
u256 const& balance() const { return m_balance; }
/// Increments the balance of this account by the given amount. It's a bigint, so can be negative.
void addBalance(bigint _i) { m_balance = (u256)((bigint)m_balance + _i); }
/// @returns the nonce of the account. Can be altered in place.
u256& nonce() { return m_nonce; }
/// @returns the nonce of the account.
u256 const& nonce() const { return m_nonce; }
/// Increment the nonce of the account by one.
void incNonce() { m_nonce++; }
/// @returns the root of the trie (whose nodes are stored in the state db externally to this class)
/// which encodes the base-state of the account's storage (upon which the storage is overlaid).
h256 baseRoot() const { assert(m_storageRoot); return m_storageRoot; }
/// @returns the storage overlay as a simple map.
std::map<u256, u256> const& storageOverlay() const { return m_storageOverlay; }
/// Set a key/value pair in the account's storage. This actually goes into the overlay, for committing
/// to the trie later.
void setStorage(u256 _p, u256 _v) { m_storageOverlay[_p] = _v; }
/// @returns true if we are in the contract-conception state and setCode is valid to call.
bool isFreshCode() const { return m_codeHash == c_contractConceptionCodeHash; }
/// @returns true if we are either in the contract-conception state or if the account's code is not
/// empty.
bool codeBearing() const { return m_codeHash != EmptySHA3; }
/// @returns the hash of the account's code. Must only be called when isFreshCode() returns false.
h256 codeHash() const { assert(!isFreshCode()); return m_codeHash; }
/// Sets the code of the account. Must only be called when isFreshCode() returns true.
void setCode(bytesConstRef _code) { assert(isFreshCode()); m_codeCache = _code.toBytes(); }
/// @returns true if the account's code is available through code().
bool codeCacheValid() const { return m_codeHash == EmptySHA3 || m_codeHash == c_contractConceptionCodeHash || m_codeCache.size(); }
/// Specify to the object what the actual code is for the account. @a _code must have a SHA3 equal to
/// codeHash() and must only be called when isFreshCode() returns false.
void noteCode(bytesConstRef _code) { assert(sha3(_code) == m_codeHash); m_codeCache = _code.toBytes(); }
/// @returns the account's code. Must only be called when codeCacheValid returns true.
bytes const& code() const { assert(codeCacheValid()); return m_codeCache; }
private:
/// Is this account existant? If not, it represents a deleted account.
bool m_isAlive = false;
/// Account's nonce.
u256 m_nonce = 0;
/// Account's balance.
u256 m_balance = 0;
/// The base storage root. Used with the state DB to give a base to the storage. m_storageOverlay is
/// overlaid on this and takes precedence for all values set.
h256 m_storageRoot = EmptyTrie;
/** If c_contractConceptionCodeHash then we're in the limbo where we're running the initialisation code.
* We expect a setCode() at some point later.
* If EmptySHA3, then m_code, which should be empty, is valid.
* If anything else, then m_code is valid iff it's not empty, otherwise, State::ensureCached() needs to
* be called with the correct args.
*/
h256 m_codeHash = EmptySHA3;
/// The map with is overlaid onto whatever storage is implied by the m_storageRoot in the trie.
std::map<u256, u256> m_storageOverlay;
/// The associated code for this account. The SHA3 of this should be equal to m_codeHash unless m_codeHash
/// equals c_contractConceptionCodeHash.
bytes m_codeCache;
/// Value for m_codeHash when this account is having its code determined.
static const h256 c_contractConceptionCodeHash;
};
}
}

94
libethereum/AddressState.h

@ -1,94 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AddressState.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#include <libdevcore/Common.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/TrieDB.h>
#include <libdevcrypto/SHA3.h>
namespace dev
{
namespace eth
{
// TODO: Document fully.
class AddressState
{
public:
enum NewAccountType { NormalCreation, ContractConception };
/// Construct a dead AddressState.
AddressState() {}
/// Construct an alive AddressState, with given endowment, for either a normal (non-contract) account or for a contract account in the
/// conception phase, where the code is not yet known.
AddressState(u256 _balance, NewAccountType _t): m_isAlive(true), m_balance(_balance), m_codeHash(_t == NormalCreation ? h256() : EmptySHA3) {}
/// Explicit constructor for wierd cases of construction of a normal account.
AddressState(u256 _nonce, u256 _balance): m_isAlive(true), m_nonce(_nonce), m_balance(_balance) {}
/// Explicit constructor for wierd cases of construction or a contract account.
AddressState(u256 _nonce, u256 _balance, h256 _contractRoot, h256 _codeHash): m_isAlive(true), m_nonce(_nonce), m_balance(_balance), m_storageRoot(_contractRoot), m_codeHash(_codeHash) {}
void kill() { m_isAlive = false; m_storageOverlay.clear(); m_codeHash = EmptySHA3; m_storageRoot = EmptyTrie; m_balance = 0; m_nonce = 0; }
bool isAlive() const { return m_isAlive; }
u256& balance() { return m_balance; }
u256 const& balance() const { return m_balance; }
void addBalance(bigint _i) { m_balance = (u256)((bigint)m_balance + _i); }
u256& nonce() { return m_nonce; }
u256 const& nonce() const { return m_nonce; }
void incNonce() { m_nonce++; }
h256 baseRoot() const { return m_storageRoot; }
std::map<u256, u256> const& storage() const { return m_storageOverlay; }
void setStorage(u256 _p, u256 _v) { m_storageOverlay[_p] = _v; }
bool isFreshCode() const { return !m_codeHash; }
bool codeBearing() const { return m_codeHash != EmptySHA3; }
bool codeCacheValid() const { return m_codeHash == EmptySHA3 || !m_codeHash || m_codeCache.size(); }
h256 codeHash() const { assert(m_codeHash); return m_codeHash; }
bytes const& code() const { assert(m_codeHash == EmptySHA3 || !m_codeHash || m_codeCache.size()); return m_codeCache; }
void setCode(bytesConstRef _code) { assert(!m_codeHash); m_codeCache = _code.toBytes(); }
void noteCode(bytesConstRef _code) { assert(sha3(_code) == m_codeHash); m_codeCache = _code.toBytes(); }
private:
bool m_isAlive = false;
u256 m_nonce = 0;
u256 m_balance = 0;
/// The base storage root. Used with the state DB to give a base to the storage. m_storageOverlay is overlaid on this and takes precedence for all values set.
h256 m_storageRoot = EmptyTrie;
/// If 0 then we're in the limbo where we're running the initialisation code. We expect a setCode() at some point later.
/// If EmptySHA3, then m_code, which should be empty, is valid.
/// If anything else, then m_code is valid iff it's not empty, otherwise, State::ensureCached() needs to be called with the correct args.
h256 m_codeHash = EmptySHA3;
// TODO: change to unordered_map.
std::map<u256, u256> m_storageOverlay;
bytes m_codeCache;
};
}
}

2
libethereum/All.h

@ -1,6 +1,6 @@
#pragma once
#include "AddressState.h"
#include "Account.h"
#include "BlockChain.h"
#include "Client.h"
#include "Defaults.h"

6
libethereum/BlockChain.cpp

@ -52,9 +52,9 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, BlockChain const& _bc)
return _out;
}
std::map<Address, AddressState> const& dev::eth::genesisState()
std::map<Address, Account> const& dev::eth::genesisState()
{
static std::map<Address, AddressState> s_ret;
static std::map<Address, Account> s_ret;
if (s_ret.empty())
// Initialise.
for (auto i: vector<string>({
@ -67,7 +67,7 @@ std::map<Address, AddressState> const& dev::eth::genesisState()
"6c386a4b26f73c802f34673f7248bb118f97424a",
"e4157b34ea9615cfbde6b4fda419828124b70c78"
}))
s_ret[Address(fromHex(i))] = AddressState(u256(1) << 200, AddressState::NormalCreation);
s_ret[Address(fromHex(i))] = Account(u256(1) << 200, Account::NormalCreation);
return s_ret;
}

4
libethereum/BlockChain.h

@ -33,7 +33,7 @@
#include <libethcore/BlockInfo.h>
#include <libdevcore/Guards.h>
#include "BlockDetails.h"
#include "AddressState.h"
#include "Account.h"
#include "BlockQueue.h"
namespace ldb = leveldb;
@ -57,7 +57,7 @@ struct BlockChainChat: public LogChannel { static const char* name() { return "-
struct BlockChainNote: public LogChannel { static const char* name() { return "=B="; } static const int verbosity = 4; };
// TODO: Move all this Genesis stuff into Genesis.h/.cpp
std::map<Address, AddressState> const& genesisState();
std::map<Address, Account> const& genesisState();
ldb::Slice toSlice(h256 _h, unsigned _sub = 0);

2
libethereum/Executive.cpp

@ -138,7 +138,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g
m_newAddress = right160(sha3(rlpList(_sender, m_s.transactionsFrom(_sender) - 1)));
// Set up new account...
m_s.m_cache[m_newAddress] = AddressState(0, m_s.balance(m_newAddress) + _endowment, h256(), h256());
m_s.m_cache[m_newAddress] = Account(m_s.balance(m_newAddress) + _endowment, Account::ContractConception);
// Execute _init.
m_vm = new VM(_gas);

2
libethereum/ExtVM.h

@ -102,7 +102,7 @@ public:
private:
State& m_s; ///< A reference to the base state.
std::map<Address, AddressState> m_origCache; ///< The cache of the address states (i.e. the externalities) as-was prior to the execution.
std::map<Address, Account> m_origCache; ///< The cache of the address states (i.e. the externalities) as-was prior to the execution.
Manifest* m_ms;
};

32
libethereum/State.cpp

@ -224,7 +224,7 @@ Address State::nextActiveAddress(Address _a) const
// TODO: repot
struct CachedAddressState
{
CachedAddressState(std::string const& _rlp, AddressState const* _s, OverlayDB const* _o): rS(_rlp), r(rS), s(_s), o(_o) {}
CachedAddressState(std::string const& _rlp, Account const* _s, OverlayDB const* _o): rS(_rlp), r(rS), s(_s), o(_o) {}
bool exists() const
{
@ -259,7 +259,7 @@ struct CachedAddressState
ret[j.first] = RLP(j.second).toInt<u256>();
}
if (s)
for (auto const& j: s->storage())
for (auto const& j: s->storageOverlay())
if ((!ret.count(j.first) && j.second) || (ret.count(j.first) && ret.at(j.first) != j.second))
ret[j.first] = j.second;
return ret;
@ -300,7 +300,7 @@ struct CachedAddressState
std::string rS;
RLP r;
AddressState const* s;
Account const* s;
OverlayDB const* o;
};
@ -346,7 +346,7 @@ void State::ensureCached(Address _a, bool _requireCode, bool _forceCreate) const
ensureCached(m_cache, _a, _requireCode, _forceCreate);
}
void State::ensureCached(std::map<Address, AddressState>& _cache, Address _a, bool _requireCode, bool _forceCreate) const
void State::ensureCached(std::map<Address, Account>& _cache, Address _a, bool _requireCode, bool _forceCreate) const
{
auto it = _cache.find(_a);
if (it == _cache.end())
@ -356,11 +356,11 @@ void State::ensureCached(std::map<Address, AddressState>& _cache, Address _a, bo
if (stateBack.empty() && !_forceCreate)
return;
RLP state(stateBack);
AddressState s;
Account s;
if (state.isNull())
s = AddressState(0, AddressState::NormalCreation);
s = Account(0, Account::NormalCreation);
else
s = AddressState(state[0].toInt<u256>(), state[1].toInt<u256>(), state[2].toHash<h256>(), state[3].toHash<h256>());
s = Account(state[0].toInt<u256>(), state[1].toInt<u256>(), state[2].toHash<h256>(), state[3].toHash<h256>());
bool ok;
tie(it, ok) = _cache.insert(make_pair(_a, s));
}
@ -965,7 +965,7 @@ void State::noteSending(Address _id)
{
cwarn << "Sending from non-existant account. How did it pay!?!";
// this is impossible. but we'll continue regardless...
m_cache[_id] = AddressState(1, 0);
m_cache[_id] = Account(1, 0);
}
else
it->second.incNonce();
@ -976,7 +976,7 @@ void State::addBalance(Address _id, u256 _amount)
ensureCached(_id, false, false);
auto it = m_cache.find(_id);
if (it == m_cache.end())
m_cache[_id] = AddressState(_amount, AddressState::NormalCreation);
m_cache[_id] = Account(_amount, Account::NormalCreation);
else
it->second.addBalance(_amount);
}
@ -1011,8 +1011,8 @@ u256 State::storage(Address _id, u256 _memory) const
return 0;
// See if it's in the account's storage cache.
auto mit = it->second.storage().find(_memory);
if (mit != it->second.storage().end())
auto mit = it->second.storageOverlay().find(_memory);
if (mit != it->second.storageOverlay().end())
return mit->second;
// Not in the storage cache - go to the DB.
@ -1040,7 +1040,7 @@ map<u256, u256> State::storage(Address _id) const
}
// Then merge cached storage over the top.
for (auto const& i: it->second.storage())
for (auto const& i: it->second.storageOverlay())
if (i.second)
ret[i.first] = i.second;
else
@ -1057,7 +1057,7 @@ h256 State::storageRoot(Address _id) const
RLP r(s);
return r[2].toHash<h256>();
}
return h256();
return EmptyTrie;
}
bytes const& State::code(Address _contract) const
@ -1267,7 +1267,7 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas,
Address newAddress = right160(sha3(rlpList(_sender, transactionsFrom(_sender) - 1)));
// Set up new account...
m_cache[newAddress] = AddressState(balance(newAddress) + _endowment, AddressState::ContractConception);
m_cache[newAddress] = Account(balance(newAddress) + _endowment, Account::ContractConception);
// Execute init code.
VM vm(*_gas);
@ -1366,7 +1366,7 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, State const& _s)
for (auto i: d)
{
auto it = _s.m_cache.find(i);
AddressState* cache = it != _s.m_cache.end() ? &it->second : nullptr;
Account* cache = it != _s.m_cache.end() ? &it->second : nullptr;
string rlpString = dtr.count(i) ? trie.at(i) : "";
RLP r(rlpString);
assert(cache || r);
@ -1394,7 +1394,7 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, State const& _s)
mem[j.first] = RLP(j.second).toInt<u256>(), back.insert(j.first);
}
if (cache)
for (auto const& j: cache->storage())
for (auto const& j: cache->storageOverlay())
{
if ((!mem.count(j.first) && j.second) || (mem.count(j.first) && mem.at(j.first) != j.second))
mem[j.first] = j.second, delta.insert(j.first);

20
libethereum/State.h

@ -33,7 +33,7 @@
#include <libevm/FeeStructure.h>
#include <libevm/ExtVMFace.h>
#include "TransactionQueue.h"
#include "AddressState.h"
#include "Account.h"
#include "Transaction.h"
#include "Executive.h"
#include "AccountDiff.h"
@ -129,8 +129,10 @@ public:
/// @returns the set containing all addresses currently in use in Ethereum.
std::map<Address, u256> addresses() const;
/// @returns the address b such that b > @a _a .
Address nextActiveAddress(Address _a) const;
/// Get the header information on the present block.
BlockInfo const& info() const { return m_currentBlock; }
/// @brief Checks that mining the current object will result in a valid block.
@ -299,7 +301,7 @@ private:
void ensureCached(Address _a, bool _requireCode, bool _forceCreate) const;
/// Retrieve all information about a given address into a cache.
void ensureCached(std::map<Address, AddressState>& _cache, Address _a, bool _requireCode, bool _forceCreate) const;
void ensureCached(std::map<Address, Account>& _cache, Address _a, bool _requireCode, bool _forceCreate) const;
/// Commit all changes waiting in the address cache to the DB.
void commit();
@ -340,18 +342,18 @@ private:
std::set<h256> m_transactionSet; ///< The set of transaction hashes that we've included in the state.
OverlayDB m_lastTx;
mutable std::map<Address, AddressState> m_cache; ///< Our address cache. This stores the states of each address that has (or at least might have) been changed.
mutable std::map<Address, Account> m_cache; ///< Our address cache. This stores the states of each address that has (or at least might have) been changed.
BlockInfo m_previousBlock; ///< The previous block's information.
BlockInfo m_currentBlock; ///< The current block's information.
bytes m_currentBytes; ///< The current block.
bytes m_currentTxs;
bytes m_currentUncles;
bytes m_currentTxs; ///< The RLP-encoded block of transactions.
bytes m_currentUncles; ///< The RLP-encoded block of uncles.
Address m_ourAddress; ///< Our address (i.e. the address to which fees go).
ProofOfWork m_pow;
ProofOfWork m_pow; ///< The PoW mining class.
u256 m_blockReward;
@ -365,7 +367,7 @@ private:
std::ostream& operator<<(std::ostream& _out, State const& _s);
template <class DB>
void commit(std::map<Address, AddressState> const& _cache, DB& _db, TrieDB<Address, DB>& _state)
void commit(std::map<Address, Account> const& _cache, DB& _db, TrieDB<Address, DB>& _state)
{
for (auto const& i: _cache)
if (!i.second.isAlive())
@ -375,7 +377,7 @@ void commit(std::map<Address, AddressState> const& _cache, DB& _db, TrieDB<Addre
RLPStream s(4);
s << i.second.nonce() << i.second.balance();
if (i.second.storage().empty())
if (i.second.storageOverlay().empty())
{
assert(i.second.baseRoot());
s.append(i.second.baseRoot());
@ -383,7 +385,7 @@ void commit(std::map<Address, AddressState> const& _cache, DB& _db, TrieDB<Addre
else
{
TrieDB<h256, DB> storageDB(&_db, i.second.baseRoot());
for (auto const& j: i.second.storage())
for (auto const& j: i.second.storageOverlay())
if (j.second)
storageDB.insert(j.first, rlp(j.second));
else

24
libevm/VM.h

@ -262,8 +262,8 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
case Instruction::PUSH31:
case Instruction::PUSH32:
break;
case Instruction::BNOT:
case Instruction::NOT:
case Instruction::ISZERO:
case Instruction::CALLDATALOAD:
case Instruction::EXTCODESIZE:
case Instruction::POP:
@ -395,7 +395,7 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
m_stack.back() = (u256)boost::multiprecision::powm((bigint)base, (bigint)expon, bigint(2) << 256);
break;
}
case Instruction::BNOT:
case Instruction::NOT:
m_stack.back() = ~m_stack.back();
break;
case Instruction::LT:
@ -418,7 +418,7 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
m_stack[m_stack.size() - 2] = m_stack.back() == m_stack[m_stack.size() - 2] ? 1 : 0;
m_stack.pop_back();
break;
case Instruction::NOT:
case Instruction::ISZERO:
m_stack.back() = m_stack.back() ? 0 : 1;
break;
case Instruction::AND:
@ -506,12 +506,12 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
{
unsigned mf = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned cf = (unsigned)m_stack.back();
u256 cf = m_stack.back();
m_stack.pop_back();
unsigned l = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned el = cf + l > _ext.data.size() ? _ext.data.size() < cf ? 0 : _ext.data.size() - cf : l;
memcpy(m_temp.data() + mf, _ext.data.data() + cf, el);
unsigned el = cf + l > (u256)_ext.data.size() ? (u256)_ext.data.size() < cf ? 0 : _ext.data.size() - (unsigned)cf : l;
memcpy(m_temp.data() + mf, _ext.data.data() + (unsigned)cf, el);
memset(m_temp.data() + mf + el, 0, l - el);
break;
}
@ -522,12 +522,12 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
{
unsigned mf = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned cf = (unsigned)m_stack.back();
u256 cf = (u256)m_stack.back();
m_stack.pop_back();
unsigned l = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned el = cf + l > _ext.code.size() ? _ext.code.size() < cf ? 0 : _ext.code.size() - cf : l;
memcpy(m_temp.data() + mf, _ext.code.data() + cf, el);
unsigned el = cf + l > (u256)_ext.code.size() ? (u256)_ext.code.size() < cf ? 0 : _ext.code.size() - (unsigned)cf : l;
memcpy(m_temp.data() + mf, _ext.code.data() + (unsigned)cf, el);
memset(m_temp.data() + mf + el, 0, l - el);
break;
}
@ -540,12 +540,12 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
m_stack.pop_back();
unsigned mf = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned cf = (unsigned)m_stack.back();
u256 cf = m_stack.back();
m_stack.pop_back();
unsigned l = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned el = cf + l > _ext.codeAt(a).size() ? _ext.codeAt(a).size() < cf ? 0 : _ext.codeAt(a).size() - cf : l;
memcpy(m_temp.data() + mf, _ext.codeAt(a).data() + cf, el);
unsigned el = cf + l > (u256)_ext.codeAt(a).size() ? (u256)_ext.codeAt(a).size() < cf ? 0 : _ext.codeAt(a).size() - (unsigned)cf : l;
memcpy(m_temp.data() + mf, _ext.codeAt(a).data() + (unsigned)cf, el);
memset(m_temp.data() + mf + el, 0, l - el);
break;
}

8
libevmface/Instruction.cpp

@ -39,13 +39,13 @@ const std::map<std::string, Instruction> dev::eth::c_instructions =
{ "MOD", Instruction::MOD },
{ "SMOD", Instruction::SMOD },
{ "EXP", Instruction::EXP },
{ "BNOT", Instruction::BNOT },
{ "BNOT", Instruction::NOT },
{ "LT", Instruction::LT },
{ "GT", Instruction::GT },
{ "SLT", Instruction::SLT },
{ "SGT", Instruction::SGT },
{ "EQ", Instruction::EQ },
{ "NOT", Instruction::NOT },
{ "NOT", Instruction::ISZERO },
{ "AND", Instruction::AND },
{ "OR", Instruction::OR },
{ "XOR", Instruction::XOR },
@ -172,13 +172,13 @@ static const std::map<Instruction, InstructionInfo> c_instructionInfo =
{ Instruction::MOD, { "MOD", 0, 2, 1 } },
{ Instruction::SMOD, { "SMOD", 0, 2, 1 } },
{ Instruction::EXP, { "EXP", 0, 2, 1 } },
{ Instruction::BNOT, { "BNOT", 0, 1, 1 } },
{ Instruction::NOT, { "BNOT", 0, 1, 1 } },
{ Instruction::LT, { "LT", 0, 2, 1 } },
{ Instruction::GT, { "GT", 0, 2, 1 } },
{ Instruction::SLT, { "SLT", 0, 2, 1 } },
{ Instruction::SGT, { "SGT", 0, 2, 1 } },
{ Instruction::EQ, { "EQ", 0, 2, 1 } },
{ Instruction::NOT, { "NOT", 0, 1, 1 } },
{ Instruction::ISZERO, { "NOT", 0, 1, 1 } },
{ Instruction::AND, { "AND", 0, 2, 1 } },
{ Instruction::OR, { "OR", 0, 2, 1 } },
{ Instruction::XOR, { "XOR", 0, 2, 1 } },

19
libevmface/Instruction.h

@ -43,22 +43,23 @@ enum class Instruction: uint8_t
SDIV, ///< signed integer division operation
MOD, ///< modulo remainder operation
SMOD, ///< signed modulo remainder operation
ADDMOD, ///< unsigned modular addition
MULMOD, ///< unsigned modular multiplication
EXP, ///< exponential operation
BNOT, ///< bitwise not
LT, ///< less-than comparision
SIGNEXTEND, ///< extend length of signed integer
LT = 0x10, ///< less-than comparision
GT, ///< greater-than comparision
SLT, ///< signed less-than comparision
SGT, ///< signed greater-than comparision
EQ, ///< equality comparision
NOT, ///< simple not operator
AND = 0x10, ///< bitwise AND operation
ISZERO, ///< simple not operator
AND, ///< bitwise AND operation
OR, ///< bitwise OR operation
XOR, ///< bitwise XOR operation
NOT, ///< bitwise NOT opertation
BYTE, ///< retrieve single byte from word
ADDMOD, ///< unsigned modular addition
MULMOD, ///< unsigned modular multiplication
SIGNEXTEND, ///< extend length of signed integer
SHA3 = 0x20, ///< compute SHA3-256 hash
ADDRESS = 0x30, ///< get address of currently executing account
@ -83,7 +84,7 @@ enum class Instruction: uint8_t
GASLIMIT, ///< get the block's gas limit
POP = 0x50, ///< remove item from stack
MLOAD = 0x53, ///< load word from memory
MLOAD, ///< load word from memory
MSTORE, ///< save word to memory
MSTORE8, ///< save byte to memory
SLOAD, ///< load word from storage

2
liblll/Assembly.cpp

@ -251,7 +251,7 @@ Assembly& Assembly::optimise(bool _enable)
{ { PushSub, Instruction::POP }, [](AssemblyItemsConstRef) -> AssemblyItems { return {}; } },
{ { PushSubSize, Instruction::POP }, [](AssemblyItemsConstRef) -> AssemblyItems { return {}; } },
{ { Push, PushTag, Instruction::JUMPI }, [](AssemblyItemsConstRef m) -> AssemblyItems { if (m[0].data()) return { m[1], Instruction::JUMP }; else return {}; } },
{ { Instruction::NOT, Instruction::NOT }, [](AssemblyItemsConstRef) -> AssemblyItems { return {}; } },
{ { Instruction::ISZERO, Instruction::ISZERO }, [](AssemblyItemsConstRef) -> AssemblyItems { return {}; } },
};
for (auto const& i: c_simple)

14
liblll/CodeFragment.cpp

@ -328,7 +328,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
std::map<std::string, Instruction> const c_arith = { { "+", Instruction::ADD }, { "-", Instruction::SUB }, { "*", Instruction::MUL }, { "/", Instruction::DIV }, { "%", Instruction::MOD }, { "&", Instruction::AND }, { "|", Instruction::OR }, { "^", Instruction::XOR } };
std::map<std::string, pair<Instruction, bool>> const c_binary = { { "<", { Instruction::LT, false } }, { "<=", { Instruction::GT, true } }, { ">", { Instruction::GT, false } }, { ">=", { Instruction::LT, true } }, { "S<", { Instruction::SLT, false } }, { "S<=", { Instruction::SGT, true } }, { "S>", { Instruction::SGT, false } }, { "S>=", { Instruction::SLT, true } }, { "=", { Instruction::EQ, false } }, { "!=", { Instruction::EQ, true } } };
std::map<std::string, Instruction> const c_unary = { { "!", Instruction::NOT } };
std::map<std::string, Instruction> const c_unary = { { "!", Instruction::ISZERO } };
vector<CodeFragment> code;
CompilerState ns = _s;
@ -403,7 +403,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
m_asm.append(code[0].m_asm, 1);
m_asm.append(it->second.first);
if (it->second.second)
m_asm.append(Instruction::NOT);
m_asm.append(Instruction::ISZERO);
}
else if (c_unary.count(us))
{
@ -437,7 +437,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
m_asm.append(code[0].m_asm);
if (us == "WHEN")
m_asm.append(Instruction::NOT);
m_asm.append(Instruction::ISZERO);
auto end = m_asm.appendJumpI();
m_asm.onePath();
m_asm.otherPath();
@ -452,7 +452,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
auto begin = m_asm.append();
m_asm.append(code[0].m_asm);
m_asm.append(Instruction::NOT);
m_asm.append(Instruction::ISZERO);
auto end = m_asm.appendJumpI();
m_asm.append(code[1].m_asm, 0);
m_asm.appendJump(begin);
@ -466,7 +466,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
m_asm.append(code[0].m_asm, 0);
auto begin = m_asm.append();
m_asm.append(code[1].m_asm);
m_asm.append(Instruction::NOT);
m_asm.append(Instruction::ISZERO);
auto end = m_asm.appendJumpI();
m_asm.append(code[3].m_asm, 0);
m_asm.append(code[2].m_asm, 0);
@ -502,7 +502,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
requireDeposit(2, 1);
m_asm.append(code[2].m_asm, 1);
m_asm.append(Instruction::LT);
m_asm.append(Instruction::NOT);
m_asm.append(Instruction::ISZERO);
m_asm.append(Instruction::MUL);
m_asm.append(Instruction::DUP1);
}
@ -525,7 +525,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
// Check if true - predicate
m_asm.append(code[i - 1].m_asm, 1);
if (us == "&&")
m_asm.append(Instruction::NOT);
m_asm.append(Instruction::ISZERO);
m_asm.appendJumpI(end);
}
m_asm.append(Instruction::POP);

215
libserpent/opcodes.h

@ -1,3 +1,20 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ETHSERP_OPCODES
#define ETHSERP_OPCODES
@ -7,122 +24,128 @@
#include <map>
class Mapping {
public:
Mapping(std::string Op, int Opcode, int In, int Out) {
op = Op;
opcode = Opcode;
in = In;
out = Out;
}
std::string op;
int opcode;
int in;
int out;
public:
Mapping(std::string Op, int Opcode, int In, int Out) {
op = Op;
opcode = Opcode;
in = In;
out = Out;
}
std::string op;
int opcode;
int in;
int out;
};
Mapping mapping[] = {
Mapping("STOP", 0x00, 0, 0),
Mapping("ADD", 0x01, 2, 1),
Mapping("MUL", 0x02, 2, 1),
Mapping("SUB", 0x03, 2, 1),
Mapping("DIV", 0x04, 2, 1),
Mapping("SDIV", 0x05, 2, 1),
Mapping("MOD", 0x06, 2, 1),
Mapping("SMOD", 0x07, 2, 1),
Mapping("EXP", 0x08, 2, 1),
Mapping("NEG", 0x09, 1, 1),
Mapping("LT", 0x0a, 2, 1),
Mapping("GT", 0x0b, 2, 1),
Mapping("SLT", 0x0c, 2, 1),
Mapping("SGT", 0x0d, 2, 1),
Mapping("EQ", 0x0e, 2, 1),
Mapping("NOT", 0x0f, 1, 1),
Mapping("AND", 0x10, 2, 1),
Mapping("OR", 0x11, 2, 1),
Mapping("XOR", 0x12, 2, 1),
Mapping("BYTE", 0x13, 2, 1),
Mapping("ADDMOD", 0x14, 3, 1),
Mapping("MULMOD", 0x15, 3, 1),
Mapping("SHA3", 0x20, 2, 1),
Mapping("ADDRESS", 0x30, 0, 1),
Mapping("BALANCE", 0x31, 1, 1),
Mapping("ORIGIN", 0x32, 0, 1),
Mapping("CALLER", 0x33, 0, 1),
Mapping("CALLVALUE", 0x34, 0, 1),
Mapping("CALLDATALOAD", 0x35, 1, 1),
Mapping("CALLDATASIZE", 0x36, 0, 1),
Mapping("CALLDATACOPY", 0x37, 3, 1),
Mapping("CODESIZE", 0x38, 0, 1),
Mapping("CODECOPY", 0x39, 3, 1),
Mapping("GASPRICE", 0x3a, 0, 1),
Mapping("PREVHASH", 0x40, 0, 1),
Mapping("COINBASE", 0x41, 0, 1),
Mapping("TIMESTAMP", 0x42, 0, 1),
Mapping("NUMBER", 0x43, 0, 1),
Mapping("DIFFICULTY", 0x44, 0, 1),
Mapping("GASLIMIT", 0x45, 0, 1),
Mapping("POP", 0x50, 1, 0),
Mapping("MLOAD", 0x53, 1, 1),
Mapping("MSTORE", 0x54, 2, 0),
Mapping("MSTORE8", 0x55, 2, 0),
Mapping("SLOAD", 0x56, 1, 1),
Mapping("SSTORE", 0x57, 2, 0),
Mapping("JUMP", 0x58, 1, 0),
Mapping("JUMPI", 0x59, 2, 0),
Mapping("PC", 0x5a, 0, 1),
Mapping("MSIZE", 0x5b, 0, 1),
Mapping("GAS", 0x5c, 0, 1),
Mapping("JUMPDEST", 0x5d, 0, 0),
Mapping("CREATE", 0xf0, 3, 1),
Mapping("CALL", 0xf1, 7, 1),
Mapping("RETURN", 0xf2, 2, 0),
Mapping("CALL_CODE", 0xf3, 7, 1),
Mapping("SUICIDE", 0xff, 1, 0),
Mapping("---END---", 0x00, 0, 0),
Mapping("STOP", 0x00, 0, 0),
Mapping("ADD", 0x01, 2, 1),
Mapping("MUL", 0x02, 2, 1),
Mapping("SUB", 0x03, 2, 1),
Mapping("DIV", 0x04, 2, 1),
Mapping("SDIV", 0x05, 2, 1),
Mapping("MOD", 0x06, 2, 1),
Mapping("SMOD", 0x07, 2, 1),
Mapping("EXP", 0x08, 2, 1),
Mapping("NEG", 0x09, 1, 1),
Mapping("LT", 0x0a, 2, 1),
Mapping("GT", 0x0b, 2, 1),
Mapping("SLT", 0x0c, 2, 1),
Mapping("SGT", 0x0d, 2, 1),
Mapping("EQ", 0x0e, 2, 1),
Mapping("NOT", 0x0f, 1, 1),
Mapping("AND", 0x10, 2, 1),
Mapping("OR", 0x11, 2, 1),
Mapping("XOR", 0x12, 2, 1),
Mapping("BYTE", 0x13, 2, 1),
Mapping("ADDMOD", 0x14, 3, 1),
Mapping("MULMOD", 0x15, 3, 1),
Mapping("SIGNEXTEND", 0x16, 2, 1),
Mapping("SHA3", 0x20, 2, 1),
Mapping("ADDRESS", 0x30, 0, 1),
Mapping("BALANCE", 0x31, 1, 1),
Mapping("ORIGIN", 0x32, 0, 1),
Mapping("CALLER", 0x33, 0, 1),
Mapping("CALLVALUE", 0x34, 0, 1),
Mapping("CALLDATALOAD", 0x35, 1, 1),
Mapping("CALLDATASIZE", 0x36, 0, 1),
Mapping("CALLDATACOPY", 0x37, 3, 1),
Mapping("CODESIZE", 0x38, 0, 1),
Mapping("CODECOPY", 0x39, 3, 1),
Mapping("GASPRICE", 0x3a, 0, 1),
Mapping("PREVHASH", 0x40, 0, 1),
Mapping("COINBASE", 0x41, 0, 1),
Mapping("TIMESTAMP", 0x42, 0, 1),
Mapping("NUMBER", 0x43, 0, 1),
Mapping("DIFFICULTY", 0x44, 0, 1),
Mapping("GASLIMIT", 0x45, 0, 1),
Mapping("POP", 0x50, 1, 0),
Mapping("MLOAD", 0x53, 1, 1),
Mapping("MSTORE", 0x54, 2, 0),
Mapping("MSTORE8", 0x55, 2, 0),
Mapping("SLOAD", 0x56, 1, 1),
Mapping("SSTORE", 0x57, 2, 0),
Mapping("JUMP", 0x58, 1, 0),
Mapping("JUMPI", 0x59, 2, 0),
Mapping("PC", 0x5a, 0, 1),
Mapping("MSIZE", 0x5b, 0, 1),
Mapping("GAS", 0x5c, 0, 1),
Mapping("JUMPDEST", 0x5d, 0, 0),
Mapping("CREATE", 0xf0, 3, 1),
Mapping("CALL", 0xf1, 7, 1),
Mapping("RETURN", 0xf2, 2, 0),
Mapping("CALL_CODE", 0xf3, 7, 1),
Mapping("SUICIDE", 0xff, 1, 0),
Mapping("---END---", 0x00, 0, 0),
};
std::map<std::string, std::vector<int> > opcodes;
std::map<int, std::string> reverseOpcodes;
// Fetches everything EXCEPT PUSH1..32
std::pair<std::string, std::vector<int> > _opdata(std::string ops, int opi) {
if (!opcodes.size()) {
int i = 0;
while (mapping[i].op != "---END---") {
Mapping mi = mapping[i];
opcodes[mi.op] = triple(mi.opcode, mi.in, mi.out);
i++;
}
for (i = 1; i <= 16; i++) {
opcodes["DUP"+unsignedToDecimal(i)] = triple(0x7f + i, i, i+1);
opcodes["SWAP"+unsignedToDecimal(i)] = triple(0x8f + i, i+1, i+1);
}
for (std::map<std::string, std::vector<int> >::iterator it=opcodes.begin();
it != opcodes.end();
it++) {
reverseOpcodes[(*it).second[0]] = (*it).first;
}
}
std::string op;
std::vector<int> opdata;
op = reverseOpcodes.count(opi) ? reverseOpcodes[opi] : "";
opdata = opcodes.count(ops) ? opcodes[ops] : triple(-1, -1, -1);
return std::pair<std::string, std::vector<int> >(op, opdata);
std::pair<std::string, std::vector<int> > _opdata(std::string ops, int opi)
{
if (!opcodes.size())
{
int i = 0;
while (mapping[i].op != "---END---")
{
Mapping mi = mapping[i];
opcodes[mi.op] = triple(mi.opcode, mi.in, mi.out);
i++;
}
for (i = 1; i <= 16; i++)
{
opcodes["DUP"+unsignedToDecimal(i)] = triple(0x7f + i, i, i+1);
opcodes["SWAP"+unsignedToDecimal(i)] = triple(0x8f + i, i+1, i+1);
}
for (std::map<std::string, std::vector<int> >::iterator it=opcodes.begin(); it != opcodes.end(); it++)
reverseOpcodes[(*it).second[0]] = (*it).first;
}
std::string op;
std::vector<int> opdata;
op = reverseOpcodes.count(opi) ? reverseOpcodes[opi] : "";
opdata = opcodes.count(ops) ? opcodes[ops] : triple(-1, -1, -1);
return std::pair<std::string, std::vector<int> >(op, opdata);
}
int opcode(std::string op) {
int opcode(std::string op)
{
return _opdata(op, -1).second[0];
}
int opinputs(std::string op) {
int opinputs(std::string op)
{
return _opdata(op, -1).second[1];
}
int opoutputs(std::string op) {
int opoutputs(std::string op)
{
return _opdata(op, -1).second[2];
}
std::string op(int opcode) {
std::string op(int opcode)
{
return _opdata("", opcode).first;
}

150
libsolidity/AST.h

@ -41,9 +41,11 @@ namespace solidity
class ASTVisitor;
/// The root (abstract) class of the AST inheritance tree.
/// It is possible to traverse all direct and indirect children of an AST node by calling
/// accept, providing an ASTVisitor.
/**
* The root (abstract) class of the AST inheritance tree.
* It is possible to traverse all direct and indirect children of an AST node by calling
* accept, providing an ASTVisitor.
*/
class ASTNode: private boost::noncopyable
{
public:
@ -77,7 +79,9 @@ private:
Location m_location;
};
/// Abstract AST class for a declaration (contract, function, struct, variable).
/**
* Abstract AST class for a declaration (contract, function, struct, variable).
*/
class Declaration: public ASTNode
{
public:
@ -85,15 +89,17 @@ public:
ASTNode(_location), m_name(_name) {}
/// Returns the declared name.
const ASTString& getName() const { return *m_name; }
ASTString const& getName() const { return *m_name; }
private:
ASTPointer<ASTString> m_name;
};
/// Definition of a contract. This is the only AST nodes where child nodes are not visited in
/// document order. It first visits all struct declarations, then all variable declarations and
/// finally all function declarations.
/**
* Definition of a contract. This is the only AST nodes where child nodes are not visited in
* document order. It first visits all struct declarations, then all variable declarations and
* finally all function declarations.
*/
class ContractDefinition: public Declaration
{
public:
@ -133,9 +139,11 @@ private:
std::vector<ASTPointer<VariableDeclaration>> m_members;
};
/// Parameter list, used as function parameter list and return list.
/// None of the parameters is allowed to contain mappings (not even recursively
/// inside structs), but (@todo) this is not yet enforced.
/**
* Parameter list, used as function parameter list and return list.
* None of the parameters is allowed to contain mappings (not even recursively
* inside structs), but (@todo) this is not yet enforced.
*/
class ParameterList: public ASTNode
{
public:
@ -183,8 +191,10 @@ private:
std::vector<VariableDeclaration const*> m_localVariables;
};
/// Declaration of a variable. This can be used in various places, e.g. in function parameter
/// lists, struct definitions and even function bodys.
/**
* Declaration of a variable. This can be used in various places, e.g. in function parameter
* lists, struct definitions and even function bodys.
*/
class VariableDeclaration: public Declaration
{
public:
@ -196,8 +206,8 @@ public:
bool isTypeGivenExplicitly() const { return bool(m_typeName); }
TypeName* getTypeName() const { return m_typeName.get(); }
//! Returns the declared or inferred type. Can be an empty pointer if no type was explicitly
//! declared and there is no assignment to the variable that fixes the type.
/// Returns the declared or inferred type. Can be an empty pointer if no type was explicitly
/// declared and there is no assignment to the variable that fixes the type.
std::shared_ptr<Type const> const& getType() const { return m_type; }
void setType(std::shared_ptr<Type const> const& _type) { m_type = _type; }
@ -210,7 +220,9 @@ private:
/// Types
/// @{
/// Abstract base class of a type name, can be any built-in or user-defined type.
/**
* Abstract base class of a type name, can be any built-in or user-defined type.
*/
class TypeName: public ASTNode
{
public:
@ -222,8 +234,10 @@ public:
virtual std::shared_ptr<Type> toType() = 0;
};
/// Any pre-defined type name represented by a single keyword, i.e. it excludes mappings,
/// contracts, functions, etc.
/**
* Any pre-defined type name represented by a single keyword, i.e. it excludes mappings,
* contracts, functions, etc.
*/
class ElementaryTypeName: public TypeName
{
public:
@ -238,8 +252,10 @@ private:
Token::Value m_type;
};
/// Name referring to a user-defined type (i.e. a struct).
/// @todo some changes are necessary if this is also used to refer to contract types later
/**
* Name referring to a user-defined type (i.e. a struct).
* @todo some changes are necessary if this is also used to refer to contract types later
*/
class UserDefinedTypeName: public TypeName
{
public:
@ -248,7 +264,7 @@ public:
virtual void accept(ASTVisitor& _visitor) override;
virtual std::shared_ptr<Type> toType() override { return Type::fromUserDefinedTypeName(*this); }
const ASTString& getName() const { return *m_name; }
ASTString const& getName() const { return *m_name; }
void setReferencedStruct(StructDefinition& _referencedStruct) { m_referencedStruct = &_referencedStruct; }
StructDefinition const* getReferencedStruct() const { return m_referencedStruct; }
@ -258,7 +274,9 @@ private:
StructDefinition* m_referencedStruct;
};
/// A mapping type. Its source form is "mapping('keyType' => 'valueType')"
/**
* A mapping type. Its source form is "mapping('keyType' => 'valueType')"
*/
class Mapping: public TypeName
{
public:
@ -279,20 +297,24 @@ private:
/// @{
/// Abstract base class for statements.
/**
* Abstract base class for statements.
*/
class Statement: public ASTNode
{
public:
explicit Statement(Location const& _location): ASTNode(_location) {}
virtual void accept(ASTVisitor& _visitor) override;
//! Check all type requirements, throws exception if some requirement is not met.
//! This includes checking that operators are applicable to their arguments but also that
//! the number of function call arguments matches the number of formal parameters and so forth.
/// Check all type requirements, throws exception if some requirement is not met.
/// This includes checking that operators are applicable to their arguments but also that
/// the number of function call arguments matches the number of formal parameters and so forth.
virtual void checkTypeRequirements() = 0;
};
/// Brace-enclosed block containing zero or more statements.
/**
* Brace-enclosed block containing zero or more statements.
*/
class Block: public Statement
{
public:
@ -306,8 +328,10 @@ private:
std::vector<ASTPointer<Statement>> m_statements;
};
/// If-statement with an optional "else" part. Note that "else if" is modeled by having a new
/// if-statement as the false (else) body.
/**
* If-statement with an optional "else" part. Note that "else if" is modeled by having a new
* if-statement as the false (else) body.
*/
class IfStatement: public Statement
{
public:
@ -324,11 +348,13 @@ public:
private:
ASTPointer<Expression> m_condition;
ASTPointer<Statement> m_trueBody;
ASTPointer<Statement> m_falseBody; //< "else" part, optional
ASTPointer<Statement> m_falseBody; ///< "else" part, optional
};
/// Statement in which a break statement is legal.
/// @todo actually check this requirement.
/**
* Statement in which a break statement is legal.
* @todo actually check this requirement.
*/
class BreakableStatement: public Statement
{
public:
@ -381,15 +407,17 @@ public:
Expression* getExpression() const { return m_expression.get(); }
private:
ASTPointer<Expression> m_expression; //< value to return, optional
ASTPointer<Expression> m_expression; ///< value to return, optional
/// Pointer to the parameter list of the function, filled by the @ref NameAndTypeResolver.
ParameterList* m_returnParameters;
};
/// Definition of a variable as a statement inside a function. It requires a type name (which can
/// also be "var") but the actual assignment can be missing.
/// Examples: var a = 2; uint256 a;
/**
* Definition of a variable as a statement inside a function. It requires a type name (which can
* also be "var") but the actual assignment can be missing.
* Examples: var a = 2; uint256 a;
*/
class VariableDefinition: public Statement
{
public:
@ -477,8 +505,10 @@ private:
ASTPointer<Expression> m_rightHandSide;
};
/// Operation involving a unary operator, pre- or postfix.
/// Examples: ++i, delete x or !true
/**
* Operation involving a unary operator, pre- or postfix.
* Examples: ++i, delete x or !true
*/
class UnaryOperation: public Expression
{
public:
@ -498,8 +528,10 @@ private:
bool m_isPrefix;
};
/// Operation involving a binary operator.
/// Examples: 1 + 2, true && false or 1 <= 4
/**
* Operation involving a binary operator.
* Examples: 1 + 2, true && false or 1 <= 4
*/
class BinaryOperation: public Expression
{
public:
@ -521,7 +553,9 @@ private:
std::shared_ptr<Type const> m_commonType;
};
/// Can be ordinary function call, type cast or struct construction.
/**
* Can be ordinary function call, type cast or struct construction.
*/
class FunctionCall: public Expression
{
public:
@ -543,7 +577,9 @@ private:
std::vector<ASTPointer<Expression>> m_arguments;
};
/// Access to a member of an object. Example: x.name
/**
* Access to a member of an object. Example: x.name
*/
class MemberAccess: public Expression
{
public:
@ -551,7 +587,7 @@ public:
ASTPointer<ASTString> const& _memberName):
Expression(_location), m_expression(_expression), m_memberName(_memberName) {}
virtual void accept(ASTVisitor& _visitor) override;
const ASTString& getMemberName() const { return *m_memberName; }
ASTString const& getMemberName() const { return *m_memberName; }
virtual void checkTypeRequirements() override;
private:
@ -559,7 +595,9 @@ private:
ASTPointer<ASTString> m_memberName;
};
/// Index access to an array. Example: a[2]
/**
* Index access to an array. Example: a[2]
*/
class IndexAccess: public Expression
{
public:
@ -574,15 +612,19 @@ private:
ASTPointer<Expression> m_index;
};
/// Primary expression, i.e. an expression that do not be divided any further like a literal or
/// a variable reference.
/**
* Primary expression, i.e. an expression that cannot be divided any further. Examples are literals
* or variable references.
*/
class PrimaryExpression: public Expression
{
public:
PrimaryExpression(Location const& _location): Expression(_location) {}
};
/// An identifier, i.e. a reference to a declaration by name like a variable or function.
/**
* An identifier, i.e. a reference to a declaration by name like a variable or function.
*/
class Identifier: public PrimaryExpression
{
public:
@ -599,13 +641,15 @@ public:
private:
ASTPointer<ASTString> m_name;
//! Declaration the name refers to.
/// Declaration the name refers to.
Declaration* m_referencedDeclaration;
};
/// An elementary type name expression is used in expressions like "a = uint32(2)" to change the
/// type of an expression explicitly. Here, "uint32" is the elementary type name expression and
/// "uint32(2)" is a @ref FunctionCall.
/**
* An elementary type name expression is used in expressions like "a = uint32(2)" to change the
* type of an expression explicitly. Here, "uint32" is the elementary type name expression and
* "uint32(2)" is a @ref FunctionCall.
*/
class ElementaryTypeNameExpression: public PrimaryExpression
{
public:
@ -620,7 +664,9 @@ private:
Token::Value m_typeToken;
};
/// A literal string or number. @see Type::literalToBigEndian is used to actually parse its value.
/**
* A literal string or number. @see Type::literalToBigEndian is used to actually parse its value.
*/
class Literal: public PrimaryExpression
{
public:

6
libsolidity/ASTPrinter.h

@ -30,13 +30,15 @@ namespace dev
namespace solidity
{
/// Pretty-printer for the abstract syntax tree (the "pretty" is arguable) for debugging purposes.
/**
* Pretty-printer for the abstract syntax tree (the "pretty" is arguable) for debugging purposes.
*/
class ASTPrinter: public ASTVisitor
{
public:
/// Create a printer for the given abstract syntax tree. If the source is specified,
/// the corresponding parts of the source are printed with each node.
ASTPrinter(ASTPointer<ASTNode> const& _ast, const std::string& _source = std::string());
ASTPrinter(ASTPointer<ASTNode> const& _ast, std::string const& _source = std::string());
/// Output the string representation of the AST to _stream.
void print(std::ostream& _stream);

14
libsolidity/ASTVisitor.h

@ -30,12 +30,14 @@ namespace dev
namespace solidity
{
/// Visitor interface for the abstract syntax tree. This class is tightly bound to the
/// implementation of @ref ASTNode::accept and its overrides. After a call to
/// @ref ASTNode::accept, the function visit for the appropriate parameter is called and then
/// (if it returns true) this continues recursively for all child nodes in document order
/// (there is an exception for contracts). After all child nodes have been visited, endVisit is
/// called for the node.
/**
* Visitor interface for the abstract syntax tree. This class is tightly bound to the
* implementation of @ref ASTNode::accept and its overrides. After a call to
* @ref ASTNode::accept, the function visit for the appropriate parameter is called and then
* (if it returns true) this continues recursively for all child nodes in document order
* (there is an exception for contracts). After all child nodes have been visited, endVisit is
* called for the node.
*/
class ASTVisitor
{
public:

6
libsolidity/BaseTypes.h

@ -29,8 +29,10 @@ namespace dev
namespace solidity
{
/// Representation of an interval of source positions.
/// The interval includes start and excludes end.
/**
* Representation of an interval of source positions.
* The interval includes start and excludes end.
*/
struct Location
{
Location(int _start, int _end): start(_start), end(_end) { }

2
libsolidity/Compiler.cpp

@ -243,7 +243,7 @@ bool Compiler::visit(WhileStatement& _whileStatement)
m_context << loopStart;
ExpressionCompiler::compileExpression(m_context, _whileStatement.getCondition());
m_context << eth::Instruction::NOT;
m_context << eth::Instruction::ISZERO;
m_context.appendConditionalJumpTo(loopEnd);
_whileStatement.getBody().accept(*this);

12
libsolidity/ExpressionCompiler.cpp

@ -71,10 +71,10 @@ void ExpressionCompiler::endVisit(UnaryOperation& _unaryOperation)
switch (_unaryOperation.getOperator())
{
case Token::NOT: // !
m_context << eth::Instruction::NOT;
m_context << eth::Instruction::ISZERO;
break;
case Token::BIT_NOT: // ~
m_context << eth::Instruction::BNOT;
m_context << eth::Instruction::NOT;
break;
case Token::DELETE: // delete
{
@ -262,7 +262,7 @@ void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation& _binaryOperati
_binaryOperation.getLeftExpression().accept(*this);
m_context << eth::Instruction::DUP1;
if (op == Token::AND)
m_context << eth::Instruction::NOT;
m_context << eth::Instruction::ISZERO;
eth::AssemblyItem endLabel = m_context.appendConditionalJump();
_binaryOperation.getRightExpression().accept(*this);
m_context << endLabel;
@ -274,7 +274,7 @@ void ExpressionCompiler::appendCompareOperatorCode(Token::Value _operator, Type
{
m_context << eth::Instruction::EQ;
if (_operator == Token::NE)
m_context << eth::Instruction::NOT;
m_context << eth::Instruction::ISZERO;
}
else
{
@ -288,11 +288,11 @@ void ExpressionCompiler::appendCompareOperatorCode(Token::Value _operator, Type
{
case Token::GTE:
m_context << (isSigned ? eth::Instruction::SGT : eth::Instruction::GT)
<< eth::Instruction::NOT;
<< eth::Instruction::ISZERO;
break;
case Token::LTE:
m_context << (isSigned ? eth::Instruction::SLT : eth::Instruction::LT)
<< eth::Instruction::NOT;
<< eth::Instruction::ISZERO;
break;
case Token::GT:
m_context << (isSigned ? eth::Instruction::SLT : eth::Instruction::LT);

23
libsolidity/NameAndTypeResolver.h

@ -33,8 +33,11 @@ namespace dev
namespace solidity
{
//! Resolves name references, resolves all types and checks that all operations are valid for the
//! inferred types. An exception is throw on the first error.
/**
* Resolves name references, types and checks types of all expressions.
* Specifically, it checks that all operations are valid for the inferred types.
* An exception is throw on the first error.
*/
class NameAndTypeResolver: private boost::noncopyable
{
public:
@ -54,15 +57,17 @@ public:
private:
void reset();
//! Maps nodes declaring a scope to scopes, i.e. ContractDefinition, FunctionDeclaration and
//! StructDefinition (@todo not yet implemented), where nullptr denotes the global scope.
/// Maps nodes declaring a scope to scopes, i.e. ContractDefinition, FunctionDeclaration and
/// StructDefinition (@todo not yet implemented), where nullptr denotes the global scope.
std::map<ASTNode const*, Scope> m_scopes;
Scope* m_currentScope;
};
//! Traverses the given AST upon construction and fills _scopes with all declarations inside the
//! AST.
/**
* Traverses the given AST upon construction and fills _scopes with all declarations inside the
* AST.
*/
class DeclarationRegistrationHelper: private ASTVisitor
{
public:
@ -87,8 +92,10 @@ private:
FunctionDefinition* m_currentFunction;
};
//! Resolves references to declarations (of variables and types) and also establishes the link
//! between a return statement and the return parameter list.
/**
* Resolves references to declarations (of variables and types) and also establishes the link
* between a return statement and the return parameter list.
*/
class ReferencesResolver: private ASTVisitor
{
public:

4
libsolidity/Scanner.h

@ -125,7 +125,7 @@ public:
/// Returns the current token
Token::Value getCurrentToken() { return m_current_token.token; }
Location getCurrentLocation() const { return m_current_token.location; }
const std::string& getCurrentLiteral() const { return m_current_token.literal; }
std::string const& getCurrentLiteral() const { return m_current_token.literal; }
///@}
///@{
@ -134,7 +134,7 @@ public:
/// Returns the next token without advancing input.
Token::Value peekNextToken() const { return m_next_token.token; }
Location peekLocation() const { return m_next_token.location; }
const std::string& peekLiteral() const { return m_next_token.literal; }
std::string const& peekLiteral() const { return m_next_token.literal; }
///@}
///@{

6
libsolidity/Scope.h

@ -32,8 +32,10 @@ namespace dev
namespace solidity
{
/// Container that stores mappings betwee names and declarations. It also contains a link to the
/// enclosing scope.
/**
* Container that stores mappings betwee names and declarations. It also contains a link to the
* enclosing scope.
*/
class Scope
{
public:

16
libsolidity/Types.cpp

@ -143,7 +143,7 @@ bool IntegerType::acceptsUnaryOperator(Token::Value _operator) const
_operator == Token::INC || _operator == Token::DEC;
}
bool IntegerType::operator==(const Type& _other) const
bool IntegerType::operator==(Type const& _other) const
{
if (_other.getCategory() != getCategory())
return false;
@ -159,7 +159,7 @@ std::string IntegerType::toString() const
return prefix + dev::toString(m_bits);
}
u256 IntegerType::literalValue(const Literal& _literal) const
u256 IntegerType::literalValue(Literal const& _literal) const
{
bigint value(_literal.getValue());
//@todo check that the number is not too large
@ -180,7 +180,7 @@ bool BoolType::isExplicitlyConvertibleTo(Type const& _convertTo) const
return isImplicitlyConvertibleTo(_convertTo);
}
u256 BoolType::literalValue(const Literal& _literal) const
u256 BoolType::literalValue(Literal const& _literal) const
{
if (_literal.getToken() == Token::TRUE_LITERAL)
return u256(1);
@ -190,7 +190,7 @@ u256 BoolType::literalValue(const Literal& _literal) const
assert(false);
}
bool ContractType::operator==(const Type& _other) const
bool ContractType::operator==(Type const& _other) const
{
if (_other.getCategory() != getCategory())
return false;
@ -198,7 +198,7 @@ bool ContractType::operator==(const Type& _other) const
return other.m_contract == m_contract;
}
bool StructType::operator==(const Type& _other) const
bool StructType::operator==(Type const& _other) const
{
if (_other.getCategory() != getCategory())
return false;
@ -206,7 +206,7 @@ bool StructType::operator==(const Type& _other) const
return other.m_struct == m_struct;
}
bool FunctionType::operator==(const Type& _other) const
bool FunctionType::operator==(Type const& _other) const
{
if (_other.getCategory() != getCategory())
return false;
@ -214,7 +214,7 @@ bool FunctionType::operator==(const Type& _other) const
return other.m_function == m_function;
}
bool MappingType::operator==(const Type& _other) const
bool MappingType::operator==(Type const& _other) const
{
if (_other.getCategory() != getCategory())
return false;
@ -222,7 +222,7 @@ bool MappingType::operator==(const Type& _other) const
return *other.m_keyType == *m_keyType && *other.m_valueType == *m_valueType;
}
bool TypeType::operator==(const Type& _other) const
bool TypeType::operator==(Type const& _other) const
{
if (_other.getCategory() != getCategory())
return false;

40
libsolidity/Types.h

@ -36,7 +36,9 @@ namespace solidity
// @todo realMxN, string<N>, mapping
/// Abstract base class that forms the root of the type hierarchy.
/**
* Abstract base class that forms the root of the type hierarchy.
*/
class Type: private boost::noncopyable
{
public:
@ -76,7 +78,9 @@ public:
virtual u256 literalValue(Literal const&) const { assert(false); }
};
/// Any kind of integer type including hash and address.
/**
* Any kind of integer type including hash and address.
*/
class IntegerType: public Type
{
public:
@ -112,7 +116,9 @@ private:
Modifier m_modifier;
};
/// The boolean type.
/**
* The boolean type.
*/
class BoolType: public Type
{
public:
@ -133,7 +139,9 @@ public:
virtual u256 literalValue(Literal const& _literal) const override;
};
/// The type of a contract instance, there is one distinct type for each contract definition.
/**
* The type of a contract instance, there is one distinct type for each contract definition.
*/
class ContractType: public Type
{
public:
@ -148,7 +156,9 @@ private:
ContractDefinition const& m_contract;
};
/// The type of a struct instance, there is one distinct type per struct definition.
/**
* The type of a struct instance, there is one distinct type per struct definition.
*/
class StructType: public Type
{
public:
@ -167,7 +177,9 @@ private:
StructDefinition const& m_struct;
};
/// The type of a function, there is one distinct type per function definition.
/**
* The type of a function, there is one distinct type per function definition.
*/
class FunctionType: public Type
{
public:
@ -184,7 +196,9 @@ private:
FunctionDefinition const& m_function;
};
/// The type of a mapping, there is one distinct type per key/value type pair.
/**
* The type of a mapping, there is one distinct type per key/value type pair.
*/
class MappingType: public Type
{
public:
@ -199,8 +213,10 @@ private:
std::shared_ptr<Type const> m_valueType;
};
/// The void type, can only be implicitly used as the type that is returned by functions without
/// return parameters.
/**
* The void type, can only be implicitly used as the type that is returned by functions without
* return parameters.
*/
class VoidType: public Type
{
public:
@ -210,8 +226,10 @@ public:
virtual std::string toString() const override { return "void"; }
};
/// The type of a type reference. The type of "uint32" when used in "a = uint32(2)" is an example
/// of a TypeType.
/**
* The type of a type reference. The type of "uint32" when used in "a = uint32(2)" is an example
* of a TypeType.
*/
class TypeType: public Type
{
public:

4
test/solidityCompiler.cpp

@ -163,7 +163,7 @@ BOOST_AUTO_TEST_CASE(ifStatement)
byte(Instruction::JUMPI),
// new check "else if" condition
byte(Instruction::DUP1),
byte(Instruction::NOT),
byte(Instruction::ISZERO),
byte(Instruction::PUSH1), 0x13 + shift,
byte(Instruction::JUMPI),
// "else" body
@ -201,7 +201,7 @@ BOOST_AUTO_TEST_CASE(loops)
bytes expectation({byte(Instruction::JUMPDEST),
byte(Instruction::JUMPDEST),
byte(Instruction::PUSH1), 0x1,
byte(Instruction::NOT),
byte(Instruction::ISZERO),
byte(Instruction::PUSH1), 0x21 + shift,
byte(Instruction::JUMPI),
byte(Instruction::PUSH1), 0x1,

12
test/solidityExpressionCompiler.cpp

@ -159,7 +159,7 @@ BOOST_AUTO_TEST_CASE(comparison)
byte(eth::Instruction::GT),
byte(eth::Instruction::PUSH1), 0x1,
byte(eth::Instruction::EQ),
byte(eth::Instruction::NOT)});
byte(eth::Instruction::ISZERO)});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -175,18 +175,18 @@ BOOST_AUTO_TEST_CASE(short_circuiting)
byte(eth::Instruction::ADD),
byte(eth::Instruction::PUSH1), 0x4,
byte(eth::Instruction::GT),
byte(eth::Instruction::NOT), // after this we have 10 + 8 >= 4
byte(eth::Instruction::ISZERO), // after this we have 10 + 8 >= 4
byte(eth::Instruction::DUP1),
byte(eth::Instruction::PUSH1), 0x14,
byte(eth::Instruction::JUMPI), // short-circuit if it is true
byte(eth::Instruction::PUSH1), 0x2,
byte(eth::Instruction::PUSH1), 0x9,
byte(eth::Instruction::EQ),
byte(eth::Instruction::NOT), // after this we have 2 != 9
byte(eth::Instruction::ISZERO), // after this we have 2 != 9
byte(eth::Instruction::JUMPDEST),
byte(eth::Instruction::PUSH1), 0x1,
byte(eth::Instruction::EQ),
byte(eth::Instruction::NOT)});
byte(eth::Instruction::ISZERO)});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -228,10 +228,10 @@ BOOST_AUTO_TEST_CASE(unary_operators)
bytes expectation({byte(eth::Instruction::PUSH1), 0x1,
byte(eth::Instruction::PUSH1), 0x0,
byte(eth::Instruction::SUB),
byte(eth::Instruction::BNOT),
byte(eth::Instruction::NOT),
byte(eth::Instruction::PUSH1), 0x2,
byte(eth::Instruction::EQ),
byte(eth::Instruction::NOT)});
byte(eth::Instruction::ISZERO)});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}

2
test/solidityNameAndTypeResolution.cpp

@ -38,7 +38,7 @@ namespace test
namespace
{
void parseTextAndResolveNames(const std::string& _source)
void parseTextAndResolveNames(std::string const& _source)
{
Parser parser;
ASTPointer<ContractDefinition> contract = parser.parse(

2
test/solidityParser.cpp

@ -37,7 +37,7 @@ namespace test
namespace
{
ASTPointer<ASTNode> parseText(const std::string& _source)
ASTPointer<ASTNode> parseText(std::string const& _source)
{
Parser parser;
return parser.parse(std::make_shared<Scanner>(CharStream(_source)));

2
test/vm.cpp

@ -471,7 +471,7 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end
}
// Set up new account...
m_cache[_newAddress] = AddressState(0, balance(_newAddress) + _endowment, h256(), h256());
m_cache[_newAddress] = Account(0, balance(_newAddress) + _endowment, h256(), h256());
// Execute init code.
VM vm(*_gas);

12
test/vmArithmeticTestFiller.json

@ -1319,7 +1319,7 @@
},
"neg0": {
"bnot0": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
@ -1347,7 +1347,7 @@
}
},
"neg1": {
"bnot1": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
@ -1375,7 +1375,7 @@
}
},
"neg2": {
"bnot2": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
@ -1403,7 +1403,7 @@
}
},
"neg3": {
"bnot3": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
@ -1431,7 +1431,7 @@
}
},
"neg4": {
"bnot4": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
@ -1459,7 +1459,7 @@
}
},
"neg5": {
"bnot5": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",

336
test/vmBitwiseLogicOperationTestFiller.json

@ -1224,6 +1224,342 @@
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"signextend_bitIsSet": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "0x62122ff4600016600057",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"signextend_BitIsNotSet": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "0x62122f6a600016600057",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"signextend_BitIsSetInHigherByte": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "0x6212faf4600116600057",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"signextend_BitIsNotSetInHigherByte": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "0x62126af4600116600057",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"signextendInvalidByteNumber": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "0x62126af4605016600057",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"signextend_00": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "{ [[ 0 ]] (SIGNEXTEND 0 0) } ",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"signextend_BigByte_0": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "{ [[ 0 ]] (SIGNEXTEND 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0) } ",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"signextend_0_BigByte": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "{ [[ 0 ]] (SIGNEXTEND 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) } ",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"signextend_BigByteBigByte": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "{ [[ 0 ]] (SIGNEXTEND 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) } ",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"signextend_AlmostBiggestByte": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "{ [[ 0 ]] (SIGNEXTEND 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe) } ",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"signextend_bigBytePlus1": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "0x66f000000000000161ffff16600057",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"signextend_BigBytePlus1_2": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "0x60ff68f0000000000000000116600057",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
}
}

4
windows/LibEthereum.vcxproj

@ -103,8 +103,8 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\libethcore\_libethcore.cpp" />
<ClCompile Include="..\libethereum\Account.cpp" />
<ClCompile Include="..\libethereum\AccountDiff.cpp" />
<ClCompile Include="..\libethereum\AddressState.cpp" />
<ClCompile Include="..\libethereum\BlockChain.cpp" />
<ClCompile Include="..\libethereum\BlockDetails.cpp" />
<ClCompile Include="..\libethereum\BlockQueue.cpp" />
@ -318,8 +318,8 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\libethereum\Account.h" />
<ClInclude Include="..\libethereum\AccountDiff.h" />
<ClInclude Include="..\libethereum\AddressState.h" />
<ClInclude Include="..\libethereum\All.h" />
<ClInclude Include="..\libethereum\BlockChain.h" />
<ClInclude Include="..\libethereum\BlockDetails.h" />

12
windows/LibEthereum.vcxproj.filters

@ -4,9 +4,6 @@
<ClCompile Include="stdafx.cpp">
<Filter>Windows</Filter>
</ClCompile>
<ClCompile Include="..\libethereum\AddressState.cpp">
<Filter>libethereum</Filter>
</ClCompile>
<ClCompile Include="..\libethereum\BlockChain.cpp">
<Filter>libethereum</Filter>
</ClCompile>
@ -202,14 +199,14 @@
<ClCompile Include="..\libdevcrypto\SHA3MAC.cpp">
<Filter>libdevcrypto</Filter>
</ClCompile>
<ClCompile Include="..\libethereum\Account.cpp">
<Filter>libethereum</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Windows</Filter>
</ClInclude>
<ClInclude Include="..\libethereum\AddressState.h">
<Filter>libethereum</Filter>
</ClInclude>
<ClInclude Include="..\libethereum\BlockChain.h">
<Filter>libethereum</Filter>
</ClInclude>
@ -435,6 +432,9 @@
<ClInclude Include="..\libdevcrypto\SHA3MAC.h">
<Filter>libdevcrypto</Filter>
</ClInclude>
<ClInclude Include="..\libethereum\Account.h">
<Filter>libethereum</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Windows">

Loading…
Cancel
Save