Browse Source

Merge branch 'develop' into mk_jsonrpc

Conflicts:
	libqethereum/QEthereum.cpp
	libqethereum/QEthereum.h
cl-refactor
Marek Kotewicz 10 years ago
parent
commit
8ca8ac7e85
  1. 6
      exp/main.cpp
  2. 16
      libdevcore/FixedHash.h
  3. 61
      libdevcrypto/Common.cpp
  4. 20
      libdevcrypto/Common.h
  5. 1
      libethcore/All.h
  6. 20
      libethereum/ExtVM.h
  7. 72
      libethereum/Transaction.cpp
  8. 9
      libethereum/Transaction.h
  9. 35
      libevm/ExtVMFace.h
  10. 5
      libevmface/Instruction.cpp
  11. 3
      libevmface/Instruction.h
  12. 4
      libwhisper/Interface.cpp
  13. 27
      libwhisper/Interface.h
  14. 97
      libwhisper/Message.cpp
  15. 91
      libwhisper/Message.h
  16. 6
      libwhisper/WhisperHost.cpp
  17. 10
      libwhisper/WhisperHost.h
  18. 2
      libwhisper/WhisperPeer.cpp
  19. 14
      stdserv.js
  20. 55
      test/createRandomTest.cpp
  21. 60
      test/vm.cpp
  22. 22
      test/vm.h

6
exp/main.cpp

@ -104,14 +104,14 @@ int main(int argc, char** argv)
ph.connect(remoteHost, remotePort);
/// Only interested in the packet if the lowest bit is 1
auto w = wh->installWatch(MessageFilter(TopicMasks({{Topic("0000000000000000000000000000000000000000000000000000000000000001"), Topic("0000000000000000000000000000000000000000000000000000000000000001")}})));
auto w = wh->installWatch(TopicFilter(TopicMasks({{Topic("0000000000000000000000000000000000000000000000000000000000000001"), Topic("0000000000000000000000000000000000000000000000000000000000000001")}})));
for (int i = 0; ; ++i)
{
wh->sendRaw(RLPStream().append(i * i).out(), Topic(u256(i)), 1000);
wh->sendRaw(RLPStream().append(i * i).out(), Topic(u256(i)));
for (auto i: wh->checkWatch(w))
{
auto p = wh->message(i).payload;
auto p = wh->envelope(i).open().payload();
cnote << "New message:" << RLP(p).toInt<unsigned>();
}
}

16
libdevcore/FixedHash.h

@ -158,6 +158,21 @@ public:
return ret;
}
/// Returns the index of the first bit set to one, or size() * 8 if no bits are set.
inline unsigned firstBitSet() const
{
unsigned ret = 0;
for (auto d: m_data)
if (d)
for (;; ++ret, d <<= 1)
if (d & 0x80)
return ret;
else {}
else
ret += 8;
return ret;
}
private:
std::array<byte, N> m_data; ///< The binary data.
};
@ -193,6 +208,7 @@ inline std::ostream& operator<<(std::ostream& _out, FixedHash<N> const& _h)
}
// Common types of FixedHash.
using h520 = FixedHash<65>;
using h512 = FixedHash<64>;
using h256 = FixedHash<32>;
using h160 = FixedHash<20>;

61
libdevcrypto/Common.cpp

@ -108,3 +108,64 @@ KeyPair KeyPair::fromEncryptedSeed(bytesConstRef _seed, std::string const& _pass
return KeyPair(sha3(aesDecrypt(_seed, _password)));
}
void dev::encrypt(Public _k, bytesConstRef _plain, bytes& _cipher)
{
(void)_k;
_cipher = _plain.toBytes();
}
bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& _plain)
{
(void)_k;
_plain = _cipher.toBytes();
return true;
}
Public dev::recover(Signature _sig, h256 _message)
{
secp256k1_start();
byte pubkey[65];
int pubkeylen = 65;
if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _sig.data(), pubkey, &pubkeylen, 0, (int)_sig[64]))
return Public();
// right160(dev::sha3(bytesConstRef(&(pubkey[1]), 64)));
#if ETH_CRYPTO_TRACE
h256* sig = (h256 const*)_sig.data();
cout << "---- RECOVER -------------------------------" << endl;
cout << "MSG: " << _message << endl;
cout << "R S V: " << sig[0] << " " << sig[1] << " " << (int)(_sig[64] - 27) << "+27" << endl;
cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl;
#endif
return *(Public const*)&(pubkey[1]);
}
inline h256 kFromMessage(h256 _msg, h256 _priv)
{
return _msg ^ _priv;
}
Signature dev::sign(Secret _k, h256 _message)
{
int v = 0;
secp256k1_start();
SignatureStruct ret;
h256 nonce = kFromMessage(_message, _k);
if (!secp256k1_ecdsa_sign_compact(_message.data(), 32, ret.r.data(), _k.data(), nonce.data(), &v))
return Signature();
#if ETH_ADDRESS_DEBUG
cout << "---- SIGN -------------------------------" << endl;
cout << "MSG: " << _message << endl;
cout << "SEC: " << _k << endl;
cout << "NON: " << nonce << endl;
cout << "R S V: " << ret.r << " " << ret.s << " " << v << "+27" << endl;
#endif
ret.v = v;
return *(Signature const*)&ret;
}

20
libdevcrypto/Common.h

@ -37,6 +37,12 @@ using Secret = h256;
/// @NOTE This is not endian-specific; it's just a bunch of bytes.
using Public = h512;
/// A signature: 65 bytes: r: [0, 32), s: [32, 64), v: 64.
/// @NOTE This is not endian-specific; it's just a bunch of bytes.
using Signature = h520;
struct SignatureStruct { h256 r; h256 s; byte v; };
/// An Ethereum address: 20 bytes.
/// @NOTE This is not endian-specific; it's just a bunch of bytes.
using Address = h160;
@ -44,9 +50,17 @@ using Address = h160;
/// A vector of Ethereum addresses.
using Addresses = h160s;
/// Convert a private key into the public key equivalent.
/// @returns 0 if it's not a valid private key.
Address toAddress(h256 _private);
/// A vector of secrets.
using Secrets = h256s;
/// Convert a secret key into the public key equivalent.
/// @returns 0 if it's not a valid secret key.
Address toAddress(Secret _secret);
void encrypt(Public _k, bytesConstRef _plain, bytes& o_cipher);
bool decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plain);
Public recover(Signature _sig, h256 _message);
Signature sign(Secret _k, h256 _message);
/// Simple class that represents a "key pair".
/// All of the data of the class can be regenerated from the secret key (m_secret) alone.

1
libethcore/All.h

@ -3,6 +3,5 @@
#include "BlockInfo.h"
#include "CommonEth.h"
#include "ProofOfWork.h"
#include "CryptoHeaders.h"
#include "Exceptions.h"

20
libethereum/ExtVM.h

@ -46,16 +46,16 @@ public:
}
/// Read storage location.
u256 store(u256 _n) { return m_s.storage(myAddress, _n); }
virtual u256 store(u256 _n) override final { return m_s.storage(myAddress, _n); }
/// Write a value in storage.
void setStore(u256 _n, u256 _v) { m_s.setStorage(myAddress, _n, _v); if (m_ms) m_ms->altered.push_back(_n); }
virtual void setStore(u256 _n, u256 _v) override final { m_s.setStorage(myAddress, _n, _v); if (m_ms) m_ms->altered.push_back(_n); }
/// Read address's code.
bytes const& codeAt(Address _a) { return m_s.code(_a); }
virtual bytes const& codeAt(Address _a) override final { return m_s.code(_a); }
/// Create a new contract.
h160 create(u256 _endowment, u256* _gas, bytesConstRef _code, OnOpFunc const& _onOp = OnOpFunc())
virtual h160 create(u256 _endowment, u256* _gas, bytesConstRef _code, OnOpFunc const& _onOp = OnOpFunc()) override final
{
// Increment associated nonce for sender.
m_s.noteSending(myAddress);
@ -68,7 +68,7 @@ public:
}
/// Create a new message call. Leave _myAddressOverride as the default to use the present address as caller.
bool call(Address _receiveAddress, u256 _txValue, bytesConstRef _txData, u256* _gas, bytesRef _out, OnOpFunc const& _onOp = OnOpFunc(), Address _myAddressOverride = Address(), Address _codeAddressOverride = Address())
virtual bool call(Address _receiveAddress, u256 _txValue, bytesConstRef _txData, u256* _gas, bytesRef _out, OnOpFunc const& _onOp = {}, Address _myAddressOverride = {}, Address _codeAddressOverride = {}) override final
{
if (m_ms)
m_ms->internal.resize(m_ms->internal.size() + 1);
@ -79,16 +79,16 @@ public:
}
/// Read address's balance.
u256 balance(Address _a) { return m_s.balance(_a); }
virtual u256 balance(Address _a) override final { return m_s.balance(_a); }
/// Subtract amount from account's balance.
void subBalance(u256 _a) { m_s.subBalance(myAddress, _a); }
virtual void subBalance(u256 _a) override final { m_s.subBalance(myAddress, _a); }
/// Determine account's TX count.
u256 txCount(Address _a) { return m_s.transactionsFrom(_a); }
virtual u256 txCount(Address _a) override final { return m_s.transactionsFrom(_a); }
/// Suicide the associated contract to the given address.
void suicide(Address _a)
virtual void suicide(Address _a) override final
{
m_s.addBalance(_a, m_s.balance(myAddress));
ExtVMFace::suicide(_a);
@ -96,7 +96,7 @@ public:
/// Revert any changes made (by any of the other calls).
/// @TODO check call site for the parent manifest being discarded.
void revert() { if (m_ms) *m_ms = Manifest(); m_s.m_cache = m_origCache; }
virtual void revert() override final { if (m_ms) *m_ms = Manifest(); m_s.m_cache = m_origCache; }
State& state() const { return m_s; }

72
libethereum/Transaction.cpp

@ -19,9 +19,9 @@
* @date 2014
*/
#include <secp256k1/secp256k1.h>
#include <libdevcore/vector_ref.h>
#include <libdevcore/Log.h>
#include <libdevcrypto/Common.h>
#include <libethcore/Exceptions.h>
#include "Transaction.h"
using namespace std;
@ -42,7 +42,7 @@ Transaction::Transaction(bytesConstRef _rlpData, bool _checkSender)
receiveAddress = rlp[field = 3].toHash<Address>();
value = rlp[field = 4].toInt<u256>();
data = rlp[field = 5].toBytes();
vrs = Signature{ rlp[field = 6].toInt<byte>(), rlp[field = 7].toInt<u256>(), rlp[field = 8].toInt<u256>() };
vrs = SignatureStruct{ rlp[field = 7].toInt<u256>(), rlp[field = 8].toInt<u256>(), byte(rlp[field = 6].toInt<byte>() - 27) };
if (_checkSender)
m_sender = sender();
}
@ -70,53 +70,18 @@ Address Transaction::sender() const
{
if (!m_sender)
{
secp256k1_start();
h256 sig[2] = { vrs.r, vrs.s };
h256 msg = sha3(false);
byte pubkey[65];
int pubkeylen = 65;
if (!secp256k1_ecdsa_recover_compact(msg.data(), 32, sig[0].data(), pubkey, &pubkeylen, 0, (int)vrs.v - 27))
auto p = recover(*(Signature const*)&vrs, sha3(false));
if (!p)
BOOST_THROW_EXCEPTION(InvalidSignature());
// TODO: check right160 is correct and shouldn't be left160.
m_sender = right160(dev::sha3(bytesConstRef(&(pubkey[1]), 64)));
#if ETH_ADDRESS_DEBUG
cout << "---- RECOVER -------------------------------" << endl;
cout << "MSG: " << msg << endl;
cout << "R S V: " << sig[0] << " " << sig[1] << " " << (int)(vrs.v - 27) << "+27" << endl;
cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl;
cout << "ADR: " << m_sender << endl;
#endif
m_sender = right160(dev::sha3(bytesConstRef(p.data(), sizeof(p))));
}
return m_sender;
}
void Transaction::sign(Secret _priv)
{
int v = 0;
secp256k1_start();
h256 msg = sha3(false);
h256 sig[2];
h256 nonce = kFromMessage(msg, _priv);
if (!secp256k1_ecdsa_sign_compact(msg.data(), 32, sig[0].data(), _priv.data(), nonce.data(), &v))
BOOST_THROW_EXCEPTION(InvalidSignature());
#if ETH_ADDRESS_DEBUG
cout << "---- SIGN -------------------------------" << endl;
cout << "MSG: " << msg << endl;
cout << "SEC: " << _priv << endl;
cout << "NON: " << nonce << endl;
cout << "R S V: " << sig[0] << " " << sig[1] << " " << v << "+27" << endl;
#endif
vrs.v = (byte)(v + 27);
vrs.r = (u256)sig[0];
vrs.s = (u256)sig[1];
auto sig = dev::sign(_priv, sha3(false));
vrs = *(SignatureStruct const*)&sig;
}
void Transaction::fillStream(RLPStream& _s, bool _sig) const
@ -129,26 +94,5 @@ void Transaction::fillStream(RLPStream& _s, bool _sig) const
_s << "";
_s << value << data;
if (_sig)
_s << vrs.v << vrs.r << vrs.s;
}
// If the h256 return is an integer, store it in bigendian (i.e. u256 ret; ... return (h256)ret; )
h256 Transaction::kFromMessage(h256 _msg, h256 _priv)
{
// TODO!
// bytes v(32, 1);
// bytes k(32, 0);
/*
v = '\x01' * 32
k = '\x00' * 32
priv = encode_privkey(priv,'bin')
msghash = encode(hash_to_int(msghash),256,32)
k = hmac.new(k, v+'\x00'+priv+msghash, hashlib.sha256).digest()
v = hmac.new(k, v, hashlib.sha256).digest()
k = hmac.new(k, v+'\x01'+priv+msghash, hashlib.sha256).digest()
v = hmac.new(k, v, hashlib.sha256).digest()
return decode(hmac.new(k, v, hashlib.sha256).digest(),256)
*/
return _msg ^ _priv;
_s << (vrs.v + 27) << (u256)vrs.r << (u256)vrs.s;
}

9
libethereum/Transaction.h

@ -30,13 +30,6 @@ namespace dev
namespace eth
{
struct Signature
{
byte v;
u256 r;
u256 s;
};
struct Transaction
{
Transaction() {}
@ -54,7 +47,7 @@ struct Transaction
bytes data; ///< The data associated with the transaction, or the initialiser if it's a creation transaction.
Signature vrs; ///< The signature of the transaction. Encodes the sender.
SignatureStruct vrs; ///< The signature of the transaction. Encodes the sender.
Address safeSender() const noexcept; ///< Like sender() but will never throw.
Address sender() const; ///< Determine the sender of the transaction from the signature (and hash).

35
libevm/ExtVMFace.h

@ -21,7 +21,7 @@
#pragma once
#include <list>
#include <set>
#include <functional>
#include <libdevcore/Common.h>
#include <libevmface/Instruction.h>
@ -45,49 +45,54 @@ struct Post
using OnOpFunc = std::function<void(uint64_t /*steps*/, Instruction /*instr*/, bigint /*newMemSize*/, bigint /*gasCost*/, void/*VM*/*, void/*ExtVM*/ const*)>;
/**
* @brief A null implementation of the class for specifying VM externalities.
* @brief Interface and null implementation of the class for specifying VM externalities.
*/
class ExtVMFace
{
public:
/// Null constructor.
ExtVMFace() {}
ExtVMFace() = default;
/// Full constructor.
ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytesConstRef _code, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, unsigned _depth);
/// Get the code at the given location in code ROM.
byte getCode(u256 _n) const { return _n < code.size() ? code[(unsigned)_n] : 0; }
virtual ~ExtVMFace() = default;
ExtVMFace(ExtVMFace const&) = delete;
void operator=(ExtVMFace) = delete;
/// Read storage location.
u256 store(u256) { return 0; }
virtual u256 store(u256) { return 0; }
/// Write a value in storage.
void setStore(u256, u256) {}
virtual void setStore(u256, u256) {}
/// Read address's balance.
u256 balance(Address) { return 0; }
virtual u256 balance(Address) { return 0; }
/// Read address's code.
bytes const& codeAt(Address) { return NullBytes; }
virtual bytes const& codeAt(Address) { return NullBytes; }
/// Subtract amount from account's balance.
void subBalance(u256) {}
virtual void subBalance(u256) {}
/// Determine account's TX count.
u256 txCount(Address) { return 0; }
virtual u256 txCount(Address) { return 0; }
/// Suicide the associated contract and give proceeds to the given address.
void suicide(Address) { suicides.insert(myAddress); }
virtual void suicide(Address) { suicides.insert(myAddress); }
/// Create a new (contract) account.
h160 create(u256, u256*, bytesConstRef, bytesConstRef) { return h160(); }
virtual h160 create(u256, u256*, bytesConstRef, OnOpFunc const&) { return h160(); }
/// Make a new message call.
bool call(Address, u256, bytesConstRef, u256*, bytesRef, OnOpFunc const&, Address, Address) { return false; }
virtual bool call(Address, u256, bytesConstRef, u256*, bytesRef, OnOpFunc const&, Address, Address) { return false; }
/// Revert any changes made (by any of the other calls).
void revert() {}
virtual void revert() {}
/// Get the code at the given location in code ROM.
byte getCode(u256 _n) const { return _n < code.size() ? code[(size_t)_n] : 0; }
Address myAddress; ///< Address associated with executing code (a contract, or contract-to-be).
Address caller; ///< Address which sent the message (either equal to origin or a contract).

5
libevmface/Instruction.cpp

@ -318,3 +318,8 @@ InstructionInfo dev::eth::instructionInfo(Instruction _inst)
return InstructionInfo({"<INVALID_INSTRUCTION: " + toString((unsigned)_inst) + ">", 0, 0, 0});
}
}
bool dev::eth::isValidInstruction(Instruction _inst)
{
return c_instructionInfo.count(_inst);
}

3
libevmface/Instruction.h

@ -180,6 +180,9 @@ struct InstructionInfo
/// Information on all the instructions.
InstructionInfo instructionInfo(Instruction _inst);
/// check whether instructions exists
bool isValidInstruction(Instruction _inst);
/// Convert from string mnemonic to Instruction type.
extern const std::map<std::string, Instruction> c_instructions;

4
libwhisper/Interface.cpp

@ -34,10 +34,10 @@ using namespace dev::shh;
#endif
#define clogS(X) dev::LogOutputStream<X, true>(false) << "| " << std::setw(2) << session()->socketId() << "] "
bool MessageFilter::matches(Message const& _m) const
bool TopicFilter::matches(Envelope const& _e) const
{
for (TopicMask const& t: m_topicMasks)
if (((t.first ^ _m.topic) & t.second) == 0)
if (((t.first ^ _e.topic()) & t.second) == 0)
return true;
return false;
}

27
libwhisper/Interface.h

@ -46,17 +46,17 @@ namespace shh
using TopicMask = std::pair<Topic, Topic>;
using TopicMasks = std::vector<TopicMask>;
class MessageFilter
class TopicFilter
{
public:
MessageFilter() {}
MessageFilter(TopicMasks const& _m): m_topicMasks(_m) {}
MessageFilter(RLP const& _r): m_topicMasks((TopicMasks)_r) {}
TopicFilter() {}
TopicFilter(TopicMasks const& _m): m_topicMasks(_m) {}
TopicFilter(RLP const& _r): m_topicMasks((TopicMasks)_r) {}
void fillStream(RLPStream& _s) const { _s << m_topicMasks; }
h256 sha3() const { RLPStream s; fillStream(s); return dev::sha3(s.out()); }
bool matches(Message const& _m) const;
bool matches(Envelope const& _m) const;
private:
TopicMasks m_topicMasks;
@ -64,9 +64,9 @@ private:
struct InstalledFilter
{
InstalledFilter(MessageFilter const& _f): filter(_f) {}
InstalledFilter(TopicFilter const& _f): filter(_f) {}
MessageFilter filter;
TopicFilter filter;
unsigned refCount = 1;
};
@ -84,17 +84,20 @@ class Interface
public:
virtual ~Interface() {}
virtual void inject(Message const& _m, WhisperPeer* _from = nullptr) = 0;
virtual void inject(Envelope const& _m, WhisperPeer* _from = nullptr) = 0;
virtual unsigned installWatch(MessageFilter const& _filter) = 0;
virtual unsigned installWatch(TopicFilter const& _filter) = 0;
virtual unsigned installWatch(h256 _filterId) = 0;
virtual void uninstallWatch(unsigned _watchId) = 0;
virtual h256s peekWatch(unsigned _watchId) const = 0;
virtual h256s checkWatch(unsigned _watchId) = 0;
virtual Message message(h256 _m) const = 0;
virtual Envelope envelope(h256 _m) const = 0;
virtual void sendRaw(bytes const& _payload, h256 _topic, unsigned _ttl) = 0;
void sendRaw(bytes const& _payload, Topic _topic, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).seal(_topic, _ttl, _workToProve)); }
void sendRaw(Public _to, bytes const& _payload, Topic _topic, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).seal(_to, _topic, _ttl, _workToProve)); }
void sendRaw(Secret _from, bytes const& _payload, Topic _topic, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).seal(_from, _topic, _ttl, _workToProve)); }
void sendRaw(Secret _from, Public _to, bytes const& _payload, Topic _topic, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).seal(_from, _to, _topic, _ttl, _workToProve)); }
};
struct WatshhChannel: public dev::LogChannel { static const char* name() { return "shh"; } static const int verbosity = 1; };
@ -115,7 +118,7 @@ class Watch: public boost::noncopyable
public:
Watch() {}
Watch(Whisper& _c, h256 _f): m_c(&_c), m_id(_c.installWatch(_f)) {}
Watch(Whisper& _c, MessageFilter const& _tf): m_c(&_c), m_id(_c.installWatch(_tf)) {}
Watch(Whisper& _c, TopicFilter const& _tf): m_c(&_c), m_id(_c.installWatch(_tf)) {}
~Watch() { if (m_c) m_c->uninstallWatch(m_id); }
bool check() { return m_c ? m_c->checkWatch(m_id) : false; }

97
libwhisper/Message.cpp

@ -25,3 +25,100 @@ using namespace std;
using namespace dev;
using namespace dev::p2p;
using namespace dev::shh;
Message::Message(Envelope const& _e, Secret const& _s)
{
try
{
bytes b;
if (_s)
decrypt(_s, &(_e.data()), b);
populate(_s ? b : _e.data());
m_to = KeyPair(_s).pub();
}
catch (...) // Invalid secret? TODO: replace ... with InvalidSecret
{
}
}
void Message::populate(bytes const& _data)
{
if (!_data.size())
return;
byte flags = _data[0];
if (!!(flags & ContainsSignature) && _data.size() > sizeof(Signature) + 1) // has a signature
{
bytesConstRef payload = bytesConstRef(&_data).cropped(sizeof(Signature) + 1);
h256 h = sha3(payload);
m_from = recover(*(Signature const*)&(_data[1]), h);
m_payload = payload.toBytes();
}
else
m_payload = bytesConstRef(&_data).cropped(1).toBytes();
}
Envelope Message::seal(Secret _from, Topic const& _topic, unsigned _ttl, unsigned _workToProve)
{
Envelope ret(time(0) + _ttl, _ttl, _topic);
bytes input(1 + m_payload.size());
input[0] = 0;
memcpy(input.data() + 1, m_payload.data(), m_payload.size());
if (_from) // needs a sig
{
input.resize(1 + m_payload.size() + sizeof(Signature));
input[0] |= ContainsSignature;
*(Signature*)&(input[1 + m_payload.size()]) = sign(_from, sha3(m_payload));
}
if (m_to)
encrypt(m_to, &input, ret.m_data);
else
swap(ret.m_data, input);
ret.proveWork(_workToProve);
return ret;
}
Message Envelope::open(Secret const& _s) const
{
return Message(*this, _s);
}
Message Envelope::open() const
{
return Message(*this);
}
unsigned Envelope::workProved() const
{
h256 d[2];
d[0] = sha3NoNonce();
d[1] = m_nonce;
return dev::sha3(bytesConstRef(d[0].data(), 64)).firstBitSet();
}
void Envelope::proveWork(unsigned _ms)
{
// PoW
h256 d[2];
d[0] = sha3NoNonce();
uint32_t& n = *(uint32_t*)&(d[1][30]);
unsigned bestBitSet = 0;
bytesConstRef chuck(d[0].data(), 64);
chrono::high_resolution_clock::time_point then = chrono::high_resolution_clock::now() + chrono::milliseconds(_ms);
for (n = 0; chrono::high_resolution_clock::now() < then; )
// do it rounds of 1024 for efficiency
for (unsigned i = 0; i < 1024; ++i, ++n)
{
auto fbs = dev::sha3(chuck).firstBitSet();
if (fbs > bestBitSet)
{
bestBitSet = fbs;
m_nonce = n;
}
}
}

91
libwhisper/Message.h

@ -36,27 +36,88 @@ namespace dev
namespace shh
{
struct Message
class Message;
class Envelope
{
unsigned expiry = 0;
unsigned ttl = 0;
Topic topic; // TODO: change to h256
bytes payload;
friend class Message;
Message() {}
Message(unsigned _exp, unsigned _ttl, Topic const& _topic, bytes const& _payload): expiry(_exp), ttl(_ttl), topic(_topic), payload(_payload) {}
Message(RLP const& _m)
public:
Envelope() {}
Envelope(RLP const& _m)
{
expiry = _m[0].toInt<unsigned>();
ttl = _m[1].toInt<unsigned>();
topic = (Topic)_m[2];
payload = _m[3].toBytes();
m_expiry = _m[0].toInt<unsigned>();
m_ttl = _m[1].toInt<unsigned>();
m_topic = (Topic)_m[2];
m_data = _m[3].toBytes();
}
operator bool () const { return !!expiry; }
operator bool() const { return !!m_expiry; }
void streamOut(RLPStream& _s, bool _withNonce) const { _s.appendList(_withNonce ? 5 : 4) << m_expiry << m_ttl << m_topic << m_data; if (_withNonce) _s << m_nonce; }
h256 sha3() const { RLPStream s; streamOut(s, true); return dev::sha3(s.out()); }
h256 sha3NoNonce() const { RLPStream s; streamOut(s, false); return dev::sha3(s.out()); }
unsigned sent() const { return m_expiry - m_ttl; }
unsigned expiry() const { return m_expiry; }
unsigned ttl() const { return m_ttl; }
Topic const& topic() const { return m_topic; }
bytes const& data() const { return m_data; }
Message open(Secret const& _s) const;
Message open() const;
unsigned workProved() const;
void proveWork(unsigned _ms);
private:
Envelope(unsigned _exp, unsigned _ttl, Topic const& _topic): m_expiry(_exp), m_ttl(_ttl), m_topic(_topic) {}
unsigned m_expiry = 0;
unsigned m_ttl = 0;
u256 m_nonce;
Topic m_topic;
bytes m_data;
};
enum /*Message Flags*/
{
ContainsSignature = 0
};
/// An (unencrypted) message, constructed from the combination of an Envelope, and, potentially,
/// a Secret key to decrypt the Message.
class Message
{
public:
Message() {}
Message(Envelope const& _e, Secret const& _s = Secret());
Message(bytes const& _payload): m_payload(_payload) {}
Message(bytesConstRef _payload): m_payload(_payload.toBytes()) {}
Message(bytes&& _payload) { std::swap(_payload, m_payload); }
Public from() const { return m_from; }
Public to() const { return m_to; }
bytes const& payload() const { return m_payload; }
void setTo(Public _to) { m_to = _to; }
operator bool() const { return !!m_payload.size() || m_from || m_to; }
/// Turn this message into a ditributable Envelope.
Envelope seal(Secret _from, Topic const& _topic, unsigned _workToProve = 50, unsigned _ttl = 50);
// Overloads for skipping _from or specifying _to.
Envelope seal(Topic const& _topic, unsigned _ttl = 50, unsigned _workToProve = 50) { return seal(Secret(), _topic, _workToProve, _ttl); }
Envelope seal(Public _to, Topic const& _topic, unsigned _workToProve = 50, unsigned _ttl = 50) { m_to = _to; return seal(Secret(), _topic, _workToProve, _ttl); }
Envelope seal(Secret _from, Public _to, Topic const& _topic, unsigned _workToProve = 50, unsigned _ttl = 50) { m_to = _to; return seal(_from, _topic, _workToProve, _ttl); }
private:
void populate(bytes const& _data);
void streamOut(RLPStream& _s) const { _s.appendList(4) << expiry << ttl << topic << payload; }
h256 sha3() const { RLPStream s; streamOut(s); return dev::sha3(s.out()); }
Public m_from;
Public m_to;
bytes m_payload;
};
}

6
libwhisper/WhisperHost.cpp

@ -47,11 +47,11 @@ void WhisperHost::streamMessage(h256 _m, RLPStream& _s) const
if (m_messages.count(_m))
{
UpgradeGuard ll(l);
m_messages.at(_m).streamOut(_s);
m_messages.at(_m).streamOut(_s, true);
}
}
void WhisperHost::inject(Message const& _m, WhisperPeer* _p)
void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p)
{
auto h = _m.sha3();
{
@ -95,7 +95,7 @@ unsigned WhisperHost::installWatch(h256 _h)
return ret;
}
unsigned WhisperHost::installWatch(shh::MessageFilter const& _f)
unsigned WhisperHost::installWatch(shh::TopicFilter const& _f)
{
Guard l(m_filterLock);

10
libwhisper/WhisperHost.h

@ -48,17 +48,15 @@ public:
unsigned protocolVersion() const { return 0; }
virtual void inject(Message const& _m, WhisperPeer* _from = nullptr);
virtual void inject(Envelope const& _e, WhisperPeer* _from = nullptr);
virtual unsigned installWatch(MessageFilter const& _filter);
virtual unsigned installWatch(TopicFilter const& _filter);
virtual unsigned installWatch(h256 _filterId);
virtual void uninstallWatch(unsigned _watchId);
virtual h256s peekWatch(unsigned _watchId) const { dev::Guard l(m_filterLock); try { return m_watches.at(_watchId).changes; } catch (...) { return h256s(); } }
virtual h256s checkWatch(unsigned _watchId) { dev::Guard l(m_filterLock); h256s ret; try { ret = m_watches.at(_watchId).changes; m_watches.at(_watchId).changes.clear(); } catch (...) {} return ret; }
virtual Message message(h256 _m) const { try { dev::ReadGuard l(x_messages); return m_messages.at(_m); } catch (...) { return Message(); } }
virtual void sendRaw(bytes const& _payload, Topic _topic, unsigned _ttl) { inject(Message(time(0) + _ttl, _ttl, _topic, _payload)); }
virtual Envelope envelope(h256 _m) const { try { dev::ReadGuard l(x_messages); return m_messages.at(_m); } catch (...) { return Envelope(); } }
private:
void streamMessage(h256 _m, RLPStream& _s) const;
@ -66,7 +64,7 @@ private:
void noteChanged(h256 _messageHash, h256 _filter);
mutable dev::SharedMutex x_messages;
std::map<h256, Message> m_messages;
std::map<h256, Envelope> m_messages;
mutable dev::Mutex m_filterLock;
std::map<h256, InstalledFilter> m_filters;

2
libwhisper/WhisperPeer.cpp

@ -71,7 +71,7 @@ bool WhisperPeer::interpret(unsigned _id, RLP const& _r)
unsigned n = 0;
for (auto i: _r)
if (n++)
host()->inject(Message(i), this);
host()->inject(Envelope(i), this);
sendMessages();
break;
}

14
stdserv.js

@ -1,3 +1,5 @@
eth = web3.eth;
env.note('Creating Config...')
var configCode = eth.lll("
{
@ -277,25 +279,25 @@ eth.transact({ 'to': config, 'data': ['3', exchange] });
env.note('Register my name...')
eth.transact({ 'to': nameReg, 'data': [ eth.fromAscii('register'), eth.fromAscii('Gav') ] });
eth.transact({ 'to': nameReg, 'data': [ web3.fromAscii('register'), web3.fromAscii('Gav') ] });
env.note('Dole out ETH to other address...')
eth.transact({ 'value': '100000000000000000000', 'to': eth.accounts[1] });
env.note('Register my other name...')
eth.transact({ 'from': eth.keys[1], 'to': nameReg, 'data': [ eth.fromAscii('register'), eth.fromAscii("Gav Would") ] });
eth.transact({ 'from': eth.keys[1], 'to': nameReg, 'data': [ web3.fromAscii('register'), web3.fromAscii("Gav Would") ] });
env.note('Approve Exchange...')
eth.transact({ 'to': gavCoin, 'data': [ eth.fromAscii('approve'), exchange ] });
eth.transact({ 'to': gavCoin, 'data': [ web3.fromAscii('approve'), exchange ] });
env.note('Approve Exchange on other address...')
eth.transact({ 'from': eth.keys[1], 'to': gavCoin, 'data': [ eth.fromAscii('approve'), exchange ] });
eth.transact({ 'from': eth.keys[1], 'to': gavCoin, 'data': [ web3.fromAscii('approve'), exchange ] });
env.note('Make offer 5000GAV/5ETH...')
eth.transact({ 'to': exchange, 'data': [eth.fromAscii('new'), gavCoin, '5000', '0', '5000000000000000000'] });
eth.transact({ 'to': exchange, 'data': [web3.fromAscii('new'), gavCoin, '5000', '0', '5000000000000000000'] });
env.note('Register gav.eth...')
eth.transact({ 'to': dnsReg, 'data': [eth.fromAscii('register'), eth.fromAscii('gav'), eth.fromAscii('opensecrecy.com')] });
eth.transact({ 'to': dnsReg, 'data': [web3.fromAscii('register'), web3.fromAscii('gav'), web3.fromAscii('opensecrecy.com')] });
env.note('All done.')

55
test/createRandomTest.cpp

@ -42,11 +42,7 @@ void doMyTests(json_spirit::mValue& v);
int main(int argc, char *argv[])
{
if (argc != 2)
{
cout << "usage: createRandomTest <filename>\n";
return 0;
}
g_logVerbosity = 0;
// create random code
@ -64,14 +60,48 @@ int main(int argc, char *argv[])
string randomCode;
for (int i = 0; i < lengthOfCode; ++i)
randomCode += toHex(toCompactBigEndian(randGen()));
{
uint8_t opcode = randGen();
// disregard all invalid commands, except of one (0x10)
if (dev::eth::isValidInstruction(dev::eth::Instruction(opcode)) || opcode == 0x10)
randomCode += toHex(toCompactBigEndian(opcode));
else
i--;
}
// read template test file
const string s =\
"{\n\
\"randomVMtest\": {\n\
\"env\" : {\n\
\"previousHash\" : \"5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6\",\n\
\"currentNumber\" : \"0\",\n\
\"currentGasLimit\" : \"1000000\",\n\
\"currentDifficulty\" : \"256\",\n\
\"currentTimestamp\" : 1,\n\
\"currentCoinbase\" : \"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba\"\n\
},\n\
\"pre\" : {\n\
\"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6\" : {\n\
\"balance\" : \"1000000000000000000\",\n\
\"nonce\" : 0,\n\
\"code\" : \"random\",\n\
\"storage\": {}\n\
}\n\
},\n\
\"exec\" : {\n\
\"address\" : \"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6\",\n\
\"origin\" : \"cd1722f3947def4cf144679da39c4c32bdc35681\",\n\
\"caller\" : \"cd1722f3947def4cf144679da39c4c32bdc35681\",\n\
\"value\" : \"1000000000000000000\",\n\
\"data\" : \"\",\n\
\"gasPrice\" : \"100000000000000\",\n\
\"gas\" : \"10000\"\n\
}\n\
}\n\
}";
mValue v;
boost::filesystem::path p(__FILE__);
boost::filesystem::path dir = p.parent_path();
string s = asString(contents(dir.string() + "/randomTestFiller.json"));
read_string(s, v);
// insert new random code
@ -80,9 +110,8 @@ int main(int argc, char *argv[])
// execute code in vm
doMyTests(v);
// write new test
string filename = argv[1];
writeFile(filename, asBytes(json_spirit::write_string(v, true)));
// stream to output for further handling by the bash script
cout << json_spirit::write_string(v, true);
return 0;
}

60
test/vm.cpp

@ -35,7 +35,7 @@ using namespace dev::test;
FakeExtVM::FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth): /// TODO: XXX: remove the default argument & fix.
ExtVMFace(Address(), Address(), Address(), 0, 1, bytesConstRef(), bytesConstRef(), _previousBlock, _currentBlock, _depth) {}
h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFunc)
h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFunc const&)
{
Transaction t;
t.value = _endowment;
@ -45,7 +45,7 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun
m_s.noteSending(myAddress);
m_ms.internal.resize(m_ms.internal.size() + 1);
auto ret = m_s.create(myAddress, _endowment, gasPrice, _gas, _init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, OnOpFunc(), 1);
auto ret = m_s.create(myAddress, _endowment, gasPrice, _gas, _init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1);
if (!m_ms.internal.back().from)
m_ms.internal.pop_back();
@ -61,7 +61,7 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun
return ret;
}
bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc, Address _myAddressOverride = Address(), Address _codeAddressOverride = Address())
bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride, Address _codeAddressOverride)
{
u256 contractgas = 0xffff;
@ -91,7 +91,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data,
if (!m_s.addresses().count(myAddress))
{
m_ms.internal.resize(m_ms.internal.size() + 1);
auto na = m_s.createNewAddress(myAddress, myAddress, balance(myAddress), gasPrice, &contractgas, init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, OnOpFunc(), 1);
auto na = m_s.createNewAddress(myAddress, myAddress, balance(myAddress), gasPrice, &contractgas, init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1);
if (!m_ms.internal.back().from)
m_ms.internal.pop_back();
if (na != myAddress)
@ -512,12 +512,10 @@ void doTests(json_spirit::mValue& v, bool _fillin)
}
bytes output;
u256 gas;
VM vm(fev.gas);
try
{
VM vm(fev.gas);
output = vm.go(fev).toVector();
gas = vm.gas(); // Get the remaining gas
}
catch (Exception const& _e)
{
@ -554,7 +552,7 @@ void doTests(json_spirit::mValue& v, bool _fillin)
o["post"] = mValue(fev.exportState());
o["callcreates"] = fev.exportCallCreates();
o["out"] = "0x" + toHex(output);
fev.push(o, "gas", gas);
fev.push(o, "gas", vm.gas());
}
else
{
@ -578,8 +576,44 @@ void doTests(json_spirit::mValue& v, bool _fillin)
else
BOOST_CHECK(output == fromHex(o["out"].get_str()));
BOOST_CHECK(test.toInt(o["gas"]) == gas);
BOOST_CHECK(test.addresses == fev.addresses);
BOOST_CHECK_EQUAL(test.toInt(o["gas"]), vm.gas());
auto& expectedAddrs = test.addresses;
auto& resultAddrs = fev.addresses;
for (auto&& expectedPair : expectedAddrs)
{
auto& expectedAddr = expectedPair.first;
auto resultAddrIt = resultAddrs.find(expectedAddr);
if (resultAddrIt == resultAddrs.end())
BOOST_ERROR("Missing expected address " << expectedAddr);
else
{
auto& expectedState = expectedPair.second;
auto& resultState = resultAddrIt->second;
BOOST_CHECK_MESSAGE(std::get<0>(expectedState) == std::get<0>(resultState), expectedAddr << ": incorrect balance " << std::get<0>(resultState) << ", expected " << std::get<0>(expectedState));
BOOST_CHECK_MESSAGE(std::get<1>(expectedState) == std::get<1>(resultState), expectedAddr << ": incorrect txCount " << std::get<1>(resultState) << ", expected " << std::get<1>(expectedState));
BOOST_CHECK_MESSAGE(std::get<3>(expectedState) == std::get<3>(resultState), expectedAddr << ": incorrect code");
auto&& expectedStore = std::get<2>(expectedState);
auto&& resultStore = std::get<2>(resultState);
for (auto&& expectedStorePair : expectedStore)
{
auto& expectedStoreKey = expectedStorePair.first;
auto resultStoreIt = resultStore.find(expectedStoreKey);
if (resultStoreIt == resultStore.end())
BOOST_ERROR(expectedAddr << ": missing store key " << expectedStoreKey);
else
{
auto& expectedStoreValue = expectedStorePair.second;
auto& resultStoreValue = resultStoreIt->second;
BOOST_CHECK_MESSAGE(expectedStoreValue == resultStoreValue, expectedAddr << ": store[" << expectedStoreKey << "] = " << resultStoreValue << ", expected " << expectedStoreValue);
}
}
}
}
BOOST_CHECK(test.addresses == fev.addresses); // Just to make sure nothing missed
BOOST_CHECK(test.callcreates == fev.callcreates);
}
}
@ -621,11 +655,13 @@ void executeTests(const string& _name)
if (ptestPath == NULL)
{
cnote << " could not find environment variable ETHEREUM_TEST_PATH \n";
testPath = "../../../tests/vmtests";
testPath = "../../../tests";
}
else
testPath = ptestPath;
testPath += "/vmtests";
#ifdef FILL_TESTS
try
{
@ -654,7 +690,7 @@ void executeTests(const string& _name)
cnote << "Testing VM..." << _name;
json_spirit::mValue v;
string s = asString(contents(testPath + "/" + _name + ".json"));
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?");
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + testPath + "/" + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?");
json_spirit::read_string(s, v);
dev::test::doTests(v, false);
}

22
test/vm.h

@ -44,24 +44,24 @@ class FakeState: public eth::State
{
public:
/// Execute a contract-creation transaction.
h160 createNewAddress(Address _newAddress, Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _originAddress = Address(), std::set<Address>* o_suicides = nullptr, eth::Manifest* o_ms = nullptr, eth::OnOpFunc const& _onOp = eth::OnOpFunc(), unsigned _level = 0);
h160 createNewAddress(Address _newAddress, Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _originAddress = {}, std::set<Address>* o_suicides = nullptr, eth::Manifest* o_ms = nullptr, eth::OnOpFunc const& _onOp = {}, unsigned _level = 0);
};
class FakeExtVM: public eth::ExtVMFace
{
public:
FakeExtVM() {}
FakeExtVM() = default;
FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth = 0);
u256 store(u256 _n) { return std::get<2>(addresses[myAddress])[_n]; }
void setStore(u256 _n, u256 _v) { std::get<2>(addresses[myAddress])[_n] = _v; }
u256 balance(Address _a) { return std::get<0>(addresses[_a]); }
void subBalance(u256 _a) { std::get<0>(addresses[myAddress]) -= _a; }
u256 txCount(Address _a) { return std::get<1>(addresses[_a]); }
void suicide(Address _a) { std::get<0>(addresses[_a]) += std::get<0>(addresses[myAddress]); addresses.erase(myAddress); }
bytes const& codeAt(Address _a) { return std::get<3>(addresses[_a]); }
h160 create(u256 _endowment, u256* _gas, bytesConstRef _init, eth::OnOpFunc);
bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, eth::OnOpFunc, Address, Address);
virtual u256 store(u256 _n) override { return std::get<2>(addresses[myAddress])[_n]; }
virtual void setStore(u256 _n, u256 _v) override { std::get<2>(addresses[myAddress])[_n] = _v; }
virtual u256 balance(Address _a) override { return std::get<0>(addresses[_a]); }
virtual void subBalance(u256 _a) override { std::get<0>(addresses[myAddress]) -= _a; }
virtual u256 txCount(Address _a) override { return std::get<1>(addresses[_a]); }
virtual void suicide(Address _a) override { std::get<0>(addresses[_a]) += std::get<0>(addresses[myAddress]); addresses.erase(myAddress); }
virtual bytes const& codeAt(Address _a) override { return std::get<3>(addresses[_a]); }
virtual h160 create(u256 _endowment, u256* _gas, bytesConstRef _init, eth::OnOpFunc const&) override;
virtual bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, eth::OnOpFunc const&, Address, Address) override;
void setTransaction(Address _caller, u256 _value, u256 _gasPrice, bytes const& _data);
void setContract(Address _myAddress, u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage, bytes const& _code);
void set(Address _a, u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage, bytes const& _code);

Loading…
Cancel
Save