From 3562b13f68e6153fb8c205ba0cd223bd463aa99d Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 30 Dec 2013 14:35:01 +0000 Subject: [PATCH] Hex-prefix Notation for the Merkle tree. --- Common.h | 2 +- PatriciaTree.cpp | 3 +- PatriciaTree.h | 133 ++++++++--------------------------------------- RLP.h | 105 +++++++++++++++++++++++++++++++++++++ main.cpp | 39 +++++++++++++- sha256.cpp | 30 +++++------ sha256.h | 40 +++++++------- 7 files changed, 202 insertions(+), 150 deletions(-) diff --git a/Common.h b/Common.h index e53bd8bf6..f2daa4520 100644 --- a/Common.h +++ b/Common.h @@ -11,7 +11,7 @@ namespace eth { using byte = uint8_t; -using bytes = vector; +using bytes = std::vector; using fBytes = foreign; using fConstBytes = foreign; diff --git a/PatriciaTree.cpp b/PatriciaTree.cpp index 8cab563c3..5e4f224a2 100644 --- a/PatriciaTree.cpp +++ b/PatriciaTree.cpp @@ -2,7 +2,7 @@ #include "PatriciaTree.h" using namespace std; using namespace eth; - +/* PatriciaTree::PatriciaTree(RLP const& _data) { // Make tree based on _data @@ -20,3 +20,4 @@ PatriciaTree::PatriciaTree(RLP const& _data) // Branch } } +*/ diff --git a/PatriciaTree.h b/PatriciaTree.h index 1741a3724..16d801b35 100644 --- a/PatriciaTree.h +++ b/PatriciaTree.h @@ -2,6 +2,7 @@ #include #include "RLP.h" +#include "sha256.h" namespace eth { @@ -24,137 +25,49 @@ using HexMap = std::map; * [1,2,3,4,T] 0x201234 */ -std::string fromHex(bytes const& _hexVector, bool _forceTerminated = false) +inline std::string fromHex(bytes const& _hexVector, bool _terminated = false, int _begin = 0, int _end = -1) { - uint begin = 0; - uint end = _hexVector.size(); - bool termed = _forceTerminated; - bool odd = _hexVector.size() % 2; + uint begin = _begin; + uint end = _end < 0 ? _hexVector.size() + 1 + _end : _end; + bool termed = _terminated; + bool odd = (end - begin) % 2; - std::string ret(((termed ? 2 : 0) | (odd ? 1 : 0)) * 16, 1); + std::string ret(1, ((termed ? 2 : 0) | (odd ? 1 : 0)) * 16); if (odd) { ret[0] |= _hexVector[0]; - begin = 1; + ++begin; } - else if (leadingZero) for (uint i = begin; i < end; i += 2) ret += _hexVector[i] * 16 + _hexVector[i + 1]; return ret; } -template bytes encodeRLP(_T _t, _Ts ... _ts) +inline u256 hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen) { + unsigned c = 0; + for (auto i = _begin; i != _end; ++i, ++c) {} -} - -struct rlplist { rlplist(uint _count): count(_count) {} uint count; }; - -class RLPStream -{ -public: - RLPStream() {} - - void append(uint _s) { appendNumeric(_s); } - void append(u256 _s) { appendNumeric(_s); } - void append(bigint _s) { appendNumeric(_s); } - - void append(std::string const& _s) - { - if (_s.size() < 0x38) - m_out.push_back(_count | 0x40); - else - pushCount(_count, 0x40); - uint os = m_out.size(); - m_out.resize(m_out.size() + _s.size()); - memcpy(m_out.data() + os, _s.data(), _s.size()); - } - - void appendList(uint _count) - { - if (_s.size() < 0x38) - m_out.push_back(_count | 0x80); - else - pushCount(_count, 0x80); - } - - RLPStream operator<<(uint _t) { append(_i); } - RLPStream operator<<(u256 _t) { append(_i); } - RLPStream operator<<(bigint _t) { append(_i); } - RLPStream operator<<(std::string const& _s) { append(_s); } - RLPStream operator<<(rlplist _l) { m_lists.push_back(_l.count); appendList(_l.count); } - -private: - void appendNumeric(uint _i) + assert(c > 0); + RLPStream rlp; + if (c == 1) { - if (_i < 0x18) - m_out.push_back(_i); - else - m_out.push_back(bytesRequired(_i) + 0x17); // max 8 bytes. + // only one left - terminate with the pair. + rlp << RLPList(2) << fromHex(_begin->first, true, _preLen) << _begin->second; } - - void appendNumeric(u256 _i) + else { - if (_i < 0x18) - m_out.push_back(_i); - else - m_out.push_back(bytesRequired(_i) + 0x17); // max 32 bytes. - } + // if they all have the same next nibble, we also want a pair. - void appendNumeric(bigint _i) - { - if (_i < 0x18) - m_out.push_back(_i); - else + // otherwise enumerate all 16+1 entries. + for (auto i = 0; i < 16; ++i) { - uint br = bytesRequired(_i); - if (br <= 32) - m_out.push_back(bytesRequired(_i) + 0x17); // max 32 bytes. - else - m_out.push_back(0x37 + bytesRequired(br)); } - for (uint i = 0; i < ) - m_out.push_back() - } - - void pushCount(uint _count, byte _base) - { - m_out.push_back(bytesRequired(_i) + 0x17); // max 8 bytes. - } - - template static uint bytesRequired(_T _i) - { - _i >>= 8; - uint i = 1; - for (; _i != 0; ++i, _i >>= 8) {} - return i; - } - - bytes m_out; -}; - -template <> bytes encodeRLP(_T _t) -{ - -} - -u256 hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen) -{ - unsigned c = 0; - for (auto i = _begin; i != _end; ++i, ++c) {} - - assert(c > 0); - if (c == 1) - return sha256(encodeRLP()); - - - - for (auto i = 0; i < 16; ++i) - { } + return sha256(rlp.out()); } -bytes toHex(std::string const& _s) +inline bytes toHex(std::string const& _s) { std::vector ret(_s.size() * 2 + 1); for (auto i: _s) @@ -166,7 +79,7 @@ bytes toHex(std::string const& _s) return ret; } -u256 hash256(StringMap const& _s) +inline u256 hash256(StringMap const& _s) { // build patricia tree. if (_s.empty()) diff --git a/RLP.h b/RLP.h index e6b4d409a..e09514f93 100644 --- a/RLP.h +++ b/RLP.h @@ -156,6 +156,111 @@ private: fConstBytes m_data; }; +struct RLPList { RLPList(uint _count): count(_count) {} uint count; }; + +class RLPStream +{ +public: + RLPStream() {} + + void append(uint _s) { appendNumeric(_s); } + void append(u256 _s) { appendNumeric(_s); } + void append(bigint _s) { appendNumeric(_s); } + + void append(std::string const& _s) + { + if (_s.size() < 0x38) + m_out.push_back(_s.size() | 0x40); + else + pushCount(_s.size(), 0x40); + uint os = m_out.size(); + m_out.resize(m_out.size() + _s.size()); + memcpy(m_out.data() + os, _s.data(), _s.size()); + } + + void appendList(uint _count) + { + if (_count < 0x38) + m_out.push_back(_count | 0x80); + else + pushCount(_count, 0x80); + } + + RLPStream operator<<(uint _i) { append(_i); return *this; } + RLPStream operator<<(u256 _i) { append(_i); return *this; } + RLPStream operator<<(bigint _i) { append(_i); return *this; } + RLPStream operator<<(std::string const& _s) { append(_s); return *this; } + RLPStream operator<<(RLPList _l) { appendList(_l.count); return *this; } + + bytes const& out() const { return m_out; } + +private: + void appendNumeric(uint _i) + { + if (_i < 0x18) + m_out.push_back(_i); + else + { + auto br = bytesRequired(_i); + m_out.push_back(br + 0x17); // max 8 bytes. + for (int i = br - 1; i >= 0; --i) + m_out.push_back((_i >> i) & 0xff); + } + } + + void appendNumeric(u256 _i) + { + if (_i < 0x18) + m_out.push_back(_i); + else + { + auto br = bytesRequired(_i); + m_out.push_back(br + 0x17); // max 8 bytes. + for (int i = br - 1; i >= 0; --i) + m_out.push_back((byte)(_i >> i)); + } + } + + void appendNumeric(bigint _i) + { + if (_i < 0x18) + m_out.push_back((byte)_i); + else + { + uint br = bytesRequired(_i); + if (br <= 32) + m_out.push_back(bytesRequired(_i) + 0x17); // max 32 bytes. + else + { + auto brbr = bytesRequired(br); + m_out.push_back(0x37 + brbr); + for (int i = brbr - 1; i >= 0; --i) + m_out.push_back((br >> i) & 0xff); + } + for (uint i = 0; i < br; ++i) + { + bigint u = (_i >> (br - 1 - i)); + m_out.push_back((uint)u); + } + } + } + + void pushCount(uint _count, byte _base) + { + m_out.push_back(bytesRequired(_count) + 0x37 + _base); // max 8 bytes. + } + + template static uint bytesRequired(_T _i) + { + _i >>= 8; + uint i = 1; + for (; _i != 0; ++i, _i >>= 8) {} + return i; + } + + bytes m_out; +}; + } inline std::ostream& operator<<(std::ostream& _out, eth::RLP _d) diff --git a/main.cpp b/main.cpp index a15b059b0..04f939777 100644 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,17 @@ #include "RLP.h" +#include "PatriciaTree.h" +#include "VirtualMachine.h" using namespace std; using namespace eth; +std::string asHex(std::string const& _data) +{ + std::ostringstream ret; + for (auto i: _data) + ret << hex << setfill('0') << setw(2) << (int)i; + return ret.str(); +} + int main() { // int of value 15 @@ -27,10 +37,37 @@ int main() // 33-byte (264-bit) int ostringstream o2; o2 << hex << RLP("\x38\x21\x20\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"); - assert(o2.str() == "20100102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); + assert(o2.str() == "2120100102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); // 56-character string. assert(toString(RLP("\x78\x38""Lorem ipsum dolor sit amet, consectetur adipisicing elit")) == "\"Lorem ipsum dolor sit amet, consectetur adipisicing elit\""); + + /* + * Hex-prefix Notation. First nibble has flags: oddness = 2^0 & termination = 2^1 + * [0,0,1,2,3,4,5] 0x10012345 + * [0,1,2,3,4,5] 0x00012345 + * [1,2,3,4,5] 0x112345 + * [0,0,1,2,3,4] 0x00001234 + * [0,1,2,3,4] 0x101234 + * [1,2,3,4] 0x001234 + * [0,0,1,2,3,4,5,T] 0x30012345 + * [0,0,1,2,3,4,T] 0x20001234 + * [0,1,2,3,4,5,T] 0x20012345 + * [1,2,3,4,5,T] 0x312345 + * [1,2,3,4,T] 0x201234 + */ + assert(asHex(fromHex({0, 0, 1, 2, 3, 4, 5}, false)) == "10012345"); + assert(asHex(fromHex({0, 1, 2, 3, 4, 5}, false)) == "00012345"); + assert(asHex(fromHex({1, 2, 3, 4, 5}, false)) == "112345"); + assert(asHex(fromHex({0, 0, 1, 2, 3, 4}, false)) == "00001234"); + assert(asHex(fromHex({0, 1, 2, 3, 4}, false)) == "101234"); + assert(asHex(fromHex({1, 2, 3, 4}, false)) == "001234"); + assert(asHex(fromHex({0, 0, 1, 2, 3, 4, 5}, true)) == "30012345"); + assert(asHex(fromHex({0, 0, 1, 2, 3, 4}, true)) == "20001234"); + assert(asHex(fromHex({0, 1, 2, 3, 4, 5}, true)) == "20012345"); + assert(asHex(fromHex({1, 2, 3, 4, 5}, true)) == "312345"); + assert(asHex(fromHex({1, 2, 3, 4}, true)) == "201234"); + return 0; } diff --git a/sha256.cpp b/sha256.cpp index bac3e198d..b4c2b9ff7 100644 --- a/sha256.cpp +++ b/sha256.cpp @@ -41,7 +41,7 @@ using namespace std; using namespace eth; -const unsigned long SHA256::sha256_k[64] = //UL = uint32 +const uint32_t SHA256::sha256_k[64] = //UL = uint32_t {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, @@ -59,11 +59,11 @@ const unsigned long SHA256::sha256_k[64] = //UL = uint32 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; -void SHA256::transform(const unsigned char *message, unsigned int block_nb) +void SHA256::transform(byte const* message, unsigned block_nb) { - uint32 w[64]; - uint32 wv[8]; - uint32 t1, t2; + uint32_t w[64]; + uint32_t wv[8]; + uint32_t t1, t2; const unsigned char *sub_block; int i; int j; @@ -111,7 +111,7 @@ void SHA256::init() m_tot_len = 0; } -void SHA256::update(const unsigned char *message, unsigned int len) +void SHA256::update(byte const* message, unsigned len) { unsigned int block_nb; unsigned int new_len, rem_len, tmp_len; @@ -134,11 +134,11 @@ void SHA256::update(const unsigned char *message, unsigned int len) m_tot_len += (block_nb + 1) << 6; } -void SHA256::final(unsigned char *digest) +void SHA256::final(byte* digest) { - unsigned int block_nb; - unsigned int pm_len; - unsigned int len_b; + unsigned block_nb; + unsigned pm_len; + unsigned len_b; int i; block_nb = (1 + ((SHA224_256_BLOCK_SIZE - 9) < (m_len % SHA224_256_BLOCK_SIZE))); @@ -154,15 +154,15 @@ void SHA256::final(unsigned char *digest) } } -std::string sha256(std::string const& _input, bool _hex) +std::string eth::sha256(std::string const& _input, bool _hex) { if (!_hex) { - string ret(SHA256::DIGEST_SIZE); + string ret(SHA256::DIGEST_SIZE, '\0'); SHA256 ctx = SHA256(); ctx.init(); ctx.update( (unsigned char*)_input.c_str(), _input.length()); - ctx.final(ret.data()); + ctx.final((byte*)ret.data()); return ret; } @@ -181,7 +181,7 @@ std::string sha256(std::string const& _input, bool _hex) return std::string(buf); } -uint256_t sha256(bytes const& _input) +uint256_t eth::sha256(bytes const& _input) { uint256_t ret = 0; @@ -190,7 +190,7 @@ uint256_t sha256(bytes const& _input) ctx.update(_input.data(), _input.size()); uint8_t buf[SHA256::DIGEST_SIZE]; ctx.final(buf); - for (uint i = 0; i < 32; ++i) + for (unsigned i = 0; i < 32; ++i) ret = (ret << 8) | buf[i]; return ret; } diff --git a/sha256.h b/sha256.h index ef382b72f..c489feaed 100644 --- a/sha256.h +++ b/sha256.h @@ -1,7 +1,7 @@ #pragma once #include -#incldue "Common.h" +#include "Common.h" #include "uint256_t.h" namespace eth @@ -10,24 +10,20 @@ namespace eth class SHA256 { protected: - typedef unsigned char uint8; - typedef unsigned long uint32; - typedef unsigned long long uint64; - - const static uint32 sha256_k[]; - static const unsigned int SHA224_256_BLOCK_SIZE = (512/8); + const static uint32_t sha256_k[]; + static const unsigned SHA224_256_BLOCK_SIZE = (512/8); public: void init(); - void update(const unsigned char *message, unsigned int len); - void final(unsigned char *digest); + void update(byte const* message, unsigned len); + void final(byte* digest); static const unsigned int DIGEST_SIZE = ( 256 / 8); protected: - void transform(const unsigned char *message, unsigned int block_nb); - unsigned int m_tot_len; - unsigned int m_len; - unsigned char m_block[2*SHA224_256_BLOCK_SIZE]; - uint32 m_h[8]; + void transform(byte const* message, unsigned block_nb); + unsigned m_tot_len; + unsigned m_len; + byte m_block[2*SHA224_256_BLOCK_SIZE]; + uint32_t m_h[8]; }; std::string sha256(std::string const& input, bool _hex); @@ -44,17 +40,17 @@ uint256_t sha256(bytes const& input); #define SHA256_F4(x) (SHA2_ROTR(x, 17) ^ SHA2_ROTR(x, 19) ^ SHA2_SHFR(x, 10)) #define SHA2_UNPACK32(x, str) \ { \ - *((str) + 3) = (uint8) ((x) ); \ - *((str) + 2) = (uint8) ((x) >> 8); \ - *((str) + 1) = (uint8) ((x) >> 16); \ - *((str) + 0) = (uint8) ((x) >> 24); \ + *((str) + 3) = (uint8_t) ((x) ); \ + *((str) + 2) = (uint8_t) ((x) >> 8); \ + *((str) + 1) = (uint8_t) ((x) >> 16); \ + *((str) + 0) = (uint8_t) ((x) >> 24); \ } #define SHA2_PACK32(str, x) \ { \ - *(x) = ((uint32) *((str) + 3) ) \ - | ((uint32) *((str) + 2) << 8) \ - | ((uint32) *((str) + 1) << 16) \ - | ((uint32) *((str) + 0) << 24); \ + *(x) = ((uint32_t) *((str) + 3) ) \ + | ((uint32_t) *((str) + 2) << 8) \ + | ((uint32_t) *((str) + 1) << 16) \ + | ((uint32_t) *((str) + 0) << 24); \ } }