Browse Source

crypto prototyping.

cl-refactor
Gav Wood 11 years ago
parent
commit
b0f4ca1339
  1. 53
      libethereum/Common.h
  2. 15
      libethereum/RLP.h
  3. 23
      libethereum/VirtualMachine.cpp
  4. 7
      libethereum/VirtualMachine.h
  5. 2
      test/CMakeLists.txt
  6. 48
      test/main.cpp

53
libethereum/Common.h

@ -3,6 +3,7 @@
#include <cassert>
#include <sstream>
#include <cstdint>
#include <type_traits>
#include <boost/multiprecision/cpp_int.hpp>
#include "vector_ref.h"
@ -31,7 +32,7 @@ template <class _T> inline std::string asHex(_T const& _data, int _w = 2)
{
std::ostringstream ret;
for (auto i: _data)
ret << std::hex << std::setfill('0') << std::setw(_w) << (int)i;
ret << std::hex << std::setfill('0') << std::setw(_w) << (int)(typename std::make_unsigned<decltype(i)>::type)i;
return ret.str();
}
@ -48,6 +49,32 @@ template <class _T, class _U> void pushFront(_T& _t, _U _e)
_t[0] = _e;
}
class BadHexCharacter: public std::exception {};
inline int fromHex(char _i)
{
if (_i >= '0' && _i <= '9')
return _i - '0';
if (_i >= 'a' && _i <= 'f')
return _i - 'a' + 10;
if (_i >= 'A' && _i <= 'F')
return _i - 'A' + 10;
throw BadHexCharacter();
}
inline bytes fromUserHex(std::string const& _s)
{
assert(_s.size() % 2 == 0);
if (_s.size() < 2)
return bytes();
uint s = (_s[0] == '0' && _s[1] == 'x') ? 2 : 0;
std::vector<uint8_t> ret;
ret.reserve((_s.size() - s) / 2);
for (uint i = s; i < _s.size(); i += 2)
ret.push_back(fromHex(_s[i]) * 16 + fromHex(_s[i + 1]));
return ret;
}
inline bytes toHex(std::string const& _s)
{
std::vector<uint8_t> ret;
@ -60,25 +87,25 @@ inline bytes toHex(std::string const& _s)
return ret;
}
template <class _T>
inline std::string toBigEndianString(_T _val, uint _s)
template <class _T, class _Out>
inline void toBigEndian(_T _val, _Out& o_out)
{
std::string ret;
ret.resize(_s);
for (uint i = 0; i < _s; ++i, _val >>= 8)
ret[_s - 1 - i] = (char)(uint8_t)_val;
return ret;
auto s = o_out.size();
for (uint i = 0; i < s; ++i, _val >>= 8)
o_out[s - 1 - i] = (typename _Out::value_type)(uint8_t)_val;
}
inline std::string toBigEndianString(u256 _val) { return toBigEndianString(_val, 32); }
inline std::string toBigEndianString(u160 _val) { return toBigEndianString(_val, 20); }
inline std::string toBigEndianString(u256 _val) { std::string ret(32, '\0'); toBigEndian(_val, ret); return ret; }
inline std::string toBigEndianString(u160 _val) { std::string ret(20, '\0'); toBigEndian(_val, ret); return ret; }
template <class _T>
inline std::string toCompactBigEndianString(_T _val)
{
int i;
for (i = 0; _val; ++i, _val >>= 8) {}
return toBigEndianString(_val, i);
int i = 0;
for (_T v = _val; v; ++i, v >>= 8) {}
std::string ret(i, '\0');
toBigEndian(_val, ret);
return ret;
}
template <class _T, class _U> uint commonPrefix(_T const& _t, _U const& _u)

15
libethereum/RLP.h

@ -119,6 +119,8 @@ public:
m_lastItem = m_lastItem.cropped(0, RLP(m_lastItem).actualSize());
m_remaining -= std::min<uint>(m_remaining, m_lastItem.size());
}
else
m_lastItem.retarget(m_lastItem.next().data(), 0);
return *this;
}
iterator operator++(int) { auto ret = *this; operator++(); return ret; }
@ -128,16 +130,17 @@ public:
private:
iterator() {}
iterator(bytesConstRef _payload, bool _begin)
iterator(RLP const& _parent, bool _begin)
{
if (_begin)
{
m_lastItem = _payload.cropped(RLP(_payload).actualSize());
m_remaining = _payload.size() - m_lastItem.size();
auto pl = _parent.payload();
m_lastItem = pl.cropped(0, RLP(pl).actualSize());
m_remaining = pl.size() - m_lastItem.size();
}
else
{
m_lastItem = _payload.cropped(m_lastItem.size());
m_lastItem = _parent.data().cropped(_parent.data().size());
m_remaining = 0;
}
}
@ -146,8 +149,8 @@ public:
};
friend class iterator;
iterator begin() const { return iterator(payload(), true); }
iterator end() const { return iterator(payload(), false); }
iterator begin() const { return iterator(*this, true); }
iterator end() const { return iterator(*this, false); }
explicit operator std::string() const { return toString(); }
explicit operator RLPs() const { return toList(); }

23
libethereum/VirtualMachine.cpp

@ -15,30 +15,21 @@ u256 const State::c_newContractFee = 0;
Transaction::Transaction(bytes const& _rlpData)
{
RLP rlp(_rlpData);
nonce = rlp[0].toFatIntFromString();
nonce = rlp[0].toFatIntStrict();
receiveAddress = as160(rlp[1].toFatIntFromString());
value = rlp[2].toFatIntStrict();
fee = rlp[3].toFatIntStrict();
data.reserve(rlp[4].itemCountStrict());
for (auto const& i: rlp[4])
data.push_back(i.toFatIntStrict());
vrs = Signature{ rlp[5].toFatIntFromString(), rlp[6].toFatIntFromString(), rlp[7].toFatIntFromString() };
vrs = Signature{ rlp[5].toFatIntStrict(), rlp[6].toFatIntStrict(), rlp[7].toFatIntStrict() };
}
bytes Transaction::rlp() const
void Transaction::fillStream(RLPStream& _s, bool _sig) const
{
RLPStream rlp;
rlp << RLPList(8);
if (nonce)
rlp << nonce;
else
rlp << "";
if (receiveAddress)
rlp << toCompactBigEndianString(receiveAddress);
else
rlp << "";
rlp << value << fee << data << toCompactBigEndianString(vrs.v) << toCompactBigEndianString(vrs.r) << toCompactBigEndianString(vrs.s);
return rlp.out();
_s << RLPList(8) << nonce << toCompactBigEndianString(receiveAddress) << value << fee << data;
if (_sig)
_s << toCompactBigEndianString(vrs.v) << toCompactBigEndianString(vrs.r) << toCompactBigEndianString(vrs.s);
}
bool State::execute(Transaction const& _t, u160 _sender)
@ -447,7 +438,7 @@ void State::execute(u160 _myAddress, u160 _txSender, u256 _txValue, u256 _txFee,
}
t.nonce = transactionsFrom(_myAddress);
execute(t);
execute(t, _myAddress);
break;
}

7
libethereum/VirtualMachine.h

@ -207,8 +207,10 @@ struct Transaction
u256s data;
Signature vrs;
bytes rlp() const;
u256 sha256() const { return eth::sha256(rlp()); }
void fillStream(RLPStream& _s, bool _sig = true) const;
bytes rlp(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return s.out(); }
std::string rlpString(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return s.str(); }
u256 sha256(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return eth::sha256(s.out()); }
};
class State
@ -220,7 +222,6 @@ public:
bool execute(bytes const& _rlp) { try { Transaction t(_rlp); u160 sender = t.vrs.address(bytesConstRef(const_cast<bytes*>(&_rlp))); return execute(t, sender); } catch (...) { return false; } } // remove const_cast once vector_ref can handle const vector* properly.
private:
bool execute(Transaction const& _t);
bool execute(Transaction const& _t, u160 _sender);
bool isNormalAddress(u160 _address) const { auto it = m_current.find(_address); return it != m_current.end() && it->second.type() == AddressType::Normal; }

2
test/CMakeLists.txt

@ -8,4 +8,6 @@ link_directories(../../secp256k1)
add_executable(testeth ${SRC_LIST})
target_link_libraries(testeth secp256k1)
target_link_libraries(testeth ethereum)
target_link_libraries(testeth gmp)

48
test/main.cpp

@ -20,7 +20,55 @@ std::string randomWord()
int main()
{
secp256k1_start();
bytes pubkey(65);
int pubkeylen = 65;
{
cout << "SEC: " << asHex(sha256("123", false)) << endl;
int ret = secp256k1_ecdsa_pubkey_create(pubkey.data(), &pubkeylen, (byte const*)sha256("123", false).data(), 1);
pubkey.resize(pubkeylen);
cout << "PUB: " << ret << " " << pubkeylen << " " << asHex(pubkey) << endl;
}
bytes tx = fromUserHex("88005401010101010101010101010101010101010101011f0de0b6b3a76400001ce8d4a5100080181c373130a009ba1f10285d4e659568bfcfec85067855c5a3c150100815dad4ef98fd37cf0593828c89db94bd6c64e210a32ef8956eaa81ea9307194996a3b879441f5d");
cout << "TX: " << RLP(tx) << endl;
Transaction t(tx);
std::string sig64 = toBigEndianString(t.vrs.r) + toBigEndianString(t.vrs.s);
cout << "SIG: " << sig64.size() << " " << asHex(sig64) << " " << t.vrs.v << endl;
auto msg = t.rlp(false);
cout << "TX w/o SIG: " << RLP(msg) << endl;
cout << "RLP(TX w/o SIG): " << asHex(t.rlpString(false)) << endl;
std::string hmsg = sha256(t.rlpString(false), false);
cout << "SHA256(RLP(TX w/o SIG)): 0x" << asHex(hmsg) << endl;
{
bytes sig(64);
u256 nonce = 0;
int v = 0;
int ret = secp256k1_ecdsa_sign_compact((byte const*)hmsg.data(), hmsg.size(), sig.data(), (byte const*)sha256("123", false).data(), (byte const*)&nonce, &v);
cout << "MYSIG: " << dec << ret << " " << sig.size() << " " << asHex(sig) << " " << v << endl;
ret = secp256k1_ecdsa_recover_compact((byte const*)hmsg.data(), hmsg.size(), (byte const*)sig.data(), pubkey.data(), &pubkeylen, 1, (int)t.vrs.v);
pubkey.resize(pubkeylen);
cout << "MYREC: " << dec << ret << " " << pubkeylen << " " << asHex(pubkey) << endl;
}
{
pubkey.resize(65);
int ret = secp256k1_ecdsa_recover_compact((byte const*)hmsg.data(), hmsg.size(), (byte const*)sig64.data(), pubkey.data(), &pubkeylen, 1, (int)t.vrs.v);
pubkey.resize(pubkeylen);
cout << "REC: " << dec << ret << " " << pubkeylen << " " << asHex(pubkey) << endl;
cout << hex << sha256(pubkey) << endl;
pubkey.resize(65);
ret = secp256k1_ecdsa_recover_compact((byte const*)hmsg.data(), hmsg.size(), (byte const*)sig64.data(), pubkey.data(), &pubkeylen, 0, (int)t.vrs.v);
pubkey.resize(pubkeylen);
cout << "REC+: " << dec << ret << " " << pubkeylen << " " << asHex(pubkey) << endl;
cout << hex << sha256(pubkey) << endl;
}
{
Trie t;

Loading…
Cancel
Save