Browse Source

Working state-transition test.

cl-refactor
Gav Wood 11 years ago
parent
commit
0a4008fc57
  1. 9
      libethereum/BlockInfo.h
  2. 25
      libethereum/Common.cpp
  3. 17
      libethereum/State.cpp
  4. 34
      libethereum/Transaction.cpp
  5. 4
      libethereum/Transaction.h
  6. 17
      test/state.cpp

9
libethereum/BlockInfo.h

@ -46,7 +46,7 @@ public:
explicit operator bool() const { return timestamp != Invalid256; }
bool operator==(BlockInfo const& _cmp) const { return hash == _cmp.hash && parentHash == _cmp.parentHash && nonce == _cmp.nonce; }
bool operator==(BlockInfo const& _cmp) const { return parentHash == _cmp.parentHash && nonce == _cmp.nonce; }
bool operator!=(BlockInfo const& _cmp) const { return !operator==(_cmp); }
static BlockInfo const& genesis() { if (!s_genesis) (s_genesis = new BlockInfo)->populateGenesis(); return *s_genesis; }
@ -68,6 +68,13 @@ private:
static BlockInfo* s_genesis;
};
inline std::ostream& operator<<(std::ostream& _out, BlockInfo const& _bi)
{
_out << _bi.hash << " " << _bi.parentHash << " " << _bi.sha3Uncles << " " << _bi.coinbaseAddress << " " << _bi.stateRoot << " " << _bi.sha3Transactions << " " <<
_bi.difficulty << " " << _bi.timestamp << " " << _bi.nonce;
return _out;
}
}

25
libethereum/Common.cpp

@ -148,17 +148,24 @@ Address eth::toAddress(Secret _private)
{
secp256k1_start();
bytes pubkey(65);
byte pubkey[65];
int pubkeylen = 65;
int ret = secp256k1_ecdsa_seckey_verify(_private.data());
if (!ret)
int ok = secp256k1_ecdsa_seckey_verify(_private.data());
if (!ok)
return Address();
ret = secp256k1_ecdsa_pubkey_create(pubkey.data(), &pubkeylen, _private.data(), 1);
if (!ret)
ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _private.data(), 0);
assert(pubkeylen == 65);
if (!ok)
return Address();
pubkey.resize(pubkeylen);
ret = secp256k1_ecdsa_pubkey_verify(pubkey.data(), pubkey.size());
if (!ret)
ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65);
if (!ok)
return Address();
return left160(eth::sha3(bytesConstRef(&pubkey).cropped(1)));
auto ret = right160(eth::sha3(bytesConstRef(&(pubkey[1]), 64)));
#if ETH_ADDRESS_DEBUG
cout << "---- ADDRESS -------------------------------" << endl;
cout << "SEC: " << _private << endl;
cout << "PUB: " << asHex(bytesConstRef(&(pubkey[1]), 64)) << endl;
cout << "ADR: " << ret << endl;
#endif
return ret;
}

17
libethereum/State.cpp

@ -154,6 +154,10 @@ void State::sync(BlockChain const& _bc, h256 _block)
exit(1);
}
// TODO: why are the hashes different when the essentials are the same?
// cout << bi << endl;
// cout << m_currentBlock << endl;
if (bi == m_currentBlock)
{
// We mined the last block.
@ -288,9 +292,6 @@ u256 State::playback(bytesConstRef _block, BlockInfo const& _grandParent, bool _
// Hash the state trie and check against the state_root hash in m_currentBlock.
if (m_currentBlock.stateRoot != rootHash())
{
cout << m_state;
cout << TrieDB<Address, Overlay>(&m_db, m_state.root());
cout << TrieDB<Address, Overlay>(&m_db, m_currentBlock.stateRoot) << endl;
// Rollback the trie.
m_db.rollback();
throw InvalidStateRoot();
@ -349,7 +350,6 @@ void State::commitToMine(BlockChain const& _bc)
// Commit any and all changes to the trie that are in the cache, then update the state root accordingly.
commit();
cout << m_state;
m_currentBlock.stateRoot = m_state.root();
m_currentBlock.parentHash = m_previousBlock.hash;
}
@ -368,7 +368,12 @@ bool State::mine(uint _msTimeout)
// Got it! Compile block:
RLPStream ret;
ret.appendList(3);
m_currentBlock.fillStream(ret, true);
{
RLPStream s;
m_currentBlock.fillStream(s, true);
m_currentBlock.hash = sha3(s.out());
ret.appendRaw(s.out());
}
ret.appendRaw(m_currentTxs);
ret.appendRaw(m_currentUncles);
ret.swapOut(m_currentBytes);
@ -509,6 +514,8 @@ void State::execute(Transaction const& _t, Address _sender)
if (balance(_sender) < _t.value + _t.fee)
throw NotEnoughCash();
// TODO: check fee is sufficient?
// Increment associated nonce for sender.
noteSending(_sender);

34
libethereum/Transaction.cpp

@ -20,6 +20,7 @@
*/
#include <secp256k1.h>
#include "vector_ref.h"
#include "Exceptions.h"
#include "Transaction.h"
using namespace std;
@ -42,16 +43,25 @@ Address Transaction::sender() const
{
secp256k1_start();
bytes sig = toBigEndian(vrs.r) + toBigEndian(vrs.s);
assert(sig.size() == 64);
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.data(), pubkey, &pubkeylen, 0, (int)vrs.v - 27))
if (!secp256k1_ecdsa_recover_compact(msg.data(), 32, sig[0].data(), pubkey, &pubkeylen, 0, (int)vrs.v - 27))
throw InvalidSignature();
// TODO: check right160 is correct and shouldn't be left160.
return right160(eth::sha3(bytesConstRef(&(pubkey[1]), 64)));
auto ret = right160(eth::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: " << asHex(bytesConstRef(&(pubkey[1]), 64)) << endl;
cout << "ADR: " << ret << endl;
#endif
return ret;
}
void Transaction::sign(Secret _priv)
@ -61,14 +71,22 @@ void Transaction::sign(Secret _priv)
secp256k1_start();
h256 msg = sha3(false);
byte sig[64];
h256 sig[2];
h256 nonce = kFromMessage(msg, _priv);
if (!secp256k1_ecdsa_sign_compact(msg.data(), 32, sig, _priv.data(), nonce.data(), &v))
if (!secp256k1_ecdsa_sign_compact(msg.data(), 32, sig[0].data(), _priv.data(), nonce.data(), &v))
throw 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 = fromBigEndian<u256>(bytesConstRef(sig, 32));
vrs.s = fromBigEndian<u256>(bytesConstRef(&(sig[32]), 32));
vrs.r = (u256)sig[0];
vrs.s = (u256)sig[1];
}
void Transaction::fillStream(RLPStream& _s, bool _sig) const

4
libethereum/Transaction.h

@ -30,8 +30,8 @@ namespace eth
struct Signature
{
byte v;
h256 r;
h256 s;
u256 r;
u256 s;
};
// [ nonce, receiving_address, value, fee, [ data item 0, data item 1 ... data item n ], v, r, s ]

17
test/state.cpp

@ -35,30 +35,43 @@ int stateTest()
BlockChain bc("/tmp");
State s(myMiner.address(), "/tmp");
cout << dec << "me: " << s.balance(me.address()) << endl;
cout << "myMiner: " << s.balance(myMiner.address()) << endl;
// Mine to get some ether!
s.commitToMine(bc);
while (!s.mine(100)) {}
bc.attemptImport(s.blockData());
s.sync(bc);
cout << "me: " << s.balance(me.address()) << endl;
cout << "myMiner: " << s.balance(myMiner.address()) << endl;
bytes tx;
{
Transaction t;
t.nonce = s.transactionsFrom(myMiner.address());
t.fee = 0;
t.value = 1000000000; // 1e9 wei.
t.value = 1000; // 1e3 wei.
t.receiveAddress = me.address();
t.sign(myMiner.secret());
assert(t.sender() == myMiner.address());
tx = t.rlp();
}
cout << RLP(tx) << endl;
s.execute(tx);
cout << "me: " << s.balance(me.address()) << endl;
cout << "myMiner: " << s.balance(myMiner.address()) << endl;
s.commitToMine(bc);
while (!s.mine(100)) {}
bc.attemptImport(s.blockData());
s.sync(bc);
cout << "me: " << s.balance(me.address()) << endl;
cout << "myMiner: " << s.balance(myMiner.address()) << endl;
// s.dumpAccounts();
return 0;
}

Loading…
Cancel
Save