Browse Source
Conflicts: alethzero/MainWin.cpp libweb3jsonrpc/WebThreeStubServer.cpp libweb3jsonrpc/abstractwebthreestubserver.h libweb3jsonrpc/spec.json test/jsonrpc.cpp test/webthreestubclient.hcl-refactor
169 changed files with 11828 additions and 5034 deletions
@ -0,0 +1,36 @@ |
|||
/*
|
|||
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 OurWebThreeStubServer.h
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#include "OurWebThreeStubServer.h" |
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::eth; |
|||
|
|||
OurWebThreeStubServer::OurWebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3, std::vector<dev::KeyPair> const& _accounts): |
|||
WebThreeStubServer(_conn, _web3, _accounts) |
|||
{} |
|||
|
|||
std::string OurWebThreeStubServer::shh_newIdentity() |
|||
{ |
|||
dev::KeyPair kp = dev::KeyPair::create(); |
|||
emit onNewId(QString::fromStdString(toJS(kp.sec()))); |
|||
return toJS(kp.pub()); |
|||
} |
@ -0,0 +1,38 @@ |
|||
/*
|
|||
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 OurWebThreeStubServer.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#include <QtCore/QObject> |
|||
#include <libdevcore/CommonJS.h> |
|||
#include <libdevcrypto/Common.h> |
|||
#include <libweb3jsonrpc/WebThreeStubServer.h> |
|||
|
|||
class OurWebThreeStubServer: public QObject, public WebThreeStubServer |
|||
{ |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
OurWebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3, std::vector<dev::KeyPair> const& _accounts); |
|||
|
|||
virtual std::string shh_newIdentity() override; |
|||
|
|||
signals: |
|||
void onNewId(QString _s); |
|||
}; |
@ -1,39 +1,60 @@ |
|||
/*
|
|||
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 SHA3MAC.cpp
|
|||
/** @file AES.cpp
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2014 |
|||
* |
|||
* SHA3 MAC |
|||
*/ |
|||
|
|||
#include "CryptoPP.h" |
|||
#include "SHA3MAC.h" |
|||
#include "AES.h" |
|||
|
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::crypto; |
|||
using namespace dev::crypto::aes; |
|||
using namespace CryptoPP; |
|||
|
|||
void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output) |
|||
struct aes::Aes128Ctr |
|||
{ |
|||
Aes128Ctr(h128 _k) |
|||
{ |
|||
mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data()); |
|||
} |
|||
CTR_Mode<AES>::Encryption mode; |
|||
}; |
|||
|
|||
Stream::Stream(StreamType, h128 _ckey): |
|||
m_cSecret(_ckey) |
|||
{ |
|||
cryptor = new Aes128Ctr(_ckey); |
|||
} |
|||
|
|||
Stream::~Stream() |
|||
{ |
|||
delete cryptor; |
|||
} |
|||
|
|||
void Stream::update(bytesRef) |
|||
{ |
|||
|
|||
} |
|||
|
|||
size_t Stream::streamOut(bytes&) |
|||
{ |
|||
CryptoPP::SHA3_256 ctx; |
|||
ctx.Update((byte*)_secret.data(), _secret.size()); |
|||
ctx.Update((byte*)_plain.data(), _plain.size()); |
|||
assert(_output.size() >= 32); |
|||
ctx.Final(_output.data()); |
|||
return 0; |
|||
} |
|||
|
@ -0,0 +1,89 @@ |
|||
/*
|
|||
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 AES.h
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2014 |
|||
* |
|||
* AES |
|||
* todo: use openssl |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <atomic> |
|||
#include "Common.h" |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace crypto |
|||
{ |
|||
namespace aes |
|||
{ |
|||
|
|||
struct Aes128Ctr; |
|||
enum StreamType { Encrypt, Decrypt }; |
|||
|
|||
/**
|
|||
* @brief Encrypted stream |
|||
*/ |
|||
class Stream |
|||
{ |
|||
public: |
|||
// streamtype maybe irrelevant w/ctr
|
|||
Stream(StreamType _t, h128 _ckey); |
|||
~Stream(); |
|||
|
|||
virtual void update(bytesRef io_bytes); |
|||
|
|||
/// Move ciphertext to _bytes.
|
|||
virtual size_t streamOut(bytes& o_bytes); |
|||
|
|||
private: |
|||
Stream(Stream const&) = delete; |
|||
Stream& operator=(Stream const&) = delete; |
|||
|
|||
h128 m_cSecret; |
|||
bytes m_text; |
|||
|
|||
Aes128Ctr* cryptor; |
|||
}; |
|||
|
|||
|
|||
/**
|
|||
* @brief Encrypted stream with inband SHA3 mac at specific interval. |
|||
*/ |
|||
class AuthenticatedStream: public Stream |
|||
{ |
|||
public: |
|||
AuthenticatedStream(StreamType _t, h128 _ckey, h128 _mackey, unsigned _interval): Stream(_t, _ckey), m_macSecret(_mackey) { m_macInterval = _interval; } |
|||
|
|||
AuthenticatedStream(StreamType _t, Secret const& _s, unsigned _interval): Stream(_t, h128(_s)), m_macSecret(FixedHash<16>((byte const*)_s.data()+16,h128::ConstructFromPointer)) { m_macInterval = _interval; } |
|||
|
|||
/// Adjust mac interval. Next mac will be xored with value.
|
|||
void adjustInterval(unsigned _interval) { m_macInterval = _interval; } |
|||
|
|||
private: |
|||
AuthenticatedStream(AuthenticatedStream const&) = delete; |
|||
AuthenticatedStream& operator=(AuthenticatedStream const&) = delete; |
|||
|
|||
std::atomic<unsigned> m_macInterval; |
|||
h128 m_macSecret; |
|||
}; |
|||
|
|||
} |
|||
} |
|||
} |
@ -1,12 +1,8 @@ |
|||
#pragma once |
|||
|
|||
#include "Common.h" |
|||
#include "CryptoPP.h" |
|||
#include "EC.h" |
|||
#include "AES.h" |
|||
#include "ECDHE.h" |
|||
#include "FileSystem.h" |
|||
#include "MemoryDB.h" |
|||
#include "OverlayDB.h" |
|||
#include "SHA3.h" |
|||
#include "SHA3MAC.h" |
|||
#include "TrieCommon.h" |
|||
#include "TrieDB.h" |
|||
|
@ -1,77 +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 EC.cpp
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2014 |
|||
* |
|||
* Shared EC classes and functions. |
|||
*/ |
|||
|
|||
#pragma warning(push) |
|||
#pragma warning(disable:4100 4244) |
|||
#pragma GCC diagnostic push |
|||
#pragma GCC diagnostic ignored "-Wconversion" |
|||
#pragma GCC diagnostic ignored "-Wunused-parameter" |
|||
#pragma GCC diagnostic ignored "-Wunused-variable" |
|||
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" |
|||
#pragma GCC diagnostic ignored "-Wextra" |
|||
#include <files.h> |
|||
#pragma warning(pop) |
|||
#pragma GCC diagnostic pop |
|||
#include "CryptoPP.h" |
|||
#include "SHA3.h" |
|||
#include "EC.h" |
|||
|
|||
// CryptoPP and dev conflict so dev and pp namespace are used explicitly
|
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::crypto; |
|||
using namespace CryptoPP; |
|||
|
|||
void dev::crypto::encrypt(Public const& _key, bytes& io_cipher) |
|||
{ |
|||
ECIES<ECP>::Encryptor e; |
|||
e.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1()); |
|||
e.AccessKey().SetPublicElement(pp::PointFromPublic(_key)); |
|||
size_t plen = io_cipher.size(); |
|||
bytes c; |
|||
c.resize(e.CiphertextLength(plen)); |
|||
// todo: use StringSource with _plain as input and output.
|
|||
e.Encrypt(pp::PRNG(), io_cipher.data(), plen, c.data()); |
|||
memset(io_cipher.data(), 0, io_cipher.size()); |
|||
io_cipher = std::move(c); |
|||
} |
|||
|
|||
void dev::crypto::decrypt(Secret const& _k, bytes& io_text) |
|||
{ |
|||
CryptoPP::ECIES<CryptoPP::ECP>::Decryptor d; |
|||
d.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1()); |
|||
d.AccessKey().SetPrivateExponent(pp::ExponentFromSecret(_k)); |
|||
size_t clen = io_text.size(); |
|||
bytes p; |
|||
p.resize(d.MaxPlaintextLength(io_text.size())); |
|||
// todo: use StringSource with _c as input and output.
|
|||
DecodingResult r = d.Decrypt(pp::PRNG(), io_text.data(), clen, p.data()); |
|||
if (!r.isValidCoding) |
|||
{ |
|||
io_text.clear(); |
|||
return; |
|||
} |
|||
io_text.resize(r.messageLength); |
|||
io_text = std::move(p); |
|||
} |
|||
|
@ -1,41 +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 EC.h
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2014 |
|||
* |
|||
* Shared EC classes and functions. |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include "Common.h" |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace crypto |
|||
{ |
|||
|
|||
/// Encrypts text (in place).
|
|||
void encrypt(Public const& _k, bytes& io_cipher); |
|||
|
|||
/// Decrypts text (in place).
|
|||
void decrypt(Secret const& _k, bytes& io_text); |
|||
|
|||
} |
|||
} |
|||
|
@ -0,0 +1,100 @@ |
|||
/*
|
|||
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 ECDHE.cpp
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#include "SHA3.h" |
|||
#include "CryptoPP.h" |
|||
#include "ECDHE.h" |
|||
|
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::crypto; |
|||
|
|||
static Secp256k1 s_secp256k1; |
|||
|
|||
void ECDHE::agree(Public const& _remote, Secret& o_sharedSecret) |
|||
{ |
|||
if (m_remoteEphemeral) |
|||
// agreement can only occur once
|
|||
BOOST_THROW_EXCEPTION(InvalidState()); |
|||
|
|||
m_remoteEphemeral = _remote; |
|||
s_secp256k1.agree(m_ephemeral.sec(), m_remoteEphemeral, o_sharedSecret); |
|||
} |
|||
|
|||
void ECDHEKeyExchange::agree(Public const& _remoteEphemeral) |
|||
{ |
|||
s_secp256k1.agree(m_ephemeral.sec(), _remoteEphemeral, m_ephemeralSecret); |
|||
} |
|||
|
|||
void ECDHEKeyExchange::exchange(bytes& o_exchange) |
|||
{ |
|||
if (!m_ephemeralSecret) |
|||
// didn't agree on public remote
|
|||
BOOST_THROW_EXCEPTION(InvalidState()); |
|||
|
|||
// The key exchange payload is in two parts and is encrypted
|
|||
// using ephemeral keypair.
|
|||
//
|
|||
// The first part is the 'prefix' which is a zero-knowledge proof
|
|||
// allowing the remote to resume or emplace a previous session.
|
|||
// If a session previously exists:
|
|||
// prefix is sha3(token) // todo: ephemeral entropy from both sides
|
|||
// If a session doesn't exist:
|
|||
// prefix is sha3(m_ephemeralSecret)
|
|||
//
|
|||
// The second part is encrypted using the public key which relates to the prefix.
|
|||
|
|||
Public encpk = m_known.first ? m_known.first : m_remoteEphemeral; |
|||
bytes exchange(encpk.asBytes()); |
|||
|
|||
// This is the public key which we would like the remote to use,
|
|||
// which maybe different than the previously-known public key.
|
|||
//
|
|||
// Here we should pick an appropriate alias or generate a new one,
|
|||
// but for now, we use static alias passed to constructor.
|
|||
//
|
|||
Public p = toPublic(m_alias.m_secret); |
|||
exchange.resize(exchange.size() + sizeof(p)); |
|||
memcpy(&exchange[exchange.size() - sizeof(p)], p.data(), sizeof(p)); |
|||
|
|||
// protocol parameters; should be fixed size
|
|||
bytes v(1, 0x80); |
|||
exchange.resize(exchange.size() + v.size()); |
|||
memcpy(&exchange[exchange.size() - v.size()], v.data(), v.size()); |
|||
|
|||
h256 auth; |
|||
sha3mac(m_alias.m_secret.ref(), m_ephemeralSecret.ref(), auth.ref()); |
|||
Signature sig = s_secp256k1.sign(m_alias.m_secret, auth); |
|||
exchange.resize(exchange.size() + sizeof(sig)); |
|||
memcpy(&exchange[exchange.size() - sizeof(sig)], sig.data(), sizeof(sig)); |
|||
|
|||
aes::AuthenticatedStream aes(aes::Encrypt, m_ephemeralSecret, 0); |
|||
h256 prefix(sha3(m_known.second ? m_known.second : (h256)m_remoteEphemeral)); |
|||
aes.update(prefix.ref()); |
|||
|
|||
s_secp256k1.encrypt(encpk, exchange); |
|||
aes.update(&exchange); |
|||
|
|||
aes.streamOut(o_exchange); |
|||
} |
|||
|
|||
|
|||
|
@ -0,0 +1,109 @@ |
|||
/*
|
|||
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 ECDHE.h
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2014 |
|||
* |
|||
* Elliptic curve Diffie-Hellman ephemeral key exchange |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include "AES.h" |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace crypto |
|||
{ |
|||
|
|||
/// Public key of remote and corresponding shared secret.
|
|||
typedef std::pair<Public,h256> AliasSession; |
|||
|
|||
/**
|
|||
* @brief An addressable EC key pair. |
|||
*/ |
|||
class Alias |
|||
{ |
|||
friend class ECDHEKeyExchange; // todo: remove
|
|||
public: |
|||
Alias(Secret _s): m_secret(_s) {}; |
|||
|
|||
AliasSession session(Address _a) { return m_sessions.count(_a) ? m_sessions.find(_a)->second : AliasSession(); } |
|||
|
|||
private: |
|||
std::map<Address,AliasSession> m_sessions; |
|||
Secret m_secret; |
|||
}; |
|||
|
|||
/**
|
|||
* @brief Derive DH shared secret from EC keypairs. |
|||
* As ephemeral keys are single-use, agreement is limited to a single occurence. |
|||
*/ |
|||
class ECDHE |
|||
{ |
|||
public: |
|||
/// Constructor (pass public key for ingress exchange).
|
|||
ECDHE(): m_ephemeral(KeyPair::create()) {}; |
|||
|
|||
/// Public key sent to remote.
|
|||
Public pubkey() { return m_ephemeral.pub(); } |
|||
|
|||
/// Input public key for dh agreement, output generated shared secret.
|
|||
void agree(Public const& _remoteEphemeral, Secret& o_sharedSecret); |
|||
|
|||
protected: |
|||
KeyPair m_ephemeral; ///< Ephemeral keypair; generated.
|
|||
Public m_remoteEphemeral; ///< Public key of remote; parameter.
|
|||
}; |
|||
|
|||
/**
|
|||
* @brief Secure exchange of static keys. |
|||
* Key exchange is encrypted with public key of remote and then encrypted by block cipher. For a blind remote the ecdhe public key is used to encrypt exchange, and for a known remote the known public key is used. The block cipher key is derived from ecdhe shared secret. |
|||
* |
|||
* Usage: Agree -> Exchange -> Authenticate |
|||
*/ |
|||
class ECDHEKeyExchange: private ECDHE |
|||
{ |
|||
public: |
|||
/// Exchange with unknown remote (pass public key for ingress exchange)
|
|||
ECDHEKeyExchange(Alias& _k): m_alias(_k) {}; |
|||
|
|||
/// Exchange with known remote
|
|||
ECDHEKeyExchange(Alias& _k, AliasSession _known): m_alias(_k), m_known(_known) {}; |
|||
|
|||
/// Provide public key for dh agreement to generate shared secret.
|
|||
void agree(Public const& _remoteEphemeral); |
|||
|
|||
/// @returns encrypted payload of key exchange
|
|||
void exchange(bytes& o_exchange); |
|||
|
|||
/// Decrypt payload, check mac, check trust, decrypt exchange, authenticate exchange, verify version, verify signature, and if no failure occurs, update or creats trust and derive session-shared-secret.
|
|||
bool authenticate(bytes _exchangeIn); |
|||
|
|||
private: |
|||
Secret m_ephemeralSecret; |
|||
Alias m_alias; |
|||
AliasSession m_known; |
|||
Secret m_sharedAliasSecret; |
|||
|
|||
FixedHash<16> m_sharedC; |
|||
FixedHash<16> m_sharedM; |
|||
}; |
|||
|
|||
} |
|||
} |
|||
|
@ -1,38 +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 SHA3MAC.h
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2014 |
|||
* |
|||
* SHA3 MAC |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <libdevcore/Common.h> |
|||
#include <libdevcore/FixedHash.h> |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace crypto |
|||
{ |
|||
|
|||
void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output); |
|||
|
|||
} |
|||
} |
|||
|
@ -0,0 +1,72 @@ |
|||
/*
|
|||
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 TransactionReceipt.h
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <array> |
|||
#include <map> |
|||
#include <libdevcore/Common.h> |
|||
#include <libdevcore/RLP.h> |
|||
#include <libevm/ExtVMFace.h> |
|||
#include "Manifest.h" |
|||
|
|||
namespace dev |
|||
{ |
|||
|
|||
namespace eth |
|||
{ |
|||
|
|||
class TransactionReceipt |
|||
{ |
|||
public: |
|||
TransactionReceipt(bytesConstRef _rlp) { RLP r(_rlp); m_stateRoot = (h256)r[0]; m_gasUsed = (u256)r[1]; m_bloom = (LogBloom)r[2]; for (auto const& i: r[3]) m_log.emplace_back(i); } |
|||
TransactionReceipt(h256 _root, u256 _gasUsed, LogEntries const& _log, Manifest const& _ms): m_stateRoot(_root), m_gasUsed(_gasUsed), m_bloom(eth::bloom(_log)), m_log(_log), m_changes(_ms) {} |
|||
|
|||
Manifest const& changes() const { return m_changes; } |
|||
|
|||
h256 const& stateRoot() const { return m_stateRoot; } |
|||
u256 const& gasUsed() const { return m_gasUsed; } |
|||
LogBloom const& bloom() const { return m_bloom; } |
|||
LogEntries const& log() const { return m_log; } |
|||
|
|||
void streamRLP(RLPStream& _s) const |
|||
{ |
|||
_s.appendList(4) << m_stateRoot << m_gasUsed << m_bloom; |
|||
_s.appendList(m_log.size()); |
|||
for (LogEntry const& l: m_log) |
|||
l.streamRLP(_s); |
|||
} |
|||
|
|||
bytes rlp() const { RLPStream s; streamRLP(s); return s.out(); } |
|||
|
|||
private: |
|||
h256 m_stateRoot; |
|||
u256 m_gasUsed; |
|||
LogBloom m_bloom; |
|||
LogEntries m_log; |
|||
|
|||
Manifest m_changes; ///< TODO: PoC-7: KILL
|
|||
}; |
|||
|
|||
using TransactionReceipts = std::vector<TransactionReceipt>; |
|||
|
|||
} |
|||
} |
@ -0,0 +1,337 @@ |
|||
/*
|
|||
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 Instruction.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#include "Instruction.h" |
|||
|
|||
#include <libdevcore/Common.h> |
|||
#include <libdevcore/CommonIO.h> |
|||
#include <libdevcore/Log.h> |
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::eth; |
|||
|
|||
const std::map<std::string, Instruction> dev::eth::c_instructions = |
|||
{ |
|||
{ "STOP", Instruction::STOP }, |
|||
{ "ADD", Instruction::ADD }, |
|||
{ "SUB", Instruction::SUB }, |
|||
{ "MUL", Instruction::MUL }, |
|||
{ "DIV", Instruction::DIV }, |
|||
{ "SDIV", Instruction::SDIV }, |
|||
{ "MOD", Instruction::MOD }, |
|||
{ "SMOD", Instruction::SMOD }, |
|||
{ "EXP", Instruction::EXP }, |
|||
{ "BNOT", Instruction::NOT }, |
|||
{ "LT", Instruction::LT }, |
|||
{ "GT", Instruction::GT }, |
|||
{ "SLT", Instruction::SLT }, |
|||
{ "SGT", Instruction::SGT }, |
|||
{ "EQ", Instruction::EQ }, |
|||
{ "NOT", Instruction::ISZERO }, |
|||
{ "AND", Instruction::AND }, |
|||
{ "OR", Instruction::OR }, |
|||
{ "XOR", Instruction::XOR }, |
|||
{ "BYTE", Instruction::BYTE }, |
|||
{ "ADDMOD", Instruction::ADDMOD }, |
|||
{ "MULMOD", Instruction::MULMOD }, |
|||
{ "SIGNEXTEND", Instruction::SIGNEXTEND }, |
|||
{ "SHA3", Instruction::SHA3 }, |
|||
{ "ADDRESS", Instruction::ADDRESS }, |
|||
{ "BALANCE", Instruction::BALANCE }, |
|||
{ "ORIGIN", Instruction::ORIGIN }, |
|||
{ "CALLER", Instruction::CALLER }, |
|||
{ "CALLVALUE", Instruction::CALLVALUE }, |
|||
{ "CALLDATALOAD", Instruction::CALLDATALOAD }, |
|||
{ "CALLDATASIZE", Instruction::CALLDATASIZE }, |
|||
{ "CALLDATACOPY", Instruction::CALLDATACOPY }, |
|||
{ "CODESIZE", Instruction::CODESIZE }, |
|||
{ "CODECOPY", Instruction::CODECOPY }, |
|||
{ "GASPRICE", Instruction::GASPRICE }, |
|||
{ "EXTCODESIZE", Instruction::EXTCODESIZE }, |
|||
{ "EXTCODECOPY", Instruction::EXTCODECOPY }, |
|||
{ "PREVHASH", Instruction::PREVHASH }, |
|||
{ "COINBASE", Instruction::COINBASE }, |
|||
{ "TIMESTAMP", Instruction::TIMESTAMP }, |
|||
{ "NUMBER", Instruction::NUMBER }, |
|||
{ "DIFFICULTY", Instruction::DIFFICULTY }, |
|||
{ "GASLIMIT", Instruction::GASLIMIT }, |
|||
{ "POP", Instruction::POP }, |
|||
{ "MLOAD", Instruction::MLOAD }, |
|||
{ "MSTORE", Instruction::MSTORE }, |
|||
{ "MSTORE8", Instruction::MSTORE8 }, |
|||
{ "SLOAD", Instruction::SLOAD }, |
|||
{ "SSTORE", Instruction::SSTORE }, |
|||
{ "JUMP", Instruction::JUMP }, |
|||
{ "JUMPI", Instruction::JUMPI }, |
|||
{ "PC", Instruction::PC }, |
|||
{ "MSIZE", Instruction::MSIZE }, |
|||
{ "GAS", Instruction::GAS }, |
|||
{ "JUMPDEST", Instruction::JUMPDEST }, |
|||
{ "PUSH1", Instruction::PUSH1 }, |
|||
{ "PUSH2", Instruction::PUSH2 }, |
|||
{ "PUSH3", Instruction::PUSH3 }, |
|||
{ "PUSH4", Instruction::PUSH4 }, |
|||
{ "PUSH5", Instruction::PUSH5 }, |
|||
{ "PUSH6", Instruction::PUSH6 }, |
|||
{ "PUSH7", Instruction::PUSH7 }, |
|||
{ "PUSH8", Instruction::PUSH8 }, |
|||
{ "PUSH9", Instruction::PUSH9 }, |
|||
{ "PUSH10", Instruction::PUSH10 }, |
|||
{ "PUSH11", Instruction::PUSH11 }, |
|||
{ "PUSH12", Instruction::PUSH12 }, |
|||
{ "PUSH13", Instruction::PUSH13 }, |
|||
{ "PUSH14", Instruction::PUSH14 }, |
|||
{ "PUSH15", Instruction::PUSH15 }, |
|||
{ "PUSH16", Instruction::PUSH16 }, |
|||
{ "PUSH17", Instruction::PUSH17 }, |
|||
{ "PUSH18", Instruction::PUSH18 }, |
|||
{ "PUSH19", Instruction::PUSH19 }, |
|||
{ "PUSH20", Instruction::PUSH20 }, |
|||
{ "PUSH21", Instruction::PUSH21 }, |
|||
{ "PUSH22", Instruction::PUSH22 }, |
|||
{ "PUSH23", Instruction::PUSH23 }, |
|||
{ "PUSH24", Instruction::PUSH24 }, |
|||
{ "PUSH25", Instruction::PUSH25 }, |
|||
{ "PUSH26", Instruction::PUSH26 }, |
|||
{ "PUSH27", Instruction::PUSH27 }, |
|||
{ "PUSH28", Instruction::PUSH28 }, |
|||
{ "PUSH29", Instruction::PUSH29 }, |
|||
{ "PUSH30", Instruction::PUSH30 }, |
|||
{ "PUSH31", Instruction::PUSH31 }, |
|||
{ "PUSH32", Instruction::PUSH32 }, |
|||
{ "DUP1", Instruction::DUP1 }, |
|||
{ "DUP2", Instruction::DUP2 }, |
|||
{ "DUP3", Instruction::DUP3 }, |
|||
{ "DUP4", Instruction::DUP4 }, |
|||
{ "DUP5", Instruction::DUP5 }, |
|||
{ "DUP6", Instruction::DUP6 }, |
|||
{ "DUP7", Instruction::DUP7 }, |
|||
{ "DUP8", Instruction::DUP8 }, |
|||
{ "DUP9", Instruction::DUP9 }, |
|||
{ "DUP10", Instruction::DUP10 }, |
|||
{ "DUP11", Instruction::DUP11 }, |
|||
{ "DUP12", Instruction::DUP12 }, |
|||
{ "DUP13", Instruction::DUP13 }, |
|||
{ "DUP14", Instruction::DUP14 }, |
|||
{ "DUP15", Instruction::DUP15 }, |
|||
{ "DUP16", Instruction::DUP16 }, |
|||
{ "SWAP1", Instruction::SWAP1 }, |
|||
{ "SWAP2", Instruction::SWAP2 }, |
|||
{ "SWAP3", Instruction::SWAP3 }, |
|||
{ "SWAP4", Instruction::SWAP4 }, |
|||
{ "SWAP5", Instruction::SWAP5 }, |
|||
{ "SWAP6", Instruction::SWAP6 }, |
|||
{ "SWAP7", Instruction::SWAP7 }, |
|||
{ "SWAP8", Instruction::SWAP8 }, |
|||
{ "SWAP9", Instruction::SWAP9 }, |
|||
{ "SWAP10", Instruction::SWAP10 }, |
|||
{ "SWAP11", Instruction::SWAP11 }, |
|||
{ "SWAP12", Instruction::SWAP12 }, |
|||
{ "SWAP13", Instruction::SWAP13 }, |
|||
{ "SWAP14", Instruction::SWAP14 }, |
|||
{ "SWAP15", Instruction::SWAP15 }, |
|||
{ "SWAP16", Instruction::SWAP16 }, |
|||
{ "LOG0", Instruction::LOG0 }, |
|||
{ "LOG1", Instruction::LOG1 }, |
|||
{ "LOG2", Instruction::LOG2 }, |
|||
{ "LOG3", Instruction::LOG3 }, |
|||
{ "LOG4", Instruction::LOG4 }, |
|||
{ "CREATE", Instruction::CREATE }, |
|||
{ "CALL", Instruction::CALL }, |
|||
{ "CALLCODE", Instruction::CALLCODE }, |
|||
{ "RETURN", Instruction::RETURN }, |
|||
{ "SUICIDE", Instruction::SUICIDE } |
|||
}; |
|||
|
|||
static const std::map<Instruction, InstructionInfo> c_instructionInfo = |
|||
{ // Add, Args, Ret, SideEffects
|
|||
{ Instruction::STOP, { "STOP", 0, 0, 0, true } }, |
|||
{ Instruction::ADD, { "ADD", 0, 2, 1, false } }, |
|||
{ Instruction::SUB, { "SUB", 0, 2, 1, false } }, |
|||
{ Instruction::MUL, { "MUL", 0, 2, 1, false } }, |
|||
{ Instruction::DIV, { "DIV", 0, 2, 1, false } }, |
|||
{ Instruction::SDIV, { "SDIV", 0, 2, 1, false } }, |
|||
{ Instruction::MOD, { "MOD", 0, 2, 1, false } }, |
|||
{ Instruction::SMOD, { "SMOD", 0, 2, 1, false } }, |
|||
{ Instruction::EXP, { "EXP", 0, 2, 1, false } }, |
|||
{ Instruction::NOT, { "NOT", 0, 1, 1, false } }, |
|||
{ Instruction::LT, { "LT", 0, 2, 1, false } }, |
|||
{ Instruction::GT, { "GT", 0, 2, 1, false } }, |
|||
{ Instruction::SLT, { "SLT", 0, 2, 1, false } }, |
|||
{ Instruction::SGT, { "SGT", 0, 2, 1, false } }, |
|||
{ Instruction::EQ, { "EQ", 0, 2, 1, false } }, |
|||
{ Instruction::ISZERO, { "ISZERO", 0, 1, 1, false } }, |
|||
{ Instruction::AND, { "AND", 0, 2, 1, false } }, |
|||
{ Instruction::OR, { "OR", 0, 2, 1, false } }, |
|||
{ Instruction::XOR, { "XOR", 0, 2, 1, false } }, |
|||
{ Instruction::BYTE, { "BYTE", 0, 2, 1, false } }, |
|||
{ Instruction::ADDMOD, { "ADDMOD", 0, 3, 1, false } }, |
|||
{ Instruction::MULMOD, { "MULMOD", 0, 3, 1, false } }, |
|||
{ Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1, false } }, |
|||
{ Instruction::SHA3, { "SHA3", 0, 2, 1, false } }, |
|||
{ Instruction::ADDRESS, { "ADDRESS", 0, 0, 1, false } }, |
|||
{ Instruction::BALANCE, { "BALANCE", 0, 1, 1, false } }, |
|||
{ Instruction::ORIGIN, { "ORIGIN", 0, 0, 1, false } }, |
|||
{ Instruction::CALLER, { "CALLER", 0, 0, 1, false } }, |
|||
{ Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1, false } }, |
|||
{ Instruction::CALLDATALOAD,{ "CALLDATALOAD", 0, 1, 1, false } }, |
|||
{ Instruction::CALLDATASIZE,{ "CALLDATASIZE", 0, 0, 1, false } }, |
|||
{ Instruction::CALLDATACOPY,{ "CALLDATACOPY", 0, 3, 0, true } }, |
|||
{ Instruction::CODESIZE, { "CODESIZE", 0, 0, 1, false } }, |
|||
{ Instruction::CODECOPY, { "CODECOPY", 0, 3, 0, true } }, |
|||
{ Instruction::GASPRICE, { "GASPRICE", 0, 0, 1, false } }, |
|||
{ Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1, false } }, |
|||
{ Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true } }, |
|||
{ Instruction::PREVHASH, { "PREVHASH", 0, 0, 1, false } }, |
|||
{ Instruction::COINBASE, { "COINBASE", 0, 0, 1, false } }, |
|||
{ Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false } }, |
|||
{ Instruction::NUMBER, { "NUMBER", 0, 0, 1, false } }, |
|||
{ Instruction::DIFFICULTY, { "DIFFICULTY", 0, 0, 1, false } }, |
|||
{ Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1, false } }, |
|||
{ Instruction::POP, { "POP", 0, 1, 0, false } }, |
|||
{ Instruction::MLOAD, { "MLOAD", 0, 1, 1, false } }, |
|||
{ Instruction::MSTORE, { "MSTORE", 0, 2, 0, true } }, |
|||
{ Instruction::MSTORE8, { "MSTORE8", 0, 2, 0, true } }, |
|||
{ Instruction::SLOAD, { "SLOAD", 0, 1, 1, false } }, |
|||
{ Instruction::SSTORE, { "SSTORE", 0, 2, 0, true } }, |
|||
{ Instruction::JUMP, { "JUMP", 0, 1, 0, true } }, |
|||
{ Instruction::JUMPI, { "JUMPI", 0, 2, 0, true } }, |
|||
{ Instruction::PC, { "PC", 0, 0, 1, false } }, |
|||
{ Instruction::MSIZE, { "MSIZE", 0, 0, 1, false } }, |
|||
{ Instruction::GAS, { "GAS", 0, 0, 1, false } }, |
|||
{ Instruction::JUMPDEST, { "JUMPDEST", 0, 1, 0, true } }, |
|||
{ Instruction::PUSH1, { "PUSH1", 1, 0, 1, false } }, |
|||
{ Instruction::PUSH2, { "PUSH2", 2, 0, 1, false } }, |
|||
{ Instruction::PUSH3, { "PUSH3", 3, 0, 1, false } }, |
|||
{ Instruction::PUSH4, { "PUSH4", 4, 0, 1, false } }, |
|||
{ Instruction::PUSH5, { "PUSH5", 5, 0, 1, false } }, |
|||
{ Instruction::PUSH6, { "PUSH6", 6, 0, 1, false } }, |
|||
{ Instruction::PUSH7, { "PUSH7", 7, 0, 1, false } }, |
|||
{ Instruction::PUSH8, { "PUSH8", 8, 0, 1, false } }, |
|||
{ Instruction::PUSH9, { "PUSH9", 9, 0, 1, false } }, |
|||
{ Instruction::PUSH10, { "PUSH10", 10, 0, 1, false } }, |
|||
{ Instruction::PUSH11, { "PUSH11", 11, 0, 1, false } }, |
|||
{ Instruction::PUSH12, { "PUSH12", 12, 0, 1, false } }, |
|||
{ Instruction::PUSH13, { "PUSH13", 13, 0, 1, false } }, |
|||
{ Instruction::PUSH14, { "PUSH14", 14, 0, 1, false } }, |
|||
{ Instruction::PUSH15, { "PUSH15", 15, 0, 1, false } }, |
|||
{ Instruction::PUSH16, { "PUSH16", 16, 0, 1, false } }, |
|||
{ Instruction::PUSH17, { "PUSH17", 17, 0, 1, false } }, |
|||
{ Instruction::PUSH18, { "PUSH18", 18, 0, 1, false } }, |
|||
{ Instruction::PUSH19, { "PUSH19", 19, 0, 1, false } }, |
|||
{ Instruction::PUSH20, { "PUSH20", 20, 0, 1, false } }, |
|||
{ Instruction::PUSH21, { "PUSH21", 21, 0, 1, false } }, |
|||
{ Instruction::PUSH22, { "PUSH22", 22, 0, 1, false } }, |
|||
{ Instruction::PUSH23, { "PUSH23", 23, 0, 1, false } }, |
|||
{ Instruction::PUSH24, { "PUSH24", 24, 0, 1, false } }, |
|||
{ Instruction::PUSH25, { "PUSH25", 25, 0, 1, false } }, |
|||
{ Instruction::PUSH26, { "PUSH26", 26, 0, 1, false } }, |
|||
{ Instruction::PUSH27, { "PUSH27", 27, 0, 1, false } }, |
|||
{ Instruction::PUSH28, { "PUSH28", 28, 0, 1, false } }, |
|||
{ Instruction::PUSH29, { "PUSH29", 29, 0, 1, false } }, |
|||
{ Instruction::PUSH30, { "PUSH30", 30, 0, 1, false } }, |
|||
{ Instruction::PUSH31, { "PUSH31", 31, 0, 1, false } }, |
|||
{ Instruction::PUSH32, { "PUSH32", 32, 0, 1, false } }, |
|||
{ Instruction::DUP1, { "DUP1", 0, 1, 2, false } }, |
|||
{ Instruction::DUP2, { "DUP2", 0, 2, 3, false } }, |
|||
{ Instruction::DUP3, { "DUP3", 0, 3, 4, false } }, |
|||
{ Instruction::DUP4, { "DUP4", 0, 4, 5, false } }, |
|||
{ Instruction::DUP5, { "DUP5", 0, 5, 6, false } }, |
|||
{ Instruction::DUP6, { "DUP6", 0, 6, 7, false } }, |
|||
{ Instruction::DUP7, { "DUP7", 0, 7, 8, false } }, |
|||
{ Instruction::DUP8, { "DUP8", 0, 8, 9, false } }, |
|||
{ Instruction::DUP9, { "DUP9", 0, 9, 10, false } }, |
|||
{ Instruction::DUP10, { "DUP10", 0, 10, 11, false } }, |
|||
{ Instruction::DUP11, { "DUP11", 0, 11, 12, false } }, |
|||
{ Instruction::DUP12, { "DUP12", 0, 12, 13, false } }, |
|||
{ Instruction::DUP13, { "DUP13", 0, 13, 14, false } }, |
|||
{ Instruction::DUP14, { "DUP14", 0, 14, 15, false } }, |
|||
{ Instruction::DUP15, { "DUP15", 0, 15, 16, false } }, |
|||
{ Instruction::DUP16, { "DUP16", 0, 16, 17, false } }, |
|||
{ Instruction::SWAP1, { "SWAP1", 0, 2, 2, false } }, |
|||
{ Instruction::SWAP2, { "SWAP2", 0, 3, 3, false } }, |
|||
{ Instruction::SWAP3, { "SWAP3", 0, 4, 4, false } }, |
|||
{ Instruction::SWAP4, { "SWAP4", 0, 5, 5, false } }, |
|||
{ Instruction::SWAP5, { "SWAP5", 0, 6, 6, false } }, |
|||
{ Instruction::SWAP6, { "SWAP6", 0, 7, 7, false } }, |
|||
{ Instruction::SWAP7, { "SWAP7", 0, 8, 8, false } }, |
|||
{ Instruction::SWAP8, { "SWAP8", 0, 9, 9, false } }, |
|||
{ Instruction::SWAP9, { "SWAP9", 0, 10, 10, false } }, |
|||
{ Instruction::SWAP10, { "SWAP10", 0, 11, 11, false } }, |
|||
{ Instruction::SWAP11, { "SWAP11", 0, 12, 12, false } }, |
|||
{ Instruction::SWAP12, { "SWAP12", 0, 13, 13, false } }, |
|||
{ Instruction::SWAP13, { "SWAP13", 0, 14, 14, false } }, |
|||
{ Instruction::SWAP14, { "SWAP14", 0, 15, 15, false } }, |
|||
{ Instruction::SWAP15, { "SWAP15", 0, 16, 16, false } }, |
|||
{ Instruction::SWAP16, { "SWAP16", 0, 17, 17, false } }, |
|||
{ Instruction::LOG0, { "LOG0", 0, 2, 0, true } }, |
|||
{ Instruction::LOG1, { "LOG1", 0, 3, 0, true } }, |
|||
{ Instruction::LOG2, { "LOG2", 0, 4, 0, true } }, |
|||
{ Instruction::LOG3, { "LOG3", 0, 5, 0, true } }, |
|||
{ Instruction::LOG4, { "LOG4", 0, 6, 0, true } }, |
|||
{ Instruction::CREATE, { "CREATE", 0, 3, 1, true } }, |
|||
{ Instruction::CALL, { "CALL", 0, 7, 1, true } }, |
|||
{ Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true } }, |
|||
{ Instruction::RETURN, { "RETURN", 0, 2, 0, true } }, |
|||
{ Instruction::SUICIDE, { "SUICIDE", 0, 1, 0, true } } |
|||
}; |
|||
|
|||
string dev::eth::disassemble(bytes const& _mem) |
|||
{ |
|||
stringstream ret; |
|||
unsigned numerics = 0; |
|||
for (auto it = _mem.begin(); it != _mem.end(); ++it) |
|||
{ |
|||
byte n = *it; |
|||
auto iit = c_instructionInfo.find((Instruction)n); |
|||
if (numerics || iit == c_instructionInfo.end() || (byte)iit->first != n) // not an instruction or expecting an argument...
|
|||
{ |
|||
if (numerics) |
|||
numerics--; |
|||
ret << "0x" << hex << (int)n << " "; |
|||
} |
|||
else |
|||
{ |
|||
auto const& ii = iit->second; |
|||
ret << ii.name << " "; |
|||
numerics = ii.additional; |
|||
} |
|||
} |
|||
return ret.str(); |
|||
} |
|||
|
|||
InstructionInfo dev::eth::instructionInfo(Instruction _inst) |
|||
{ |
|||
try |
|||
{ |
|||
return c_instructionInfo.at(_inst); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cwarn << "<INVALID_INSTRUCTION: " << toString((unsigned)_inst) << ">\n" << boost::current_exception_diagnostic_information(); |
|||
return InstructionInfo({"<INVALID_INSTRUCTION: " + toString((unsigned)_inst) + ">", 0, 0, 0, false}); |
|||
} |
|||
} |
|||
|
|||
bool dev::eth::isValidInstruction(Instruction _inst) |
|||
{ |
|||
return !!c_instructionInfo.count(_inst); |
|||
} |
@ -1,337 +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 Instruction.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#include "Instruction.h" |
|||
|
|||
#include <libdevcore/Common.h> |
|||
#include <libdevcore/CommonIO.h> |
|||
#include <libdevcore/Log.h> |
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::eth; |
|||
|
|||
const std::map<std::string, Instruction> dev::eth::c_instructions = |
|||
{ |
|||
{ "STOP", Instruction::STOP }, |
|||
{ "ADD", Instruction::ADD }, |
|||
{ "SUB", Instruction::SUB }, |
|||
{ "MUL", Instruction::MUL }, |
|||
{ "DIV", Instruction::DIV }, |
|||
{ "SDIV", Instruction::SDIV }, |
|||
{ "MOD", Instruction::MOD }, |
|||
{ "SMOD", Instruction::SMOD }, |
|||
{ "EXP", Instruction::EXP }, |
|||
{ "BNOT", Instruction::NOT }, |
|||
{ "LT", Instruction::LT }, |
|||
{ "GT", Instruction::GT }, |
|||
{ "SLT", Instruction::SLT }, |
|||
{ "SGT", Instruction::SGT }, |
|||
{ "EQ", Instruction::EQ }, |
|||
{ "NOT", Instruction::ISZERO }, |
|||
{ "AND", Instruction::AND }, |
|||
{ "OR", Instruction::OR }, |
|||
{ "XOR", Instruction::XOR }, |
|||
{ "BYTE", Instruction::BYTE }, |
|||
{ "ADDMOD", Instruction::ADDMOD }, |
|||
{ "MULMOD", Instruction::MULMOD }, |
|||
{ "SIGNEXTEND", Instruction::SIGNEXTEND }, |
|||
{ "SHA3", Instruction::SHA3 }, |
|||
{ "ADDRESS", Instruction::ADDRESS }, |
|||
{ "BALANCE", Instruction::BALANCE }, |
|||
{ "ORIGIN", Instruction::ORIGIN }, |
|||
{ "CALLER", Instruction::CALLER }, |
|||
{ "CALLVALUE", Instruction::CALLVALUE }, |
|||
{ "CALLDATALOAD", Instruction::CALLDATALOAD }, |
|||
{ "CALLDATASIZE", Instruction::CALLDATASIZE }, |
|||
{ "CALLDATACOPY", Instruction::CALLDATACOPY }, |
|||
{ "CODESIZE", Instruction::CODESIZE }, |
|||
{ "CODECOPY", Instruction::CODECOPY }, |
|||
{ "GASPRICE", Instruction::GASPRICE }, |
|||
{ "EXTCODESIZE", Instruction::EXTCODESIZE }, |
|||
{ "EXTCODECOPY", Instruction::EXTCODECOPY }, |
|||
{ "PREVHASH", Instruction::PREVHASH }, |
|||
{ "COINBASE", Instruction::COINBASE }, |
|||
{ "TIMESTAMP", Instruction::TIMESTAMP }, |
|||
{ "NUMBER", Instruction::NUMBER }, |
|||
{ "DIFFICULTY", Instruction::DIFFICULTY }, |
|||
{ "GASLIMIT", Instruction::GASLIMIT }, |
|||
{ "POP", Instruction::POP }, |
|||
{ "MLOAD", Instruction::MLOAD }, |
|||
{ "MSTORE", Instruction::MSTORE }, |
|||
{ "MSTORE8", Instruction::MSTORE8 }, |
|||
{ "SLOAD", Instruction::SLOAD }, |
|||
{ "SSTORE", Instruction::SSTORE }, |
|||
{ "JUMP", Instruction::JUMP }, |
|||
{ "JUMPI", Instruction::JUMPI }, |
|||
{ "PC", Instruction::PC }, |
|||
{ "MSIZE", Instruction::MSIZE }, |
|||
{ "GAS", Instruction::GAS }, |
|||
{ "JUMPDEST", Instruction::JUMPDEST }, |
|||
{ "PUSH1", Instruction::PUSH1 }, |
|||
{ "PUSH2", Instruction::PUSH2 }, |
|||
{ "PUSH3", Instruction::PUSH3 }, |
|||
{ "PUSH4", Instruction::PUSH4 }, |
|||
{ "PUSH5", Instruction::PUSH5 }, |
|||
{ "PUSH6", Instruction::PUSH6 }, |
|||
{ "PUSH7", Instruction::PUSH7 }, |
|||
{ "PUSH8", Instruction::PUSH8 }, |
|||
{ "PUSH9", Instruction::PUSH9 }, |
|||
{ "PUSH10", Instruction::PUSH10 }, |
|||
{ "PUSH11", Instruction::PUSH11 }, |
|||
{ "PUSH12", Instruction::PUSH12 }, |
|||
{ "PUSH13", Instruction::PUSH13 }, |
|||
{ "PUSH14", Instruction::PUSH14 }, |
|||
{ "PUSH15", Instruction::PUSH15 }, |
|||
{ "PUSH16", Instruction::PUSH16 }, |
|||
{ "PUSH17", Instruction::PUSH17 }, |
|||
{ "PUSH18", Instruction::PUSH18 }, |
|||
{ "PUSH19", Instruction::PUSH19 }, |
|||
{ "PUSH20", Instruction::PUSH20 }, |
|||
{ "PUSH21", Instruction::PUSH21 }, |
|||
{ "PUSH22", Instruction::PUSH22 }, |
|||
{ "PUSH23", Instruction::PUSH23 }, |
|||
{ "PUSH24", Instruction::PUSH24 }, |
|||
{ "PUSH25", Instruction::PUSH25 }, |
|||
{ "PUSH26", Instruction::PUSH26 }, |
|||
{ "PUSH27", Instruction::PUSH27 }, |
|||
{ "PUSH28", Instruction::PUSH28 }, |
|||
{ "PUSH29", Instruction::PUSH29 }, |
|||
{ "PUSH30", Instruction::PUSH30 }, |
|||
{ "PUSH31", Instruction::PUSH31 }, |
|||
{ "PUSH32", Instruction::PUSH32 }, |
|||
{ "DUP1", Instruction::DUP1 }, |
|||
{ "DUP2", Instruction::DUP2 }, |
|||
{ "DUP3", Instruction::DUP3 }, |
|||
{ "DUP4", Instruction::DUP4 }, |
|||
{ "DUP5", Instruction::DUP5 }, |
|||
{ "DUP6", Instruction::DUP6 }, |
|||
{ "DUP7", Instruction::DUP7 }, |
|||
{ "DUP8", Instruction::DUP8 }, |
|||
{ "DUP9", Instruction::DUP9 }, |
|||
{ "DUP10", Instruction::DUP10 }, |
|||
{ "DUP11", Instruction::DUP11 }, |
|||
{ "DUP12", Instruction::DUP12 }, |
|||
{ "DUP13", Instruction::DUP13 }, |
|||
{ "DUP14", Instruction::DUP14 }, |
|||
{ "DUP15", Instruction::DUP15 }, |
|||
{ "DUP16", Instruction::DUP16 }, |
|||
{ "SWAP1", Instruction::SWAP1 }, |
|||
{ "SWAP2", Instruction::SWAP2 }, |
|||
{ "SWAP3", Instruction::SWAP3 }, |
|||
{ "SWAP4", Instruction::SWAP4 }, |
|||
{ "SWAP5", Instruction::SWAP5 }, |
|||
{ "SWAP6", Instruction::SWAP6 }, |
|||
{ "SWAP7", Instruction::SWAP7 }, |
|||
{ "SWAP8", Instruction::SWAP8 }, |
|||
{ "SWAP9", Instruction::SWAP9 }, |
|||
{ "SWAP10", Instruction::SWAP10 }, |
|||
{ "SWAP11", Instruction::SWAP11 }, |
|||
{ "SWAP12", Instruction::SWAP12 }, |
|||
{ "SWAP13", Instruction::SWAP13 }, |
|||
{ "SWAP14", Instruction::SWAP14 }, |
|||
{ "SWAP15", Instruction::SWAP15 }, |
|||
{ "SWAP16", Instruction::SWAP16 }, |
|||
{ "LOG0", Instruction::LOG0 }, |
|||
{ "LOG1", Instruction::LOG1 }, |
|||
{ "LOG2", Instruction::LOG2 }, |
|||
{ "LOG3", Instruction::LOG3 }, |
|||
{ "LOG4", Instruction::LOG4 }, |
|||
{ "CREATE", Instruction::CREATE }, |
|||
{ "CALL", Instruction::CALL }, |
|||
{ "CALLCODE", Instruction::CALLCODE }, |
|||
{ "RETURN", Instruction::RETURN }, |
|||
{ "SUICIDE", Instruction::SUICIDE } |
|||
}; |
|||
|
|||
static const std::map<Instruction, InstructionInfo> c_instructionInfo = |
|||
{ // Add, Args, Ret
|
|||
{ Instruction::STOP, { "STOP", 0, 0, 0 } }, |
|||
{ Instruction::ADD, { "ADD", 0, 2, 1 } }, |
|||
{ Instruction::SUB, { "SUB", 0, 2, 1 } }, |
|||
{ Instruction::MUL, { "MUL", 0, 2, 1 } }, |
|||
{ Instruction::DIV, { "DIV", 0, 2, 1 } }, |
|||
{ Instruction::SDIV, { "SDIV", 0, 2, 1 } }, |
|||
{ Instruction::MOD, { "MOD", 0, 2, 1 } }, |
|||
{ Instruction::SMOD, { "SMOD", 0, 2, 1 } }, |
|||
{ Instruction::EXP, { "EXP", 0, 2, 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::ISZERO, { "NOT", 0, 1, 1 } }, |
|||
{ Instruction::AND, { "AND", 0, 2, 1 } }, |
|||
{ Instruction::OR, { "OR", 0, 2, 1 } }, |
|||
{ Instruction::XOR, { "XOR", 0, 2, 1 } }, |
|||
{ Instruction::BYTE, { "BYTE", 0, 2, 1 } }, |
|||
{ Instruction::ADDMOD, { "ADDMOD", 0, 3, 1 } }, |
|||
{ Instruction::MULMOD, { "MULMOD", 0, 3, 1 } }, |
|||
{ Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1 } }, |
|||
{ Instruction::SHA3, { "SHA3", 0, 2, 1 } }, |
|||
{ Instruction::ADDRESS, { "ADDRESS", 0, 0, 1 } }, |
|||
{ Instruction::BALANCE, { "BALANCE", 0, 1, 1 } }, |
|||
{ Instruction::ORIGIN, { "ORIGIN", 0, 0, 1 } }, |
|||
{ Instruction::CALLER, { "CALLER", 0, 0, 1 } }, |
|||
{ Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1 } }, |
|||
{ Instruction::CALLDATALOAD,{ "CALLDATALOAD", 0, 1, 1 } }, |
|||
{ Instruction::CALLDATASIZE,{ "CALLDATASIZE", 0, 0, 1 } }, |
|||
{ Instruction::CALLDATACOPY,{ "CALLDATACOPY", 0, 3, 0 } }, |
|||
{ Instruction::CODESIZE, { "CODESIZE", 0, 0, 1 } }, |
|||
{ Instruction::CODECOPY, { "CODECOPY", 0, 3, 0 } }, |
|||
{ Instruction::GASPRICE, { "GASPRICE", 0, 0, 1 } }, |
|||
{ Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1 } }, |
|||
{ Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0 } }, |
|||
{ Instruction::PREVHASH, { "PREVHASH", 0, 0, 1 } }, |
|||
{ Instruction::COINBASE, { "COINBASE", 0, 0, 1 } }, |
|||
{ Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1 } }, |
|||
{ Instruction::NUMBER, { "NUMBER", 0, 0, 1 } }, |
|||
{ Instruction::DIFFICULTY, { "DIFFICULTY", 0, 0, 1 } }, |
|||
{ Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1 } }, |
|||
{ Instruction::POP, { "POP", 0, 1, 0 } }, |
|||
{ Instruction::MLOAD, { "MLOAD", 0, 1, 1 } }, |
|||
{ Instruction::MSTORE, { "MSTORE", 0, 2, 0 } }, |
|||
{ Instruction::MSTORE8, { "MSTORE8", 0, 2, 0 } }, |
|||
{ Instruction::SLOAD, { "SLOAD", 0, 1, 1 } }, |
|||
{ Instruction::SSTORE, { "SSTORE", 0, 2, 0 } }, |
|||
{ Instruction::JUMP, { "JUMP", 0, 1, 0 } }, |
|||
{ Instruction::JUMPI, { "JUMPI", 0, 2, 0 } }, |
|||
{ Instruction::PC, { "PC", 0, 0, 1 } }, |
|||
{ Instruction::MSIZE, { "MSIZE", 0, 0, 1 } }, |
|||
{ Instruction::GAS, { "GAS", 0, 0, 1 } }, |
|||
{ Instruction::JUMPDEST, { "JUMPDEST", 0, 1, 0 } }, |
|||
{ Instruction::PUSH1, { "PUSH1", 1, 0, 1 } }, |
|||
{ Instruction::PUSH2, { "PUSH2", 2, 0, 1 } }, |
|||
{ Instruction::PUSH3, { "PUSH3", 3, 0, 1 } }, |
|||
{ Instruction::PUSH4, { "PUSH4", 4, 0, 1 } }, |
|||
{ Instruction::PUSH5, { "PUSH5", 5, 0, 1 } }, |
|||
{ Instruction::PUSH6, { "PUSH6", 6, 0, 1 } }, |
|||
{ Instruction::PUSH7, { "PUSH7", 7, 0, 1 } }, |
|||
{ Instruction::PUSH8, { "PUSH8", 8, 0, 1 } }, |
|||
{ Instruction::PUSH9, { "PUSH9", 9, 0, 1 } }, |
|||
{ Instruction::PUSH10, { "PUSH10", 10, 0, 1 } }, |
|||
{ Instruction::PUSH11, { "PUSH11", 11, 0, 1 } }, |
|||
{ Instruction::PUSH12, { "PUSH12", 12, 0, 1 } }, |
|||
{ Instruction::PUSH13, { "PUSH13", 13, 0, 1 } }, |
|||
{ Instruction::PUSH14, { "PUSH14", 14, 0, 1 } }, |
|||
{ Instruction::PUSH15, { "PUSH15", 15, 0, 1 } }, |
|||
{ Instruction::PUSH16, { "PUSH16", 16, 0, 1 } }, |
|||
{ Instruction::PUSH17, { "PUSH17", 17, 0, 1 } }, |
|||
{ Instruction::PUSH18, { "PUSH18", 18, 0, 1 } }, |
|||
{ Instruction::PUSH19, { "PUSH19", 19, 0, 1 } }, |
|||
{ Instruction::PUSH20, { "PUSH20", 20, 0, 1 } }, |
|||
{ Instruction::PUSH21, { "PUSH21", 21, 0, 1 } }, |
|||
{ Instruction::PUSH22, { "PUSH22", 22, 0, 1 } }, |
|||
{ Instruction::PUSH23, { "PUSH23", 23, 0, 1 } }, |
|||
{ Instruction::PUSH24, { "PUSH24", 24, 0, 1 } }, |
|||
{ Instruction::PUSH25, { "PUSH25", 25, 0, 1 } }, |
|||
{ Instruction::PUSH26, { "PUSH26", 26, 0, 1 } }, |
|||
{ Instruction::PUSH27, { "PUSH27", 27, 0, 1 } }, |
|||
{ Instruction::PUSH28, { "PUSH28", 28, 0, 1 } }, |
|||
{ Instruction::PUSH29, { "PUSH29", 29, 0, 1 } }, |
|||
{ Instruction::PUSH30, { "PUSH30", 30, 0, 1 } }, |
|||
{ Instruction::PUSH31, { "PUSH31", 31, 0, 1 } }, |
|||
{ Instruction::PUSH32, { "PUSH32", 32, 0, 1 } }, |
|||
{ Instruction::DUP1, { "DUP1", 0, 1, 2 } }, |
|||
{ Instruction::DUP2, { "DUP2", 0, 2, 3 } }, |
|||
{ Instruction::DUP3, { "DUP3", 0, 3, 4 } }, |
|||
{ Instruction::DUP4, { "DUP4", 0, 4, 5 } }, |
|||
{ Instruction::DUP5, { "DUP5", 0, 5, 6 } }, |
|||
{ Instruction::DUP6, { "DUP6", 0, 6, 7 } }, |
|||
{ Instruction::DUP7, { "DUP7", 0, 7, 8 } }, |
|||
{ Instruction::DUP8, { "DUP8", 0, 8, 9 } }, |
|||
{ Instruction::DUP9, { "DUP9", 0, 9, 10 } }, |
|||
{ Instruction::DUP10, { "DUP10", 0, 10, 11 } }, |
|||
{ Instruction::DUP11, { "DUP11", 0, 11, 12 } }, |
|||
{ Instruction::DUP12, { "DUP12", 0, 12, 13 } }, |
|||
{ Instruction::DUP13, { "DUP13", 0, 13, 14 } }, |
|||
{ Instruction::DUP14, { "DUP14", 0, 14, 15 } }, |
|||
{ Instruction::DUP15, { "DUP15", 0, 15, 16 } }, |
|||
{ Instruction::DUP16, { "DUP16", 0, 16, 17 } }, |
|||
{ Instruction::SWAP1, { "SWAP1", 0, 2, 2 } }, |
|||
{ Instruction::SWAP2, { "SWAP2", 0, 3, 3 } }, |
|||
{ Instruction::SWAP3, { "SWAP3", 0, 4, 4 } }, |
|||
{ Instruction::SWAP4, { "SWAP4", 0, 5, 5 } }, |
|||
{ Instruction::SWAP5, { "SWAP5", 0, 6, 6 } }, |
|||
{ Instruction::SWAP6, { "SWAP6", 0, 7, 7 } }, |
|||
{ Instruction::SWAP7, { "SWAP7", 0, 8, 8 } }, |
|||
{ Instruction::SWAP8, { "SWAP8", 0, 9, 9 } }, |
|||
{ Instruction::SWAP9, { "SWAP9", 0, 10, 10 } }, |
|||
{ Instruction::SWAP10, { "SWAP10", 0, 11, 11 } }, |
|||
{ Instruction::SWAP11, { "SWAP11", 0, 12, 12 } }, |
|||
{ Instruction::SWAP12, { "SWAP12", 0, 13, 13 } }, |
|||
{ Instruction::SWAP13, { "SWAP13", 0, 14, 14 } }, |
|||
{ Instruction::SWAP14, { "SWAP14", 0, 15, 15 } }, |
|||
{ Instruction::SWAP15, { "SWAP15", 0, 16, 16 } }, |
|||
{ Instruction::SWAP16, { "SWAP16", 0, 17, 17 } }, |
|||
{ Instruction::LOG0, { "LOG0", 0, 1, 0 } }, |
|||
{ Instruction::LOG1, { "LOG1", 0, 2, 0 } }, |
|||
{ Instruction::LOG2, { "LOG2", 0, 3, 0 } }, |
|||
{ Instruction::LOG3, { "LOG3", 0, 4, 0 } }, |
|||
{ Instruction::LOG4, { "LOG4", 0, 5, 0 } }, |
|||
{ Instruction::CREATE, { "CREATE", 0, 3, 1 } }, |
|||
{ Instruction::CALL, { "CALL", 0, 7, 1 } }, |
|||
{ Instruction::CALLCODE, { "CALLCODE", 0, 7, 1 } }, |
|||
{ Instruction::RETURN, { "RETURN", 0, 2, 0 } }, |
|||
{ Instruction::SUICIDE, { "SUICIDE", 0, 1, 0} } |
|||
}; |
|||
|
|||
string dev::eth::disassemble(bytes const& _mem) |
|||
{ |
|||
stringstream ret; |
|||
unsigned numerics = 0; |
|||
for (auto it = _mem.begin(); it != _mem.end(); ++it) |
|||
{ |
|||
byte n = *it; |
|||
auto iit = c_instructionInfo.find((Instruction)n); |
|||
if (numerics || iit == c_instructionInfo.end() || (byte)iit->first != n) // not an instruction or expecting an argument...
|
|||
{ |
|||
if (numerics) |
|||
numerics--; |
|||
ret << "0x" << hex << (int)n << " "; |
|||
} |
|||
else |
|||
{ |
|||
auto const& ii = iit->second; |
|||
ret << ii.name << " "; |
|||
numerics = ii.additional; |
|||
} |
|||
} |
|||
return ret.str(); |
|||
} |
|||
|
|||
InstructionInfo dev::eth::instructionInfo(Instruction _inst) |
|||
{ |
|||
try |
|||
{ |
|||
return c_instructionInfo.at(_inst); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cwarn << "<INVALID_INSTRUCTION: " << toString((unsigned)_inst) << ">\n" << boost::current_exception_diagnostic_information(); |
|||
return InstructionInfo({"<INVALID_INSTRUCTION: " + toString((unsigned)_inst) + ">", 0, 0, 0}); |
|||
} |
|||
} |
|||
|
|||
bool dev::eth::isValidInstruction(Instruction _inst) |
|||
{ |
|||
return !!c_instructionInfo.count(_inst); |
|||
} |
File diff suppressed because it is too large
@ -0,0 +1,87 @@ |
|||
/*
|
|||
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/>.
|
|||
*/ |
|||
/**
|
|||
* @author Christian <c@ethdev.com> |
|||
* @date 2014 |
|||
* Utilities for the solidity compiler. |
|||
*/ |
|||
|
|||
#include <utility> |
|||
#include <numeric> |
|||
#include <libsolidity/AST.h> |
|||
#include <libsolidity/Compiler.h> |
|||
|
|||
using namespace std; |
|||
|
|||
namespace dev { |
|||
namespace solidity { |
|||
|
|||
void CompilerContext::addStateVariable(VariableDeclaration const& _declaration) |
|||
{ |
|||
m_stateVariables[&_declaration] = m_stateVariablesSize; |
|||
m_stateVariablesSize += _declaration.getType()->getStorageSize(); |
|||
} |
|||
|
|||
void CompilerContext::initializeLocalVariables(unsigned _numVariables) |
|||
{ |
|||
if (_numVariables > 0) |
|||
{ |
|||
*this << u256(0); |
|||
for (unsigned i = 1; i < _numVariables; ++i) |
|||
*this << eth::Instruction::DUP1; |
|||
m_asm.adjustDeposit(-_numVariables); |
|||
} |
|||
} |
|||
|
|||
bool CompilerContext::isLocalVariable(Declaration const* _declaration) const |
|||
{ |
|||
return std::find(m_localVariables.begin(), m_localVariables.end(), _declaration) != m_localVariables.end(); |
|||
} |
|||
|
|||
eth::AssemblyItem CompilerContext::getFunctionEntryLabel(FunctionDefinition const& _function) const |
|||
{ |
|||
auto res = m_functionEntryLabels.find(&_function); |
|||
if (asserts(res != m_functionEntryLabels.end())) |
|||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Function entry label not found.")); |
|||
return res->second.tag(); |
|||
} |
|||
|
|||
unsigned CompilerContext::getBaseStackOffsetOfVariable(Declaration const& _declaration) const |
|||
{ |
|||
auto res = find(begin(m_localVariables), end(m_localVariables), &_declaration); |
|||
if (asserts(res != m_localVariables.end())) |
|||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Variable not found on stack.")); |
|||
return unsigned(end(m_localVariables) - res - 1); |
|||
} |
|||
|
|||
unsigned CompilerContext::baseToCurrentStackOffset(unsigned _baseOffset) const |
|||
{ |
|||
return _baseOffset + m_asm.deposit(); |
|||
} |
|||
|
|||
u256 CompilerContext::getStorageLocationOfVariable(const Declaration& _declaration) const |
|||
{ |
|||
auto it = m_stateVariables.find(&_declaration); |
|||
if (it == m_stateVariables.end()) |
|||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Variable not found in storage.")); |
|||
return it->second; |
|||
} |
|||
|
|||
|
|||
|
|||
} |
|||
} |
@ -0,0 +1,104 @@ |
|||
/*
|
|||
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/>.
|
|||
*/ |
|||
/**
|
|||
* @author Christian <c@ethdev.com> |
|||
* @date 2014 |
|||
* Utilities for the solidity compiler. |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <ostream> |
|||
#include <libevmcore/Instruction.h> |
|||
#include <libevmcore/Assembly.h> |
|||
#include <libsolidity/Types.h> |
|||
|
|||
namespace dev { |
|||
namespace solidity { |
|||
|
|||
|
|||
/**
|
|||
* Context to be shared by all units that compile the same contract. |
|||
* It stores the generated bytecode and the position of identifiers in memory and on the stack. |
|||
*/ |
|||
class CompilerContext |
|||
{ |
|||
public: |
|||
CompilerContext(): m_stateVariablesSize(0) {} |
|||
|
|||
void addStateVariable(VariableDeclaration const& _declaration); |
|||
void startNewFunction() { m_localVariables.clear(); m_asm.setDeposit(0); } |
|||
void initializeLocalVariables(unsigned _numVariables); |
|||
void addVariable(VariableDeclaration const& _declaration) { m_localVariables.push_back(&_declaration); } |
|||
void addFunction(FunctionDefinition const& _function) { m_functionEntryLabels.insert(std::make_pair(&_function, m_asm.newTag())); } |
|||
|
|||
void adjustStackOffset(int _adjustment) { m_asm.adjustDeposit(_adjustment); } |
|||
|
|||
bool isFunctionDefinition(Declaration const* _declaration) const { return m_functionEntryLabels.count(_declaration); } |
|||
bool isLocalVariable(Declaration const* _declaration) const; |
|||
bool isStateVariable(Declaration const* _declaration) const { return m_stateVariables.count(_declaration); } |
|||
|
|||
eth::AssemblyItem getFunctionEntryLabel(FunctionDefinition const& _function) const; |
|||
/// Returns the distance of the given local variable from the top of the local variable stack.
|
|||
unsigned getBaseStackOffsetOfVariable(Declaration const& _declaration) const; |
|||
/// If supplied by a value returned by @ref getBaseStackOffsetOfVariable(variable), returns
|
|||
/// the distance of that variable from the current top of the stack.
|
|||
unsigned baseToCurrentStackOffset(unsigned _baseOffset) const; |
|||
u256 getStorageLocationOfVariable(Declaration const& _declaration) const; |
|||
|
|||
/// Appends a JUMPI instruction to a new tag and @returns the tag
|
|||
eth::AssemblyItem appendConditionalJump() { return m_asm.appendJumpI().tag(); } |
|||
/// Appends a JUMPI instruction to @a _tag
|
|||
CompilerContext& appendConditionalJumpTo(eth::AssemblyItem const& _tag) { m_asm.appendJumpI(_tag); return *this; } |
|||
/// Appends a JUMP to a new tag and @returns the tag
|
|||
eth::AssemblyItem appendJumpToNew() { return m_asm.appendJump().tag(); } |
|||
/// Appends a JUMP to a tag already on the stack
|
|||
CompilerContext& appendJump() { return *this << eth::Instruction::JUMP; } |
|||
/// Appends a JUMP to a specific tag
|
|||
CompilerContext& appendJumpTo(eth::AssemblyItem const& _tag) { m_asm.appendJump(_tag); return *this; } |
|||
/// Appends pushing of a new tag and @returns the new tag.
|
|||
eth::AssemblyItem pushNewTag() { return m_asm.append(m_asm.newPushTag()).tag(); } |
|||
/// @returns a new tag without pushing any opcodes or data
|
|||
eth::AssemblyItem newTag() { return m_asm.newTag(); } |
|||
/// Adds a subroutine to the code (in the data section) and pushes its size (via a tag)
|
|||
/// on the stack. @returns the assembly item corresponding to the pushed subroutine, i.e. its offset.
|
|||
eth::AssemblyItem addSubroutine(eth::Assembly const& _assembly) { return m_asm.appendSubSize(_assembly); } |
|||
|
|||
/// Append elements to the current instruction list and adjust @a m_stackOffset.
|
|||
CompilerContext& operator<<(eth::AssemblyItem const& _item) { m_asm.append(_item); return *this; } |
|||
CompilerContext& operator<<(eth::Instruction _instruction) { m_asm.append(_instruction); return *this; } |
|||
CompilerContext& operator<<(u256 const& _value) { m_asm.append(_value); return *this; } |
|||
CompilerContext& operator<<(bytes const& _data) { m_asm.append(_data); return *this; } |
|||
|
|||
eth::Assembly const& getAssembly() const { return m_asm; } |
|||
void streamAssembly(std::ostream& _stream) const { _stream << m_asm; } |
|||
bytes getAssembledBytecode(bool _optimize = false) { return m_asm.optimise(_optimize).assemble(); } |
|||
private: |
|||
eth::Assembly m_asm; |
|||
|
|||
/// Size of the state variables, offset of next variable to be added.
|
|||
u256 m_stateVariablesSize; |
|||
/// Storage offsets of state variables
|
|||
std::map<Declaration const*, u256> m_stateVariables; |
|||
/// Offsets of local variables on the stack.
|
|||
std::vector<Declaration const*> m_localVariables; |
|||
/// Labels pointing to the entry points of funcitons.
|
|||
std::map<Declaration const*, eth::AssemblyItem> m_functionEntryLabels; |
|||
}; |
|||
|
|||
} |
|||
} |
@ -0,0 +1,134 @@ |
|||
/*
|
|||
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/>.
|
|||
*/ |
|||
/**
|
|||
* @author Christian <c@ethdev.com> |
|||
* @date 2014 |
|||
* Full-stack compiler that converts a source code string to bytecode. |
|||
*/ |
|||
|
|||
#include <libsolidity/AST.h> |
|||
#include <libsolidity/Scanner.h> |
|||
#include <libsolidity/Parser.h> |
|||
#include <libsolidity/NameAndTypeResolver.h> |
|||
#include <libsolidity/Compiler.h> |
|||
#include <libsolidity/CompilerStack.h> |
|||
|
|||
using namespace std; |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace solidity |
|||
{ |
|||
|
|||
void CompilerStack::setSource(string const& _sourceCode) |
|||
{ |
|||
reset(); |
|||
m_scanner = make_shared<Scanner>(CharStream(_sourceCode)); |
|||
} |
|||
|
|||
void CompilerStack::parse() |
|||
{ |
|||
if (!m_scanner) |
|||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Source not available.")); |
|||
m_contractASTNode = Parser().parse(m_scanner); |
|||
NameAndTypeResolver().resolveNamesAndTypes(*m_contractASTNode); |
|||
m_parseSuccessful = true; |
|||
} |
|||
|
|||
void CompilerStack::parse(string const& _sourceCode) |
|||
{ |
|||
setSource(_sourceCode); |
|||
parse(); |
|||
} |
|||
|
|||
bytes const& CompilerStack::compile(bool _optimize) |
|||
{ |
|||
if (!m_parseSuccessful) |
|||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); |
|||
m_bytecode.clear(); |
|||
m_compiler = make_shared<Compiler>(); |
|||
m_compiler->compileContract(*m_contractASTNode); |
|||
return m_bytecode = m_compiler->getAssembledBytecode(_optimize); |
|||
} |
|||
|
|||
bytes const& CompilerStack::compile(string const& _sourceCode, bool _optimize) |
|||
{ |
|||
parse(_sourceCode); |
|||
return compile(_optimize); |
|||
} |
|||
|
|||
void CompilerStack::streamAssembly(ostream& _outStream) |
|||
{ |
|||
if (!m_compiler || m_bytecode.empty()) |
|||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); |
|||
m_compiler->streamAssembly(_outStream); |
|||
} |
|||
|
|||
string const& CompilerStack::getInterface() |
|||
{ |
|||
if (!m_parseSuccessful) |
|||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); |
|||
if (m_interface.empty()) |
|||
{ |
|||
stringstream interface; |
|||
interface << '['; |
|||
vector<FunctionDefinition const*> exportedFunctions = m_contractASTNode->getInterfaceFunctions(); |
|||
unsigned functionsCount = exportedFunctions.size(); |
|||
for (FunctionDefinition const* f: exportedFunctions) |
|||
{ |
|||
auto streamVariables = [&](vector<ASTPointer<VariableDeclaration>> const& _vars) |
|||
{ |
|||
unsigned varCount = _vars.size(); |
|||
for (ASTPointer<VariableDeclaration> const& var: _vars) |
|||
{ |
|||
interface << "{" |
|||
<< "\"name\":" << escaped(var->getName(), false) << "," |
|||
<< "\"type\":" << escaped(var->getType()->toString(), false) |
|||
<< "}"; |
|||
if (--varCount > 0) |
|||
interface << ","; |
|||
} |
|||
}; |
|||
|
|||
interface << '{' |
|||
<< "\"name\":" << escaped(f->getName(), false) << "," |
|||
<< "\"inputs\":["; |
|||
streamVariables(f->getParameters()); |
|||
interface << "]," |
|||
<< "\"outputs\":["; |
|||
streamVariables(f->getReturnParameters()); |
|||
interface << "]" |
|||
<< "}"; |
|||
if (--functionsCount > 0) |
|||
interface << ","; |
|||
} |
|||
interface << ']'; |
|||
m_interface = interface.str(); |
|||
} |
|||
return m_interface; |
|||
} |
|||
|
|||
bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimize) |
|||
{ |
|||
CompilerStack stack; |
|||
return stack.compile(_sourceCode, _optimize); |
|||
} |
|||
|
|||
|
|||
|
|||
} |
|||
} |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue