Browse Source

Move to semi-official new Trie format.

cl-refactor
Gav Wood 11 years ago
parent
commit
155cf04efe
  1. 10
      eth/CMakeLists.txt
  2. 11
      libethereum/BlockChain.cpp
  3. 20
      libethereum/BlockInfo.cpp
  4. 4
      libethereum/BlockInfo.h
  5. 5
      libethereum/CMakeLists.txt
  6. 47
      libethereum/Common.cpp
  7. 9
      libethereum/Common.h
  8. 21
      libethereum/State.cpp
  9. 3
      libethereum/State.h
  10. 6
      libethereum/Transaction.cpp
  11. 5
      libethereum/Transaction.h
  12. 120
      libethereum/Trie.cpp
  13. 3
      libethereum/Trie.h
  14. 4
      libethereum/vector_ref.h
  15. 8
      test/CMakeLists.txt
  16. 37
      test/main.cpp

10
eth/CMakeLists.txt

@ -1,13 +1,19 @@
cmake_policy(SET CMP0015 NEW) cmake_policy(SET CMP0015 NEW)
aux_source_directory(. SRC_LIST) aux_source_directory(. SRC_LIST)
include_directories(../../secp256k1/include) include_directories(../../secp256k1/include)
link_directories(../../secp256k1)
include_directories(../../cryptopp562)
link_directories(../../cryptopp562)
include_directories(../libethereum) include_directories(../libethereum)
link_directories(../libethereum) link_directories(../libethereum)
link_directories(../../secp256k1)
add_executable(eth ${SRC_LIST}) add_executable(eth ${SRC_LIST})
target_link_libraries(eth secp256k1)
target_link_libraries(eth ethereum) target_link_libraries(eth ethereum)
target_link_libraries(eth secp256k1)
target_link_libraries(eth cryptopp)
target_link_libraries(eth gmp) target_link_libraries(eth gmp)

11
libethereum/BlockChain.cpp

@ -41,8 +41,11 @@ void BlockChain::import(bytes const& _block)
BlockInfo bi; BlockInfo bi;
try try
{ {
bi.populate(_block, 0); // VERIFY: populates from the block and checks the block is internally coherent.
auto newHash = sha256(_block); bi.populate(&_block);
bi.verifyInternals(&_block);
auto newHash = eth::sha3(_block);
// Check block doesn't already exist first! // Check block doesn't already exist first!
if (m_numberAndParent.count(newHash)) if (m_numberAndParent.count(newHash))
@ -55,6 +58,10 @@ void BlockChain::import(bytes const& _block)
return; return;
bi.number = it->second.first + 1; bi.number = it->second.first + 1;
// CHECK ANCESTRY:
// TODO: check timestamp is after previous timestamp.
// TODO: check difficulty is correct given the two timestamps.
// Insert into DB // Insert into DB
m_numberAndParent[newHash] = make_pair(bi.number, bi.parentHash); m_numberAndParent[newHash] = make_pair(bi.number, bi.parentHash);
m_children.insert(make_pair(bi.parentHash, newHash)); m_children.insert(make_pair(bi.parentHash, newHash));

20
libethereum/BlockInfo.cpp

@ -20,7 +20,6 @@
*/ */
#include "Common.h" #include "Common.h"
#include "sha256.h"
#include "Exceptions.h" #include "Exceptions.h"
#include "RLP.h" #include "RLP.h"
#include "BlockInfo.h" #include "BlockInfo.h"
@ -37,8 +36,8 @@ BlockInfo::BlockInfo()
bytes BlockInfo::createGenesisBlock() bytes BlockInfo::createGenesisBlock()
{ {
RLPStream block(3); RLPStream block(3);
auto sha256EmptyList = sha256(RLPEmptyList); auto sha256EmptyList = sha3(RLPEmptyList);
block.appendList(7) << (uint)0 << sha256EmptyList << (uint)0 << sha256EmptyList << (uint)0 << (uint)0 << (uint)0; block.appendList(7) << (uint)0 << sha256EmptyList << (uint)0 << sha256EmptyList << ((uint)1 << 36) << (uint)0 << (uint)0;
block.appendRaw(RLPEmptyList); block.appendRaw(RLPEmptyList);
block.appendRaw(RLPEmptyList); block.appendRaw(RLPEmptyList);
return block.out(); return block.out();
@ -58,7 +57,7 @@ void BlockInfo::populate(bytesConstRef _block, u256 _number)
try try
{ {
RLP header = root[0]; RLP header = root[0];
hash = eth::sha256(_block); hash = eth::sha3(_block);
parentHash = header[0].toInt<u256>(); parentHash = header[0].toInt<u256>();
sha256Uncles = header[1].toInt<u256>(); sha256Uncles = header[1].toInt<u256>();
coinbaseAddress = header[2].toInt<u160>(); coinbaseAddress = header[2].toInt<u160>();
@ -73,23 +72,16 @@ void BlockInfo::populate(bytesConstRef _block, u256 _number)
} }
} }
void BlockInfo::verify(bytesConstRef _block, u256 _number, u256 _parentHash) void BlockInfo::verifyInternals(bytesConstRef _block)
{ {
populate(_block, _number);
RLP root(_block); RLP root(_block);
if (root[0][0].toInt<u256>() != _parentHash)
throw InvalidParentHash();
if (sha256Transactions != sha256(root[1].data())) if (sha256Transactions != sha3(root[1].data()))
throw InvalidTransactionsHash(); throw InvalidTransactionsHash();
if (sha256Uncles != sha256(root[2].data())) if (sha256Uncles != sha3(root[2].data()))
throw InvalidUnclesHash(); throw InvalidUnclesHash();
// TODO: check timestamp after previous timestamp.
// TODO: check parent's hash
// TODO: check difficulty against timestamp. // TODO: check difficulty against timestamp.
// TODO: check proof of work. // TODO: check proof of work.

4
libethereum/BlockInfo.h

@ -46,8 +46,8 @@ public:
bool operator==(BlockInfo const& _cmp) const { return hash == _cmp.hash && parentHash == _cmp.parentHash && nonce == _cmp.nonce && number == _cmp.number; } bool operator==(BlockInfo const& _cmp) const { return hash == _cmp.hash && parentHash == _cmp.parentHash && nonce == _cmp.nonce && number == _cmp.number; }
static BlockInfo const& genesis() { if (!s_genesis) (s_genesis = new BlockInfo)->populateGenesis(); return *s_genesis; } static BlockInfo const& genesis() { if (!s_genesis) (s_genesis = new BlockInfo)->populateGenesis(); return *s_genesis; }
void populate(bytesConstRef _block, u256 _number); void populate(bytesConstRef _block, u256 _number = 0);
void verify(bytesConstRef _block, u256 _number, u256 _parentHash); void verifyInternals(bytesConstRef _block);
static bytes createGenesisBlock(); static bytes createGenesisBlock();

5
libethereum/CMakeLists.txt

@ -2,8 +2,13 @@ cmake_policy(SET CMP0015 NEW)
include_directories(../../secp256k1/include) include_directories(../../secp256k1/include)
link_directories(../../secp256k1) link_directories(../../secp256k1)
include_directories(../../cryptopp562)
link_directories(../../cryptopp562)
aux_source_directory(. SRC_LIST) aux_source_directory(. SRC_LIST)
add_library(ethereum ${SRC_LIST}) add_library(ethereum ${SRC_LIST})
target_link_libraries(ethereum secp256k1) target_link_libraries(ethereum secp256k1)
target_link_libraries(ethereum cryptopp)
target_link_libraries(ethereum gmp) target_link_libraries(ethereum gmp)

47
libethereum/Common.cpp

@ -19,6 +19,7 @@
* @date 2014 * @date 2014
*/ */
#include <sha3.h>
#include <random> #include <random>
#include "Common.h" #include "Common.h"
#include "Exceptions.h" #include "Exceptions.h"
@ -26,6 +27,8 @@
using namespace std; using namespace std;
using namespace eth; using namespace eth;
std::string eth::escaped(std::string const& _s, bool _all) std::string eth::escaped(std::string const& _s, bool _all)
{ {
std::string ret; std::string ret;
@ -149,3 +152,47 @@ u160 eth::ripemd160(bytesConstRef _message)
ret = (ret << 8) | hashcode[i]; ret = (ret << 8) | hashcode[i];
return ret; return ret;
} }
std::string eth::sha3(std::string const& _input, bool _hex)
{
if (!_hex)
{
string ret(32, '\0');
CryptoPP::SHA3_256 ctx;
ctx.Update( (unsigned char*)_input.c_str(), _input.length());
ctx.Final((byte*)ret.data());
return ret;
}
CryptoPP::SHA3_256 ctx;
ctx.Update( (unsigned char*)_input.c_str(), _input.length());
unsigned char digest[32];
ctx.Final(digest);
std::string ret(64, '\0');
for (unsigned int i = 0; i < 32; i++)
sprintf((char*)(ret.data())+i*2, "%02x", digest[i]);
return ret;
}
bytes eth::sha3Bytes(bytesConstRef _input)
{
CryptoPP::SHA3_256 ctx;
ctx.Update((byte*)_input.data(), _input.size());
bytes ret(32);
ctx.Final(ret.data());
return ret;
}
u256 eth::sha3(bytesConstRef _input)
{
CryptoPP::SHA3_256 ctx;
ctx.Update(_input.data(), _input.size());
uint8_t buf[32];
ctx.Final(buf);
u256 ret = 0;
for (unsigned i = 0; i < 32; ++i)
ret = (ret << 8) | buf[i];
return ret;
}

9
libethereum/Common.h

@ -228,4 +228,13 @@ inline std::vector<_T> operator+(std::vector<typename std::enable_if<std::is_pod
/// Calculate RIPEMD-160 hash of the given message. /// Calculate RIPEMD-160 hash of the given message.
u160 ripemd160(bytesConstRef _message); u160 ripemd160(bytesConstRef _message);
std::string sha3(std::string const& _input, bool _hex);
bytes sha3Bytes(bytesConstRef _input);
inline bytes sha3Bytes(std::string const& _input) { return sha3Bytes((std::string*)&_input); }
inline bytes sha3Bytes(bytes const& _input) { return sha3Bytes((bytes*)&_input); }
u256 sha3(bytesConstRef _input);
inline u256 sha3(bytes const& _input) { return sha3(bytesConstRef((bytes*)&_input)); }
} }

21
libethereum/State.cpp

@ -21,11 +21,11 @@
#include <secp256k1.h> #include <secp256k1.h>
#include <random> #include <random>
#include "sha256.h"
#include "Trie.h" #include "Trie.h"
#include "BlockChain.h" #include "BlockChain.h"
#include "Instruction.h" #include "Instruction.h"
#include "Exceptions.h" #include "Exceptions.h"
#include "sha256.h"
#include "State.h" #include "State.h"
using namespace std; using namespace std;
using namespace eth; using namespace eth;
@ -50,7 +50,8 @@ void State::sync(BlockChain const& _bc, TransactionQueue const& _tq)
BlockInfo bi; BlockInfo bi;
try try
{ {
bi.verify(_bc.lastBlock(), _bc.lastBlockNumber()); bi.populate(_bc.lastBlock(), _bc.lastBlockNumber());
bi.verifyInternals(_bc.lastBlock());
} }
catch (...) catch (...)
{ {
@ -140,20 +141,6 @@ u256 State::contractMemory(Address _contract, u256 _memory) const
return i == m->second.memory().end() ? 0 : i->second; return i == m->second.memory().end() ? 0 : i->second;
} }
bool State::verify(bytes const& _block, uint _number)
{
BlockInfo bi;
try
{
bi.verify(bytesConstRef((bytes*)&_block), _number);
}
catch (...)
{
return false;
}
return true;
}
void State::execute(Transaction const& _t, Address _sender) void State::execute(Transaction const& _t, Address _sender)
{ {
// Entry point for a contract-originated transaction. // Entry point for a contract-originated transaction.
@ -186,7 +173,7 @@ void State::execute(Transaction const& _t, Address _sender)
if (_t.fee < _t.data.size() * c_memoryFee + c_newContractFee) if (_t.fee < _t.data.size() * c_memoryFee + c_newContractFee)
throw FeeTooSmall(); throw FeeTooSmall();
Address newAddress = low160(_t.sha256()); Address newAddress = low160(_t.sha3());
if (isContractAddress(newAddress)) if (isContractAddress(newAddress))
throw ContractAddressCollision(); throw ContractAddressCollision();

3
libethereum/State.h

@ -49,9 +49,6 @@ public:
/// Construct state object. /// Construct state object.
explicit State(Address _minerAddress); explicit State(Address _minerAddress);
/// Verify a given block.
bool verify(bytes const& _block, uint _number = 0);
/// Attempt to find valid nonce for block that this state represents. /// Attempt to find valid nonce for block that this state represents.
/// @param _msTimeout Timeout before return in milliseconds. /// @param _msTimeout Timeout before return in milliseconds.
/// @returns true if it got lucky. /// @returns true if it got lucky.

6
libethereum/Transaction.cpp

@ -44,20 +44,20 @@ Address Transaction::sender() const
bytes sig = toBigEndian(vrs.r) + toBigEndian(vrs.s); bytes sig = toBigEndian(vrs.r) + toBigEndian(vrs.s);
assert(sig.size() == 64); assert(sig.size() == 64);
bytes msg = sha256Bytes(false); bytes msg = sha3Bytes(false);
byte pubkey[65]; byte pubkey[65];
int pubkeylen = 65; int pubkeylen = 65;
if (!secp256k1_ecdsa_recover_compact(msg.data(), msg.size(), sig.data(), pubkey, &pubkeylen, 0, (int)vrs.v - 27)) if (!secp256k1_ecdsa_recover_compact(msg.data(), msg.size(), sig.data(), pubkey, &pubkeylen, 0, (int)vrs.v - 27))
throw InvalidSignature(); throw InvalidSignature();
return low160(eth::sha256(bytesConstRef(&(pubkey[1]), 64))); return low160(eth::sha3(bytesConstRef(&(pubkey[1]), 64)));
} }
void Transaction::sign(PrivateKey _priv) void Transaction::sign(PrivateKey _priv)
{ {
int v = 0; int v = 0;
u256 msg = sha256(false); u256 msg = sha3(false);
byte sig[64]; byte sig[64];
if (!secp256k1_ecdsa_sign_compact(toBigEndian(msg).data(), 32, sig, toBigEndian(_priv).data(), toBigEndian(kFromMessage(msg, _priv)).data(), &v)) if (!secp256k1_ecdsa_sign_compact(toBigEndian(msg).data(), 32, sig, toBigEndian(_priv).data(), toBigEndian(kFromMessage(msg, _priv)).data(), &v))
throw InvalidSignature(); throw InvalidSignature();

5
libethereum/Transaction.h

@ -22,7 +22,6 @@
#pragma once #pragma once
#include "Common.h" #include "Common.h"
#include "sha256.h"
#include "RLP.h" #include "RLP.h"
namespace eth namespace eth
@ -59,8 +58,8 @@ struct Transaction
void fillStream(RLPStream& _s, bool _sig = true) const; void fillStream(RLPStream& _s, bool _sig = true) const;
bytes rlp(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return s.out(); } bytes rlp(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return s.out(); }
std::string rlpString(bool _sig = true) const { return asString(rlp()); } std::string rlpString(bool _sig = true) const { return asString(rlp()); }
u256 sha256(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return eth::sha256(s.out()); } u256 sha3(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return eth::sha3(s.out()); }
bytes sha256Bytes(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return eth::sha256Bytes(s.out()); } bytes sha3Bytes(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return eth::sha3Bytes(s.out()); }
}; };
} }

120
libethereum/Trie.cpp

@ -66,7 +66,9 @@ std::string hexPrefixEncode(bytes const& _hexVector, bool _terminated, int _begi
return ret; return ret;
} }
u256 hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen) void hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen, RLPStream& _rlp);
void hash256rlp(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen, RLPStream& _rlp)
{ {
#if ENABLE_DEBUG_PRINT #if ENABLE_DEBUG_PRINT
static std::string s_indent; static std::string s_indent;
@ -74,16 +76,15 @@ u256 hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_i
s_indent += " "; s_indent += " ";
#endif #endif
RLPStream rlp;
if (_begin == _end) if (_begin == _end)
rlp << ""; // NULL _rlp << ""; // NULL
else if (std::next(_begin) == _end) else if (std::next(_begin) == _end)
{ {
// only one left - terminate with the pair. // only one left - terminate with the pair.
rlp.appendList(2) << hexPrefixEncode(_begin->first, true, _preLen) << _begin->second; _rlp.appendList(2) << hexPrefixEncode(_begin->first, true, _preLen) << _begin->second;
#if ENABLE_DEBUG_PRINT #if ENABLE_DEBUG_PRINT
if (g_hashDebug) if (g_hashDebug)
std::cerr << s_indent << asHex(bytesConstRef(_begin->first.data() + _preLen, _begin->first.size() - _preLen), 1) << ": " << _begin->second << " = " << sha256(rlp.out()) << std::endl; std::cerr << s_indent << asHex(bytesConstRef(_begin->first.data() + _preLen, _begin->first.size() - _preLen), 1) << ": " << _begin->second << " = " << sha3(_rlp.out()) << std::endl;
#endif #endif
} }
else else
@ -106,16 +107,17 @@ u256 hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_i
if (g_hashDebug) if (g_hashDebug)
std::cerr << s_indent << asHex(bytesConstRef(_begin->first.data() + _preLen, sharedPre), 1) << ": " << std::endl; std::cerr << s_indent << asHex(bytesConstRef(_begin->first.data() + _preLen, sharedPre), 1) << ": " << std::endl;
#endif #endif
rlp.appendList(2) << hexPrefixEncode(_begin->first, false, _preLen, sharedPre) << toCompactBigEndianString(hash256aux(_s, _begin, _end, sharedPre)); _rlp.appendList(2) << hexPrefixEncode(_begin->first, false, _preLen, sharedPre);
hash256aux(_s, _begin, _end, sharedPre, _rlp);
#if ENABLE_DEBUG_PRINT #if ENABLE_DEBUG_PRINT
if (g_hashDebug) if (g_hashDebug)
std::cerr << s_indent << "= " << sha256(rlp.out()) << std::endl; std::cerr << s_indent << "= " << sha3(_rlp.out()) << std::endl;
#endif #endif
} }
else else
{ {
// otherwise enumerate all 16+1 entries. // otherwise enumerate all 16+1 entries.
rlp.appendList(17); _rlp.appendList(17);
auto b = _begin; auto b = _begin;
if (_preLen == b->first.size()) if (_preLen == b->first.size())
{ {
@ -130,25 +132,25 @@ u256 hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_i
auto n = b; auto n = b;
for (; n != _end && n->first[_preLen] == i; ++n) {} for (; n != _end && n->first[_preLen] == i; ++n) {}
if (b == n) if (b == n)
rlp << ""; _rlp << "";
else else
{ {
#if ENABLE_DEBUG_PRINT #if ENABLE_DEBUG_PRINT
if (g_hashDebug) if (g_hashDebug)
std::cerr << s_indent << std::hex << i << ": " << std::endl; std::cerr << s_indent << std::hex << i << ": " << std::endl;
#endif #endif
rlp << toCompactBigEndianString(hash256aux(_s, b, n, _preLen + 1)); hash256aux(_s, b, n, _preLen + 1, _rlp);
} }
b = n; b = n;
} }
if (_preLen == _begin->first.size()) if (_preLen == _begin->first.size())
rlp << _begin->second; _rlp << _begin->second;
else else
rlp << ""; _rlp << "";
#if ENABLE_DEBUG_PRINT #if ENABLE_DEBUG_PRINT
if (g_hashDebug) if (g_hashDebug)
std::cerr << s_indent << "= " << sha256(rlp.out()) << std::endl; std::cerr << s_indent << "= " << sha3(_rlp.out()) << std::endl;
#endif #endif
} }
} }
@ -156,32 +158,44 @@ u256 hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_i
if (_preLen) if (_preLen)
s_indent.resize(s_indent.size() - 2); s_indent.resize(s_indent.size() - 2);
#endif #endif
return sha256(rlp.out()); }
void hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen, RLPStream& _rlp)
{
RLPStream rlp;
hash256rlp(_s, _begin, _end, _preLen, rlp);
if (rlp.out().size() < 32)
_rlp.appendRaw(rlp.out());
else
_rlp << toCompactBigEndianString(sha3(rlp.out()));
} }
u256 hash256(StringMap const& _s) u256 hash256(StringMap const& _s)
{ {
// build patricia tree. // build patricia tree.
if (_s.empty()) if (_s.empty())
return sha256(RLPNull); return sha3(RLPNull);
HexMap hexMap; HexMap hexMap;
for (auto i = _s.rbegin(); i != _s.rend(); ++i) for (auto i = _s.rbegin(); i != _s.rend(); ++i)
hexMap[toHex(i->first)] = i->second; hexMap[toHex(i->first)] = i->second;
return hash256aux(hexMap, hexMap.cbegin(), hexMap.cend(), 0); RLPStream s;
hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s);
return sha3(s.out());
} }
u256 hash256(u256Map const& _s) u256 hash256(u256Map const& _s)
{ {
// build patricia tree. // build patricia tree.
if (_s.empty()) if (_s.empty())
return sha256(RLPNull); return sha3(RLPNull);
HexMap hexMap; HexMap hexMap;
for (auto i = _s.rbegin(); i != _s.rend(); ++i) for (auto i = _s.rbegin(); i != _s.rend(); ++i)
hexMap[toHex(toBigEndianString(i->first))] = asString(rlp(i->second)); hexMap[toHex(toBigEndianString(i->first))] = asString(rlp(i->second));
return hash256aux(hexMap, hexMap.cbegin(), hexMap.cend(), 0); RLPStream s;
hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s);
return sha3(s.out());
} }
class TrieNode class TrieNode
{ {
public: public:
@ -191,16 +205,21 @@ public:
virtual std::string const& at(bytesConstRef _key) const = 0; virtual std::string const& at(bytesConstRef _key) const = 0;
virtual TrieNode* insert(bytesConstRef _key, std::string const& _value) = 0; virtual TrieNode* insert(bytesConstRef _key, std::string const& _value) = 0;
virtual TrieNode* remove(bytesConstRef _key) = 0; virtual TrieNode* remove(bytesConstRef _key) = 0;
virtual bytes rlp() const = 0; void putRLP(RLPStream& _parentStream) const;
#if ENABLE_DEBUG_PRINT #if ENABLE_DEBUG_PRINT
void debugPrint(std::string const& _indent = "") const { std::cerr << std::hex << sha256() << ":" << std::endl; debugPrintBody(_indent); } void debugPrint(std::string const& _indent = "") const { std::cerr << std::hex << sha3() << ":" << std::endl; debugPrintBody(_indent); }
#endif #endif
u256 sha256() const { /*if (!m_sha256)*/ m_sha256 = eth::sha256(rlp()); return m_sha256; } /// 256-bit hash of the node - this is a SHA-3/256 hash of the RLP of the node.
void mark() { m_sha256 = 0; } u256 hash256() const { RLPStream s; makeRLP(s); return eth::sha3(s.out()); }
bytes rlp() const { RLPStream s; makeRLP(s); return s.out(); }
void mark() { m_hash256 = 0; }
protected: protected:
void submitRLP(RLPStream& _rlpStream, bytes const& _rlpFragment) const;
virtual void makeRLP(RLPStream& _intoStream) const = 0;
#if ENABLE_DEBUG_PRINT #if ENABLE_DEBUG_PRINT
virtual void debugPrintBody(std::string const& _indent = "") const = 0; virtual void debugPrintBody(std::string const& _indent = "") const = 0;
#endif #endif
@ -208,7 +227,7 @@ protected:
static TrieNode* newBranch(bytesConstRef _k1, std::string const& _v1, bytesConstRef _k2, std::string const& _v2); static TrieNode* newBranch(bytesConstRef _k1, std::string const& _v1, bytesConstRef _k2, std::string const& _v2);
private: private:
mutable u256 m_sha256 = 0; mutable u256 m_hash256 = 0;
}; };
static const std::string c_nullString; static const std::string c_nullString;
@ -266,7 +285,7 @@ public:
virtual std::string const& at(bytesConstRef _key) const override; virtual std::string const& at(bytesConstRef _key) const override;
virtual TrieNode* insert(bytesConstRef _key, std::string const& _value) override; virtual TrieNode* insert(bytesConstRef _key, std::string const& _value) override;
virtual TrieNode* remove(bytesConstRef _key) override; virtual TrieNode* remove(bytesConstRef _key) override;
virtual bytes rlp() const override; virtual void makeRLP(RLPStream& _parentStream) const override;
private: private:
/// @returns (byte)-1 when no active branches, 16 when multiple active and the index of the active branch otherwise. /// @returns (byte)-1 when no active branches, 16 when multiple active and the index of the active branch otherwise.
@ -299,7 +318,7 @@ public:
virtual std::string const& at(bytesConstRef _key) const override { return contains(_key) ? m_value : c_nullString; } virtual std::string const& at(bytesConstRef _key) const override { return contains(_key) ? m_value : c_nullString; }
virtual TrieNode* insert(bytesConstRef _key, std::string const& _value) override; virtual TrieNode* insert(bytesConstRef _key, std::string const& _value) override;
virtual TrieNode* remove(bytesConstRef _key) override; virtual TrieNode* remove(bytesConstRef _key) override;
virtual bytes rlp() const override { return rlpList(hexPrefixEncode(m_ext, true), m_value); } virtual void makeRLP(RLPStream& _parentStream) const override;
private: private:
bool contains(bytesConstRef _key) const { return _key.size() == m_ext.size() && !memcmp(_key.data(), m_ext.data(), _key.size()); } bool contains(bytesConstRef _key) const { return _key.size() == m_ext.size() && !memcmp(_key.data(), m_ext.data(), _key.size()); }
@ -324,7 +343,7 @@ public:
virtual std::string const& at(bytesConstRef _key) const override { assert(m_next); return contains(_key) ? m_next->at(_key.cropped(m_ext.size())) : c_nullString; } virtual std::string const& at(bytesConstRef _key) const override { assert(m_next); return contains(_key) ? m_next->at(_key.cropped(m_ext.size())) : c_nullString; }
virtual TrieNode* insert(bytesConstRef _key, std::string const& _value) override; virtual TrieNode* insert(bytesConstRef _key, std::string const& _value) override;
virtual TrieNode* remove(bytesConstRef _key) override; virtual TrieNode* remove(bytesConstRef _key) override;
virtual bytes rlp() const override { assert(m_next); return rlpList(hexPrefixEncode(m_ext, false), toCompactBigEndianString(m_next->sha256())); } virtual void makeRLP(RLPStream& _parentStream) const override;
private: private:
bool contains(bytesConstRef _key) const { return _key.size() >= m_ext.size() && !memcmp(_key.data(), m_ext.data(), m_ext.size()); } bool contains(bytesConstRef _key) const { return _key.size() >= m_ext.size() && !memcmp(_key.data(), m_ext.data(), m_ext.size()); }
@ -332,6 +351,40 @@ private:
TrieNode* m_next; TrieNode* m_next;
}; };
void TrieNode::putRLP(RLPStream& _parentStream) const
{
RLPStream s;
makeRLP(s);
if (s.out().size() < 32)
_parentStream.appendRaw(s.out());
else
_parentStream << toCompactBigEndianString(eth::sha3(s.out()));
}
void TrieBranchNode::makeRLP(RLPStream& _intoStream) const
{
_intoStream.appendList(17);
for (auto i: m_nodes)
if (i)
i->putRLP(_intoStream);
else
_intoStream << "";
_intoStream << m_value;
}
void TrieLeafNode::makeRLP(RLPStream& _intoStream) const
{
_intoStream.appendList(2) << hexPrefixEncode(m_ext, true) << m_value;
}
void TrieInfixNode::makeRLP(RLPStream& _intoStream) const
{
assert(m_next);
_intoStream.appendList(2);
_intoStream << hexPrefixEncode(m_ext, false);
m_next->putRLP(_intoStream);
}
TrieNode* TrieNode::newBranch(bytesConstRef _k1, std::string const& _v1, bytesConstRef _k2, std::string const& _v2) TrieNode* TrieNode::newBranch(bytesConstRef _k1, std::string const& _v1, bytesConstRef _k2, std::string const& _v2)
{ {
uint prefix = commonPrefix(_k1, _k2); uint prefix = commonPrefix(_k1, _k2);
@ -428,15 +481,6 @@ TrieNode* TrieBranchNode::rejig()
return this; return this;
} }
bytes TrieBranchNode::rlp() const
{
RLPStream s(17);
for (auto i: m_nodes)
s << (i ? toCompactBigEndianString(i->sha256()) : "");
s << m_value;
return s.out();
}
byte TrieBranchNode::activeBranch() const byte TrieBranchNode::activeBranch() const
{ {
byte n = (byte)-1; byte n = (byte)-1;
@ -549,9 +593,9 @@ Trie::~Trie()
delete m_root; delete m_root;
} }
u256 Trie::sha256() const u256 Trie::hash256() const
{ {
return m_root ? m_root->sha256() : eth::sha256(RLPNull); return m_root ? m_root->hash256() : eth::sha3(RLPNull);
} }
bytes Trie::rlp() const bytes Trie::rlp() const

3
libethereum/Trie.h

@ -23,7 +23,6 @@
#include <map> #include <map>
#include "RLP.h" #include "RLP.h"
#include "sha256.h"
namespace eth namespace eth
{ {
@ -43,7 +42,7 @@ public:
Trie(): m_root(nullptr) {} Trie(): m_root(nullptr) {}
~Trie(); ~Trie();
u256 sha256() const; u256 hash256() const;
bytes rlp() const; bytes rlp() const;
void debugPrint(); void debugPrint();

4
libethereum/vector_ref.h

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <type_traits>
#include <cassert> #include <cassert>
#include <vector> #include <vector>
#include <string> #include <string>
@ -18,7 +19,8 @@ public:
vector_ref(std::vector<typename std::remove_const<_T>::type>* _data): m_data(_data->data()), m_count(_data->size()) {} vector_ref(std::vector<typename std::remove_const<_T>::type>* _data): m_data(_data->data()), m_count(_data->size()) {}
vector_ref(_T* _data, unsigned _count): m_data(_data), m_count(_count) {} vector_ref(_T* _data, unsigned _count): m_data(_data), m_count(_count) {}
vector_ref(std::string* _data): m_data((_T*)_data->data()), m_count(_data->size() / sizeof(_T)) {} vector_ref(std::string* _data): m_data((_T*)_data->data()), m_count(_data->size() / sizeof(_T)) {}
// TODO: const variants enabled only if is_const<_T> vector_ref(std::vector<typename std::enable_if<std::is_const<_T>::value, typename std::remove_const<_T>::type>::type> const* _data): m_data(_data->data()), m_count(_data->size()) {}
vector_ref(std::enable_if<std::is_const<_T>::value, std::string const&> _data): m_data((_T*)_data->data()), m_count(_data->size() / sizeof(_T)) {}
explicit operator bool() const { return m_data && m_count; } explicit operator bool() const { return m_data && m_count; }

8
test/CMakeLists.txt

@ -1,13 +1,19 @@
cmake_policy(SET CMP0015 NEW) cmake_policy(SET CMP0015 NEW)
aux_source_directory(. SRC_LIST) aux_source_directory(. SRC_LIST)
include_directories(../../secp256k1/include) include_directories(../../secp256k1/include)
link_directories(../../secp256k1)
include_directories(../../cryptopp562)
link_directories(../../cryptopp562)
include_directories(../libethereum) include_directories(../libethereum)
link_directories(../libethereum) link_directories(../libethereum)
link_directories(../../secp256k1)
add_executable(testeth ${SRC_LIST}) add_executable(testeth ${SRC_LIST})
target_link_libraries(testeth ethereum) target_link_libraries(testeth ethereum)
target_link_libraries(testeth cryptopp)
target_link_libraries(testeth secp256k1) target_link_libraries(testeth secp256k1)
target_link_libraries(testeth gmp) target_link_libraries(testeth gmp)

37
test/main.cpp

@ -33,6 +33,7 @@ using namespace eth;
int main() int main()
{ {
/*
// Test transaction. // Test transaction.
bytes tx = fromUserHex("88005401010101010101010101010101010101010101011f0de0b6b3a76400001ce8d4a5100080181c373130a009ba1f10285d4e659568bfcfec85067855c5a3c150100815dad4ef98fd37cf0593828c89db94bd6c64e210a32ef8956eaa81ea9307194996a3b879441f5d"); bytes tx = fromUserHex("88005401010101010101010101010101010101010101011f0de0b6b3a76400001ce8d4a5100080181c373130a009ba1f10285d4e659568bfcfec85067855c5a3c150100815dad4ef98fd37cf0593828c89db94bd6c64e210a32ef8956eaa81ea9307194996a3b879441f5d");
cout << "TX: " << RLP(tx) << endl; cout << "TX: " << RLP(tx) << endl;
@ -46,10 +47,10 @@ int main()
auto msg = t.rlp(false); auto msg = t.rlp(false);
cout << "TX w/o SIG: " << RLP(msg) << endl; cout << "TX w/o SIG: " << RLP(msg) << endl;
cout << "RLP(TX w/o SIG): " << asHex(t.rlpString(false)) << endl; cout << "RLP(TX w/o SIG): " << asHex(t.rlpString(false)) << endl;
std::string hmsg = sha256(t.rlpString(false), false); std::string hmsg = sha3(t.rlpString(false), false);
cout << "SHA256(RLP(TX w/o SIG)): 0x" << asHex(hmsg) << endl; cout << "SHA256(RLP(TX w/o SIG)): 0x" << asHex(hmsg) << endl;
bytes privkey = sha256Bytes("123"); bytes privkey = sha3Bytes("123");
secp256k1_start(); secp256k1_start();
@ -87,20 +88,32 @@ int main()
int ret = secp256k1_ecdsa_recover_compact((byte const*)hmsg.data(), hmsg.size(), (byte const*)sig64.data(), pubkey.data(), &pubkeylen, 0, (int)t.vrs.v - 27); int ret = secp256k1_ecdsa_recover_compact((byte const*)hmsg.data(), hmsg.size(), (byte const*)sig64.data(), pubkey.data(), &pubkeylen, 0, (int)t.vrs.v - 27);
pubkey.resize(pubkeylen); pubkey.resize(pubkeylen);
cout << "RECPUB: " << dec << ret << " " << pubkeylen << " " << asHex(pubkey) << endl; cout << "RECPUB: " << dec << ret << " " << pubkeylen << " " << asHex(pubkey) << endl;
cout << "SENDER: " << hex << low160(eth::sha256(bytesConstRef(&pubkey).cropped(1))) << endl; cout << "SENDER: " << hex << low160(eth::sha3(bytesConstRef(&pubkey).cropped(1))) << endl;
} }
*/
{ {
Trie t; Trie t;
cout << hex << hash256(StringMap({})) << endl;
cout << hex << t.hash256() << endl;
cout << hex << hash256({{"dog", "puppy"}, {"doe", "reindeer"}}) << endl;
t.insert("dog", "puppy");
t.insert("doe", "reindeer");
cout << hex << t.hash256() << endl;
cout << RLP(t.rlp()) << endl;
cout << asHex(t.rlp()) << endl;
}
{
Trie t;
t.insert("dog", "puppy"); t.insert("dog", "puppy");
assert(t.sha256() == hash256({{"dog", "puppy"}})); assert(t.hash256() == hash256({{"dog", "puppy"}}));
assert(t.at("dog") == "puppy"); assert(t.at("dog") == "puppy");
t.insert("doe", "reindeer"); t.insert("doe", "reindeer");
assert(t.sha256() == hash256({{"dog", "puppy"}, {"doe", "reindeer"}})); assert(t.hash256() == hash256({{"dog", "puppy"}, {"doe", "reindeer"}}));
assert(t.at("doe") == "reindeer"); assert(t.at("doe") == "reindeer");
assert(t.at("dog") == "puppy"); assert(t.at("dog") == "puppy");
t.insert("dogglesworth", "cat"); t.insert("dogglesworth", "cat");
assert(t.sha256() == hash256({{"doe", "reindeer"}, {"dog", "puppy"}, {"dogglesworth", "cat"}})); assert(t.hash256() == hash256({{"doe", "reindeer"}, {"dog", "puppy"}, {"dogglesworth", "cat"}}));
assert(t.at("doe") == "reindeer"); assert(t.at("doe") == "reindeer");
assert(t.at("dog") == "puppy"); assert(t.at("dog") == "puppy");
assert(t.at("dogglesworth") == "cat"); assert(t.at("dogglesworth") == "cat");
@ -109,11 +122,11 @@ int main()
assert(t.at("doe").empty()); assert(t.at("doe").empty());
assert(t.at("dogglesworth").empty()); assert(t.at("dogglesworth").empty());
assert(t.at("dog") == "puppy"); assert(t.at("dog") == "puppy");
assert(t.sha256() == hash256({{"dog", "puppy"}})); assert(t.hash256() == hash256({{"dog", "puppy"}}));
t.insert("horse", "stallion"); t.insert("horse", "stallion");
t.insert("do", "verb"); t.insert("do", "verb");
t.insert("doge", "coin"); t.insert("doge", "coin");
assert(t.sha256() == hash256({{"dog", "puppy"}, {"horse", "stallion"}, {"do", "verb"}, {"doge", "coin"}})); assert(t.hash256() == hash256({{"dog", "puppy"}, {"horse", "stallion"}, {"do", "verb"}, {"doge", "coin"}}));
assert(t.at("doge") == "coin"); assert(t.at("doge") == "coin");
assert(t.at("do") == "verb"); assert(t.at("do") == "verb");
assert(t.at("horse") == "stallion"); assert(t.at("horse") == "stallion");
@ -121,7 +134,7 @@ int main()
t.remove("horse"); t.remove("horse");
t.remove("do"); t.remove("do");
t.remove("doge"); t.remove("doge");
assert(t.sha256() == hash256({{"dog", "puppy"}})); assert(t.hash256() == hash256({{"dog", "puppy"}}));
assert(t.at("dog") == "puppy"); assert(t.at("dog") == "puppy");
t.remove("dog"); t.remove("dog");
@ -134,14 +147,14 @@ int main()
auto v = toString(i); auto v = toString(i);
m.insert(make_pair(k, v)); m.insert(make_pair(k, v));
t.insert(k, v); t.insert(k, v);
assert(hash256(m) == t.sha256()); assert(hash256(m) == t.hash256());
} }
while (!m.empty()) while (!m.empty())
{ {
auto k = m.begin()->first; auto k = m.begin()->first;
t.remove(k); t.remove(k);
m.erase(k); m.erase(k);
assert(hash256(m) == t.sha256()); assert(hash256(m) == t.hash256());
} }
} }
} }

Loading…
Cancel
Save