From e2f32c3632e51b58ec5f7811a9730982bac82738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 6 Nov 2014 17:58:37 +0100 Subject: [PATCH 01/50] Fix compilation with Visual Studio --- libdevcrypto/EC.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index af6d0e65e..7bc17ab99 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -134,7 +134,7 @@ bool crypto::verify(Signature const& _signature, bytesConstRef _message) bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) { - static size_t derMaxEncodingLength = 72; + static const size_t derMaxEncodingLength = 72; if (_hashed) { assert(_message.size() == 32); @@ -155,8 +155,9 @@ Public crypto::recover(Signature _signature, bytesConstRef _message) { secp256k1_start(); - int pubkeylen = 65; - byte pubkey[pubkeylen]; + static const int c_pubkeylen = 65; + auto pubkeylen = c_pubkeylen; + byte pubkey[c_pubkeylen]; if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _signature.data(), pubkey, &pubkeylen, 0, (int)_signature[64])) return Public(); @@ -180,8 +181,9 @@ bool crypto::verifySecret(Secret const& _s, Public const& _p) if (!ok) return false; - int pubkeylen = 65; - byte pubkey[pubkeylen]; + static const int c_pubkeylen = 65; + auto pubkeylen = c_pubkeylen; + byte pubkey[c_pubkeylen]; ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _s.data(), 0); if (!ok || pubkeylen != 65) return false; From de0c84c7df6ad668f0969d35475fe4608e99f072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 6 Nov 2014 18:29:49 +0100 Subject: [PATCH 02/50] Replace auto with int --- libdevcrypto/EC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index 7bc17ab99..17304668b 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -182,7 +182,7 @@ bool crypto::verifySecret(Secret const& _s, Public const& _p) return false; static const int c_pubkeylen = 65; - auto pubkeylen = c_pubkeylen; + int pubkeylen = c_pubkeylen; byte pubkey[c_pubkeylen]; ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _s.data(), 0); if (!ok || pubkeylen != 65) From 30bb7c21607d4b9c11a47a94fcdd53d3ecd87a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 6 Nov 2014 18:30:42 +0100 Subject: [PATCH 03/50] Replace auto with int --- libdevcrypto/EC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index 17304668b..237acebc5 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -156,7 +156,7 @@ Public crypto::recover(Signature _signature, bytesConstRef _message) secp256k1_start(); static const int c_pubkeylen = 65; - auto pubkeylen = c_pubkeylen; + int pubkeylen = c_pubkeylen; byte pubkey[c_pubkeylen]; if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _signature.data(), pubkey, &pubkeylen, 0, (int)_signature[64])) return Public(); From c5927833ac583d39bc32975c2e6b4a6a502a3ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 7 Nov 2014 11:37:34 +0100 Subject: [PATCH 04/50] static const variable name fix --- libdevcrypto/EC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index 237acebc5..a54c0132d 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -134,7 +134,7 @@ bool crypto::verify(Signature const& _signature, bytesConstRef _message) bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) { - static const size_t derMaxEncodingLength = 72; + static const size_t c_derMaxEncodingLength = 72; if (_hashed) { assert(_message.size() == 32); From f5730edddb632a2c35cd24dbc2b1747f9cbde0ae Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 10 Nov 2014 13:13:40 +0100 Subject: [PATCH 05/50] Replace function selector jump table by more resilient linear time check. --- libsolidity/Compiler.cpp | 39 +++++++++++++++++------------------ test/solidityCompiler.cpp | 14 ++++++------- test/solidityEndToEndTest.cpp | 16 ++++++++++++++ 3 files changed, 42 insertions(+), 27 deletions(-) diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index ce87f7bb0..c5e25a120 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -81,35 +81,34 @@ void Compiler::appendFunctionSelector(vector> con if (publicFunctions.size() > 255) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("More than 255 public functions for contract.")); - //@todo check for calldatasize? - // retrieve the first byte of the call data - m_context << u256(0) << eth::Instruction::CALLDATALOAD << u256(0) << eth::Instruction::BYTE; - // check that it is not too large - m_context << eth::Instruction::DUP1 << u256(publicFunctions.size() - 1) << eth::Instruction::LT; - eth::AssemblyItem returnTag = m_context.appendConditionalJump(); - - // otherwise, jump inside jump table (each entry of the table has size 4) - m_context << u256(4) << eth::Instruction::MUL; - eth::AssemblyItem jumpTableStart = m_context.pushNewTag(); - m_context << eth::Instruction::ADD << eth::Instruction::JUMP; - - // jump table @todo it could be that the optimizer destroys this - m_context << jumpTableStart; + // retrieve the first byte of the call data, which determines the called function + // @todo This code had a jump table in a previous version which was more efficient but also + // error prone (due to the optimizer and variable length tag addresses) + m_context << u256(1) << u256(0) // some constants + << eth::dupInstruction(1) << eth::Instruction::CALLDATALOAD + << eth::dupInstruction(2) << eth::Instruction::BYTE + << eth::dupInstruction(2); + + // stack here: 1 0 0, stack top will be counted up until it matches funid for (pair> const& f: publicFunctions) - m_context.appendJumpTo(f.second.second) << eth::Instruction::JUMPDEST; - - m_context << returnTag << eth::Instruction::STOP; + { + eth::AssemblyItem const& callDataUnpackerEntry = f.second.second; + m_context << eth::dupInstruction(2) << eth::dupInstruction(2) << eth::Instruction::EQ; + m_context.appendConditionalJumpTo(callDataUnpackerEntry); + m_context << eth::dupInstruction(4) << eth::Instruction::ADD; + //@todo avoid the last ADD (or remove it in the optimizer) + } + m_context << eth::Instruction::STOP; // function not found for (pair> const& f: publicFunctions) { FunctionDefinition const& function = *f.second.first; - m_context << f.second.second; - + eth::AssemblyItem const& callDataUnpackerEntry = f.second.second; + m_context << callDataUnpackerEntry; eth::AssemblyItem returnTag = m_context.pushNewTag(); appendCalldataUnpacker(function); m_context.appendJumpTo(m_context.getFunctionEntryLabel(function)); m_context << returnTag; - appendReturnValuePacker(function); } } diff --git a/test/solidityCompiler.cpp b/test/solidityCompiler.cpp index ba2db67e6..054ad3297 100644 --- a/test/solidityCompiler.cpp +++ b/test/solidityCompiler.cpp @@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) "}\n"; bytes code = compileContract(sourceCode); - unsigned boilerplateSize = 51; + unsigned boilerplateSize = 42; bytes expectation({byte(Instruction::JUMPDEST), byte(Instruction::PUSH1), 0x0, // initialize local variable x byte(Instruction::PUSH1), 0x2, @@ -100,8 +100,8 @@ BOOST_AUTO_TEST_CASE(different_argument_numbers) "}\n"; bytes code = compileContract(sourceCode); - unsigned shift = 75; - unsigned boilerplateSize = 88; + unsigned shift = 70; + unsigned boilerplateSize = 83; bytes expectation({byte(Instruction::JUMPDEST), byte(Instruction::PUSH1), 0x0, // initialize return variable d byte(Instruction::DUP3), @@ -153,8 +153,8 @@ BOOST_AUTO_TEST_CASE(ifStatement) "}\n"; bytes code = compileContract(sourceCode); - unsigned shift = 38; - unsigned boilerplateSize = 51; + unsigned shift = 29; + unsigned boilerplateSize = 42; bytes expectation({byte(Instruction::JUMPDEST), byte(Instruction::PUSH1), 0x0, byte(Instruction::DUP1), @@ -195,8 +195,8 @@ BOOST_AUTO_TEST_CASE(loops) "}\n"; bytes code = compileContract(sourceCode); - unsigned shift = 38; - unsigned boilerplateSize = 51; + unsigned shift = 29; + unsigned boilerplateSize = 42; bytes expectation({byte(Instruction::JUMPDEST), byte(Instruction::JUMPDEST), byte(Instruction::PUSH1), 0x1, diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index 796adcb15..788c388e4 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -148,6 +148,22 @@ BOOST_AUTO_TEST_CASE(recursive_calls) BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(4))); } +BOOST_AUTO_TEST_CASE(multiple_functions) +{ + char const* sourceCode = "contract test {\n" + " function a() returns(uint n) { return 0; }\n" + " function b() returns(uint n) { return 1; }\n" + " function c() returns(uint n) { return 2; }\n" + " function f() returns(uint n) { return 3; }\n" + "}\n"; + compileAndRun(sourceCode); + BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(0))); + BOOST_CHECK(callFunction(1, bytes()) == toBigEndian(u256(1))); + BOOST_CHECK(callFunction(2, bytes()) == toBigEndian(u256(2))); + BOOST_CHECK(callFunction(3, bytes()) == toBigEndian(u256(3))); + BOOST_CHECK(callFunction(4, bytes()) == bytes()); +} + BOOST_AUTO_TEST_CASE(while_loop) { char const* sourceCode = "contract test {\n" From f7c4db767599ffadf52fc939673a0974f3f3a0b4 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 10 Nov 2014 15:36:21 +0100 Subject: [PATCH 06/50] Tests on ranges of input data. --- test/solidityEndToEndTest.cpp | 114 ++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 52 deletions(-) diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index 796adcb15..cca9b7db2 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -41,7 +41,7 @@ class ExecutionFramework public: ExecutionFramework() { g_logVerbosity = 0; } - bytes const& compileAndRun(std::string const& _sourceCode) + bytes const& compileAndRun(string const& _sourceCode) { bytes code = dev::solidity::CompilerStack::compile(_sourceCode); sendMessage(code, true); @@ -49,28 +49,50 @@ public: return m_output; } - bytes const& callFunction(byte _index, bytes const& _data) + bytes const& callFunction(byte _index, bytes const& _data = bytes()) { sendMessage(bytes(1, _index) + _data, false); return m_output; } - bytes const& callFunction(byte _index, u256 const& _argument1) + template + bytes const& callFunction(byte _index, Args const&... _arguments) { - return callFunction(_index, toBigEndian(_argument1)); + return callFunction(_index, argsToBigEndian(_arguments...)); } - bool testSolidityAgainstCpp(byte _index, std::function const& _cppfun, u256 const& _argument1) + template + void testSolidityAgainstCpp(byte _index, CppFunction const& _cppFunctions, Args const&... _arguments) { - return toBigEndian(_cppfun(_argument1)) == callFunction(_index, toBigEndian(_argument1)); + bytes solidityResult = callFunction(_index, _arguments...); + bytes cppResult = toBigEndian(_cppFunctions(_arguments...)); + BOOST_CHECK_MESSAGE(solidityResult == cppResult, "Computed values do not match." + "\nSolidity: " + toHex(solidityResult) + "\nC++: " + toHex(cppResult)); } - bool testSolidityAgainstCpp(byte _index, std::function const& _cppfun) + template + void testSolidityAgainstCppOnRange(byte _index, CppFunction const& _cppFunction, + u256 const& _rangeStart, u256 const& _rangeEnd) { - return toBigEndian(_cppfun()) == callFunction(_index, bytes()); + for (u256 argument = _rangeStart; argument < _rangeEnd; ++argument) + { + bytes solidityResult = callFunction(_index, argument); + bytes cppResult = toBigEndian(_cppFunction(argument)); + BOOST_CHECK_MESSAGE(solidityResult == cppResult, "Computed values do not match." + "\nSolidity: " + toHex(solidityResult) + "\nC++: " + toHex(cppResult) + + "\nArgument: " + toHex(toBigEndian(argument))); + } } private: + template + bytes argsToBigEndian(FirstArg const& _firstArg, Args const&... _followingArgs) const + { + return toBigEndian(_firstArg) + argsToBigEndian(_followingArgs...); + } + + bytes argsToBigEndian() const { return bytes(); } + void sendMessage(bytes const& _data, bool _isCreation) { eth::Executive executive(m_state); @@ -91,7 +113,10 @@ private: BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress)); } else + { + BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress)); BOOST_REQUIRE(!executive.call(m_contractAddress, Address(), 0, m_gasPrice, &_data, m_gas, Address())); + } BOOST_REQUIRE(executive.go()); executive.finalize(); m_output = executive.out().toVector(); @@ -112,8 +137,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) " function f(uint a) returns(uint d) { return a * 7; }\n" "}\n"; compileAndRun(sourceCode); - u256 a = 0x200030004; - BOOST_CHECK(callFunction(0, a) == toBigEndian(a * 7)); + testSolidityAgainstCppOnRange(0, [](u256 const& a) -> u256 { return a * 7; }, 0, 100); } BOOST_AUTO_TEST_CASE(empty_contract) @@ -133,7 +157,7 @@ BOOST_AUTO_TEST_CASE(recursive_calls) " }\n" "}\n"; compileAndRun(sourceCode); - std::function recursive_calls_cpp = [&recursive_calls_cpp](u256 const& n) -> u256 + function recursive_calls_cpp = [&recursive_calls_cpp](u256 const& n) -> u256 { if (n <= 1) return 1; @@ -141,11 +165,7 @@ BOOST_AUTO_TEST_CASE(recursive_calls) return n * recursive_calls_cpp(n - 1); }; - BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(0))); - BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(1))); - BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(2))); - BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(3))); - BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(4))); + testSolidityAgainstCppOnRange(0, recursive_calls_cpp, 0, 5); } BOOST_AUTO_TEST_CASE(while_loop) @@ -169,11 +189,7 @@ BOOST_AUTO_TEST_CASE(while_loop) return nfac; }; - BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(0))); - BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(1))); - BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(2))); - BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(3))); - BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(4))); + testSolidityAgainstCppOnRange(0, while_loop_cpp, 0, 5); } BOOST_AUTO_TEST_CASE(break_outside_loop) @@ -184,9 +200,8 @@ BOOST_AUTO_TEST_CASE(break_outside_loop) " break; continue; return 2;\n" " }\n" "}\n"; - ExecutionFramework framework; - framework.compileAndRun(sourceCode); - BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(2))); + compileAndRun(sourceCode); + testSolidityAgainstCpp(0, [](u256 const& _a) -> u256 { return 2; }, u256(0)); } BOOST_AUTO_TEST_CASE(nested_loops) @@ -209,8 +224,7 @@ BOOST_AUTO_TEST_CASE(nested_loops) " return x;\n" " }\n" "}\n"; - ExecutionFramework framework; - framework.compileAndRun(sourceCode); + compileAndRun(sourceCode); auto nested_loops_cpp = [](u256 n) -> u256 { @@ -236,18 +250,7 @@ BOOST_AUTO_TEST_CASE(nested_loops) return n; }; - BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(0))); - BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(1))); - BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(2))); - BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(3))); - BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(4))); - BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(5))); - BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(6))); - BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(7))); - BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(8))); - BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(9))); - BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(10))); - BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(11))); + testSolidityAgainstCppOnRange(0, nested_loops_cpp, 0, 12); } BOOST_AUTO_TEST_CASE(calling_other_functions) @@ -279,7 +282,8 @@ BOOST_AUTO_TEST_CASE(calling_other_functions) return 3 * n + 1; }; - auto collatz_cpp = [&evenStep_cpp, &oddStep_cpp] (u256 n) -> u256 { + auto collatz_cpp = [&evenStep_cpp, &oddStep_cpp](u256 n) -> u256 + { u256 y; while ((y = n) > 1) { @@ -291,11 +295,11 @@ BOOST_AUTO_TEST_CASE(calling_other_functions) return y; }; - BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(0))); - BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(1))); - BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(2))); - BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(8))); - BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(127))); + testSolidityAgainstCpp(2, collatz_cpp, u256(0)); + testSolidityAgainstCpp(2, collatz_cpp, u256(1)); + testSolidityAgainstCpp(2, collatz_cpp, u256(2)); + testSolidityAgainstCpp(2, collatz_cpp, u256(8)); + testSolidityAgainstCpp(2, collatz_cpp, u256(127)); } BOOST_AUTO_TEST_CASE(many_local_variables) @@ -308,8 +312,15 @@ BOOST_AUTO_TEST_CASE(many_local_variables) " }\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callFunction(0, toBigEndian(u256(0x1000)) + toBigEndian(u256(0x10000)) + toBigEndian(u256(0x100000))) - == toBigEndian(u256(0x121121))); + auto f = [](u256 const& x1, u256 const& x2, u256 const& x3) -> u256 + { + u256 a = 0x1; + u256 b = 0x10; + u256 c = 0x100; + u256 y = a + b + c + x1 + x2 + x3; + return y + b + x2; + }; + testSolidityAgainstCpp(0, f, u256(0x1000), u256(0x10000), u256(0x100000)); } BOOST_AUTO_TEST_CASE(packing_unpacking_types) @@ -354,8 +365,7 @@ BOOST_AUTO_TEST_CASE(short_circuiting) return n; }; - BOOST_CHECK(testSolidityAgainstCpp(0, short_circuiting_cpp, u256(0))); - BOOST_CHECK(testSolidityAgainstCpp(0, short_circuiting_cpp, u256(1))); + testSolidityAgainstCppOnRange(0, short_circuiting_cpp, 0, 2); } BOOST_AUTO_TEST_CASE(high_bits_cleaning) @@ -375,7 +385,7 @@ BOOST_AUTO_TEST_CASE(high_bits_cleaning) return 0; return x; }; - BOOST_CHECK(testSolidityAgainstCpp(0, high_bits_cleaning_cpp)); + testSolidityAgainstCpp(0, high_bits_cleaning_cpp); } BOOST_AUTO_TEST_CASE(sign_extension) @@ -395,7 +405,7 @@ BOOST_AUTO_TEST_CASE(sign_extension) return 0; return u256(x) * -1; }; - BOOST_CHECK(testSolidityAgainstCpp(0, sign_extension_cpp)); + testSolidityAgainstCpp(0, sign_extension_cpp); } BOOST_AUTO_TEST_CASE(small_unsigned_types) @@ -412,7 +422,7 @@ BOOST_AUTO_TEST_CASE(small_unsigned_types) uint32_t x = uint32_t(0xffffff) * 0xffffff; return x / 0x100; }; - BOOST_CHECK(testSolidityAgainstCpp(0, small_unsigned_types_cpp)); + testSolidityAgainstCpp(0, small_unsigned_types_cpp); } BOOST_AUTO_TEST_CASE(small_signed_types) @@ -427,7 +437,7 @@ BOOST_AUTO_TEST_CASE(small_signed_types) { return -int32_t(10) * -int64_t(20); }; - BOOST_CHECK(testSolidityAgainstCpp(0, small_signed_types_cpp)); + testSolidityAgainstCpp(0, small_signed_types_cpp); } BOOST_AUTO_TEST_CASE(state_smoke_test) From 423598e510967b5ee52645df443bb39575fb4ed6 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 10 Nov 2014 18:07:56 +0100 Subject: [PATCH 07/50] Allow void return type. --- test/solidityEndToEndTest.cpp | 58 +++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index cca9b7db2..123d67988 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -22,6 +22,7 @@ */ #include +#include #include #include #include @@ -49,25 +50,24 @@ public: return m_output; } - bytes const& callFunction(byte _index, bytes const& _data = bytes()) + bytes const& callContractFunction(byte _index, bytes const& _data = bytes()) { sendMessage(bytes(1, _index) + _data, false); return m_output; } template - bytes const& callFunction(byte _index, Args const&... _arguments) + bytes const& callContractFunction(byte _index, Args const&... _arguments) { - return callFunction(_index, argsToBigEndian(_arguments...)); + return callContractFunction(_index, argsToBigEndian(_arguments...)); } template - void testSolidityAgainstCpp(byte _index, CppFunction const& _cppFunctions, Args const&... _arguments) + void testSolidityAgainstCpp(byte _index, CppFunction const& _cppFunction, Args const&... _arguments) { - bytes solidityResult = callFunction(_index, _arguments...); - bytes cppResult = toBigEndian(_cppFunctions(_arguments...)); - BOOST_CHECK_MESSAGE(solidityResult == cppResult, "Computed values do not match." - "\nSolidity: " + toHex(solidityResult) + "\nC++: " + toHex(cppResult)); + pair result = callImplementations(_index, _cppFunction, _arguments...); + BOOST_CHECK_MESSAGE(result.first == result.second, "Computed values do not match." + "\nSolidity: " + toHex(result.first) + "\nC++: " + toHex(result.second)); } template @@ -76,15 +76,27 @@ public: { for (u256 argument = _rangeStart; argument < _rangeEnd; ++argument) { - bytes solidityResult = callFunction(_index, argument); - bytes cppResult = toBigEndian(_cppFunction(argument)); - BOOST_CHECK_MESSAGE(solidityResult == cppResult, "Computed values do not match." - "\nSolidity: " + toHex(solidityResult) + "\nC++: " + toHex(cppResult) + + pair result = callImplementations(_index, _cppFunction, argument); + BOOST_CHECK_MESSAGE(result.first == result.second, "Computed values do not match." + "\nSolidity: " + toHex(result.first) + "\nC++: " + toHex(result.second) + "\nArgument: " + toHex(toBigEndian(argument))); } } private: + template + pair callImplementations(byte _solidityIndex, CppFunction const& _cppFunction, + Args const&... _arguments) + { + bytes solidityResult = callContractFunction(_solidityIndex, _arguments...); + bytes cppResult; + if (is_void::value) + _cppFunction(_arguments...); + else + cppResult = toBigEndian(_cppFunction(_arguments...)); + return make_pair(solidityResult, cppResult); + } + template bytes argsToBigEndian(FirstArg const& _firstArg, Args const&... _followingArgs) const { @@ -145,7 +157,7 @@ BOOST_AUTO_TEST_CASE(empty_contract) char const* sourceCode = "contract test {\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callFunction(0, bytes()).empty()); + BOOST_CHECK(callContractFunction(0, bytes()).empty()); } BOOST_AUTO_TEST_CASE(recursive_calls) @@ -333,7 +345,7 @@ BOOST_AUTO_TEST_CASE(packing_unpacking_types) " }\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callFunction(0, fromHex("01""0f0f0f0f""f0f0f0f0f0f0f0f0")) + BOOST_CHECK(callContractFunction(0, fromHex("01""0f0f0f0f""f0f0f0f0f0f0f0f0")) == fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f")); } @@ -345,7 +357,7 @@ BOOST_AUTO_TEST_CASE(multiple_return_values) " }\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callFunction(0, bytes(1, 1) + toBigEndian(u256(0xcd))) + BOOST_CHECK(callContractFunction(0, bytes(1, 1) + toBigEndian(u256(0xcd))) == toBigEndian(u256(0xcd)) + bytes(1, 1) + toBigEndian(u256(0))); } @@ -455,14 +467,14 @@ BOOST_AUTO_TEST_CASE(state_smoke_test) " }\n" "}\n"; compileAndRun(sourceCode); - BOOST_CHECK(callFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0))); - BOOST_CHECK(callFunction(0, bytes(1, 0x01)) == toBigEndian(u256(0))); - BOOST_CHECK(callFunction(1, bytes(1, 0x00) + toBigEndian(u256(0x1234))) == bytes()); - BOOST_CHECK(callFunction(1, bytes(1, 0x01) + toBigEndian(u256(0x8765))) == bytes()); - BOOST_CHECK(callFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x1234))); - BOOST_CHECK(callFunction(0, bytes(1, 0x01)) == toBigEndian(u256(0x8765))); - BOOST_CHECK(callFunction(1, bytes(1, 0x00) + toBigEndian(u256(0x3))) == bytes()); - BOOST_CHECK(callFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x3))); + BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0))); + BOOST_CHECK(callContractFunction(0, bytes(1, 0x01)) == toBigEndian(u256(0))); + BOOST_CHECK(callContractFunction(1, bytes(1, 0x00) + toBigEndian(u256(0x1234))) == bytes()); + BOOST_CHECK(callContractFunction(1, bytes(1, 0x01) + toBigEndian(u256(0x8765))) == bytes()); + BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x1234))); + BOOST_CHECK(callContractFunction(0, bytes(1, 0x01)) == toBigEndian(u256(0x8765))); + BOOST_CHECK(callContractFunction(1, bytes(1, 0x00) + toBigEndian(u256(0x3))) == bytes()); + BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x3))); } BOOST_AUTO_TEST_SUITE_END() From 554681992d3cafe39421b81f5e4022c467ac5dee Mon Sep 17 00:00:00 2001 From: subtly Date: Tue, 11 Nov 2014 03:36:07 +0100 Subject: [PATCH 08/50] aes, ecdh, ecdhe --- libdevcrypto/AES.cpp | 23 +++++++++ libdevcrypto/AES.h | 78 +++++++++++++++++++++++++++++ libdevcrypto/CryptoPP.cpp | 10 +++- libdevcrypto/CryptoPP.h | 4 +- libdevcrypto/ECDHE.cpp | 79 +++++++++++++++++++++++++++++ libdevcrypto/ECDHE.h | 102 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 294 insertions(+), 2 deletions(-) create mode 100644 libdevcrypto/AES.cpp create mode 100644 libdevcrypto/AES.h create mode 100644 libdevcrypto/ECDHE.cpp create mode 100644 libdevcrypto/ECDHE.h diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp new file mode 100644 index 000000000..109ba9646 --- /dev/null +++ b/libdevcrypto/AES.cpp @@ -0,0 +1,23 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . + */ +/** @file AES.cpp + * @author Alex Leverington + * @date 2014 + */ + +#include "AES.h" + diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h new file mode 100644 index 000000000..95525685b --- /dev/null +++ b/libdevcrypto/AES.h @@ -0,0 +1,78 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . + */ +/** @file AES.h + * @author Alex Leverington + * @date 2014 + * + * AES + */ + +#pragma once + +#include "Common.h" + +namespace dev +{ +namespace crypto +{ +namespace aes +{ + +using Secret128 = FixedHash<16>; +enum StreamType { Encrypt, Decrypt }; + +/** + * @brief Encrypted stream + */ +class Stream +{ +public: + Stream(StreamType _t, Secret128 _encS, bool _zero = true): m_type(_t), m_zeroInput(_zero), m_encSecret(_encS) {}; + + virtual void update(bytesRef io_bytes) {}; + + /// Move ciphertext to _bytes. + virtual size_t streamOut(bytes& o_bytes) {}; + +private: + StreamType m_type; + bool m_zeroInput; + Secret128 m_encSecret; + bytes m_text; +}; + +/** + * @brief Encrypted stream with inband SHA3 mac at specific interval. + */ +class AuthenticatedStream: public Stream +{ +public: + AuthenticatedStream(StreamType _t, Secret128 _encS, Secret128 _macS, unsigned _interval, bool _zero = true): Stream(_t, _encS, _zero), m_macSecret(_macS) { m_macInterval = _interval; } + + AuthenticatedStream(StreamType _t, Secret const& _s, unsigned _interval, bool _zero = true): Stream(_t, Secret128(_s), _zero), m_macSecret(FixedHash<16>(_s[0]+16)) { m_macInterval = _interval; } + + /// Adjust mac interval. Next mac will be xored with value. + void adjustInterval(unsigned _interval) { m_macInterval = _interval; }; + +private: + std::atomic m_macInterval; + Secret128 m_macSecret; +}; + +} +} +} \ No newline at end of file diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp index 1b51d5bd5..87859ef9c 100644 --- a/libdevcrypto/CryptoPP.cpp +++ b/libdevcrypto/CryptoPP.cpp @@ -31,6 +31,7 @@ using namespace CryptoPP; void pp::exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& _p) { bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true)); + secp256k1Params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false); assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true)); @@ -42,4 +43,11 @@ void pp::exponentToPublic(Integer const& _e, Public& _p) CryptoPP::DL_PublicKey_EC pk; pk.Initialize(secp256k1Params, secp256k1Params.ExponentiateBase(_e)); pp::exportPublicKey(pk, _p); -} \ No newline at end of file +} + +void pp::ecdhAgree(Secret _s, Public _r, h256& o_s) +{ + ECDH::Domain d(secp256k1Curve); + assert(d.AgreedValueLength() == sizeof(o_s)); + d.Agree(o_s.data(), _s.data(), _r.data()); +} diff --git a/libdevcrypto/CryptoPP.h b/libdevcrypto/CryptoPP.h index dc5d6a610..daf26bc3f 100644 --- a/libdevcrypto/CryptoPP.h +++ b/libdevcrypto/CryptoPP.h @@ -76,7 +76,9 @@ void exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& static void exportPrivateKey(CryptoPP::DL_PrivateKey_EC const& _k, Secret& _s) { _k.GetPrivateExponent().Encode(_s.data(), Secret::size); } void exponentToPublic(Integer const& _e, Public& _p); - + +void ecdhAgree(Secret _s, Public _r, h256& o_s); + template void initializeDLScheme(Secret const& _s, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, secretToExponent(_s)); } diff --git a/libdevcrypto/ECDHE.cpp b/libdevcrypto/ECDHE.cpp new file mode 100644 index 000000000..d785f467e --- /dev/null +++ b/libdevcrypto/ECDHE.cpp @@ -0,0 +1,79 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . + */ +/** @file ECDHE.cpp + * @author Alex Leverington + * @date 2014 + */ + +#include "SHA3.h" +#include "SHA3MAC.h" +#include "CryptoPP.h" +#include "ECDHE.h" + +using namespace std; +using namespace dev; +using namespace dev::crypto; +using namespace dev::crypto::pp; + +void ECDHE::agree(Public _remote) +{ + m_remoteEphemeral = _remote; + ecdhAgree(m_ephemeral.sec(), m_remoteEphemeral, m_sharedSecret); +} + +void ECDHEKeyExchange::exchange(bytes& o_exchange) +{ + if (!m_sharedSecret) + // didn't agree on public remote + BOOST_THROW_EXCEPTION(InvalidState()); + + Public encpk = m_known.first|m_remoteEphemeral; + bytes exchange(encpk.asBytes()); + + // This is the public key which we would like the remote to use, + // which maybe different than previously-known public key. + // Here we would pick an appropriate alias or generate a new one, + // but for now, we use static alias passed to constructor. + // + Public p; + pp::exponentToPublic(pp::secretToExponent(m_alias.m_secret), p); + exchange.resize(exchange.size() + sizeof(p)); + memcpy(exchange.data() - sizeof(p), p.data(), sizeof(p)); + + // protocol parameters; should be fixed size + bytes v(asBytes("\x80")); + exchange.resize(exchange.size() + v.size()); + memcpy(exchange.data() - v.size(), v.data(), v.size()); + + h256 auth; + sha3mac(m_alias.m_secret.ref(), m_sharedSecret.ref(), auth.ref()); + Signature sig = crypto::sign(m_alias.m_secret, auth); + exchange.resize(exchange.size() + sizeof(sig)); + memcpy(exchange.data() - sizeof(sig), sig.data(), sizeof(sig)); + + aes::AuthenticatedStream aes(aes::Encrypt, m_sharedSecret, 0); + h256 prefix(sha3((h256)(m_known.second|m_remoteEphemeral))); + aes.update(prefix.ref()); + + encrypt(encpk, exchange); + aes.update(&exchange); + + aes.streamOut(o_exchange); +} + + + diff --git a/libdevcrypto/ECDHE.h b/libdevcrypto/ECDHE.h new file mode 100644 index 000000000..11a5afa5c --- /dev/null +++ b/libdevcrypto/ECDHE.h @@ -0,0 +1,102 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . + */ +/** @file ECDHE.h + * @author Alex Leverington + * @date 2014 + * + * Elliptic curve Diffie-Hellman ephemeral key exchange + */ + +#pragma once + +#include "AES.h" +#include "EC.h" + +namespace dev +{ +namespace crypto +{ + +typedef std::pair AliasSession; + +class Alias +{ + friend class ECDHEKeyExchange; // todo: remove +public: + Alias(Secret _s): m_secret(_s) {}; + + AliasSession session(Address _a) { return m_sessions.count(_a) ? AliasSession() : m_sessions.find(_a)->second; } + +private: + std::map m_sessions; + Secret m_secret; +}; + +/** + * @brief Derive DH shared secret from EC keypairs. + */ +class ECDHE +{ +public: + /// Constructor (pass public key for ingress exchange). + ECDHE(): m_ephemeral(KeyPair::create()) {}; + + /// Public key sent to remote. + Public pubkey() { return m_ephemeral.pub(); } + + /// Provide public key for dh agreement to generated shared secret. + void agree(Public _remoteEphemeral); + +protected: + KeyPair m_ephemeral; ///< Ephemeral keypair; generated. + Public m_remoteEphemeral; ///< Public key of remote; parameter. + Secret m_sharedSecret; ///< Derived secret; derived by agree. +}; + +/** + * @brief Secure exchange of static keys. + * Key exchange is encrypted with public key of remote and then encrypted by block cipher. For a blind remote the ecdhe public key is used to encrypt exchange, and for a known remote the known public key is used. The block cipher key is derived from ecdhe shared secret. + * + * Usage: Agree -> Exchange -> Authenticate + */ +class ECDHEKeyExchange: public ECDHE +{ +public: + /// Exchange with unknown remote (pass public key for ingress exchange) + ECDHEKeyExchange(Alias& _k): m_alias(_k) {}; + + /// Exchange with known remote + ECDHEKeyExchange(Alias& _k, AliasSession _known): m_alias(_k), m_known(_known) {}; + + /// @returns encrypted payload of key exchange + void exchange(bytes& o_exchange); + + /// Decrypt payload, check mac, check trust, decrypt exchange, authenticate exchange, verify version, verify signature, and if no failure occurs, update or creats trust and derive session-shared-secret. + bool authenticate(bytes _exchangeIn); + +private: + Alias m_alias; + AliasSession m_known; + Secret m_sharedAliasSecret; + + FixedHash<16> m_sharedC; + FixedHash<16> m_sharedM; +}; + +} +} + From 44d089ca0a30c9899a274da424cc3b2aec103514 Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Tue, 11 Nov 2014 08:40:16 +0100 Subject: [PATCH 09/50] fix wrong cast --- libevm/VM.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libevm/VM.h b/libevm/VM.h index d8f71dfc9..a35b3f005 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -701,7 +701,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con break; case Instruction::JUMP: nextPC = m_stack.back(); - if (!m_jumpDests.count((unsigned)nextPC)) + if (!m_jumpDests.count(nextPC)) BOOST_THROW_EXCEPTION(BadJumpDestination()); m_stack.pop_back(); break; @@ -709,7 +709,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con if (m_stack[m_stack.size() - 2]) { nextPC = m_stack.back(); - if (!m_jumpDests.count((unsigned)nextPC)) + if (!m_jumpDests.count(nextPC)) BOOST_THROW_EXCEPTION(BadJumpDestination()); } m_stack.pop_back(); From 466454489402399ff9b5d1145cae7a7f58d1e90b Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 11 Nov 2014 11:41:23 +0100 Subject: [PATCH 10/50] Working template magic for void function. --- test/solidityEndToEndTest.cpp | 41 +++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index 123d67988..85fd707c3 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -65,9 +65,10 @@ public: template void testSolidityAgainstCpp(byte _index, CppFunction const& _cppFunction, Args const&... _arguments) { - pair result = callImplementations(_index, _cppFunction, _arguments...); - BOOST_CHECK_MESSAGE(result.first == result.second, "Computed values do not match." - "\nSolidity: " + toHex(result.first) + "\nC++: " + toHex(result.second)); + bytes solidityResult = callContractFunction(_index, _arguments...); + bytes cppResult = callCppAndEncodeResult(_cppFunction, _arguments...); + BOOST_CHECK_MESSAGE(solidityResult == cppResult, "Computed values do not match." + "\nSolidity: " + toHex(solidityResult) + "\nC++: " + toHex(cppResult)); } template @@ -76,27 +77,15 @@ public: { for (u256 argument = _rangeStart; argument < _rangeEnd; ++argument) { - pair result = callImplementations(_index, _cppFunction, argument); - BOOST_CHECK_MESSAGE(result.first == result.second, "Computed values do not match." - "\nSolidity: " + toHex(result.first) + "\nC++: " + toHex(result.second) + + bytes solidityResult = callContractFunction(_index, argument); + bytes cppResult = callCppAndEncodeResult(_cppFunction, argument); + BOOST_CHECK_MESSAGE(solidityResult == cppResult, "Computed values do not match." + "\nSolidity: " + toHex(solidityResult) + "\nC++: " + toHex(cppResult) + "\nArgument: " + toHex(toBigEndian(argument))); } } private: - template - pair callImplementations(byte _solidityIndex, CppFunction const& _cppFunction, - Args const&... _arguments) - { - bytes solidityResult = callContractFunction(_solidityIndex, _arguments...); - bytes cppResult; - if (is_void::value) - _cppFunction(_arguments...); - else - cppResult = toBigEndian(_cppFunction(_arguments...)); - return make_pair(solidityResult, cppResult); - } - template bytes argsToBigEndian(FirstArg const& _firstArg, Args const&... _followingArgs) const { @@ -105,6 +94,20 @@ private: bytes argsToBigEndian() const { return bytes(); } + template + auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments) + -> typename enable_if::value, bytes>::type + { + _cppFunction(_arguments...); + return bytes(); + } + template + auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments) + -> typename enable_if::value, bytes>::type + { + return toBigEndian(_cppFunction(_arguments...)); + } + void sendMessage(bytes const& _data, bool _isCreation) { eth::Executive executive(m_state); From 8580479d887f1e950c1b08ad1af2ce034acc9b3f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 11 Nov 2014 16:32:17 +0000 Subject: [PATCH 11/50] No implicit logs. --- alethzero/MainWin.cpp | 9 +++++++++ alethzero/MainWin.h | 2 +- libethereum/Executive.cpp | 4 ---- libethereum/State.cpp | 13 +++++-------- libethereum/TransactionReceipt.h | 2 ++ 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 8fe76e24b..155646bcb 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1238,6 +1238,7 @@ void Main::on_blocks_currentItemChanged() auto h = h256((byte const*)hba.data(), h256::ConstructFromPointer); auto details = ethereum()->blockChain().details(h); auto blockData = ethereum()->blockChain().block(h); + auto blockReceipts = ethereum()->blockChain().receipts(h); auto block = RLP(blockData); BlockInfo info(blockData); @@ -1261,6 +1262,14 @@ void Main::on_blocks_currentItemChanged() s << "
Bloom: " << details.bloom << ""; s << "
Log Bloom: " << info.logBloom << ""; s << "
Transactions: " << block[1].itemCount() << " @" << info.transactionsRoot << ""; + s << "
Receipts: @" << info.receiptsRoot << ":"; + for (unsigned i = 0; i < blockReceipts.receipts.size(); ++i) + { + s << "
TX: " << toHex(block[1][i].data()) << "
"; + s << "
Receipt: " << toHex(blockReceipts.receipts[i].rlp()) << "
"; + auto r = blockReceipts.receipts[i].rlp(); + s << "
RLP: " << toString(RLP(r)) << "
"; + } s << "
Uncles: " << block[2].itemCount() << " @" << info.sha3Uncles << ""; for (auto u: block[2]) { diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 57f9c5ebd..9f7ad97de 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -154,6 +154,7 @@ private slots: void on_newIdentity_triggered(); void refreshWhisper(); + void refreshBlockChain(); void addNewId(QString _ids); signals: @@ -214,7 +215,6 @@ private: void refreshPending(); void refreshAccounts(); void refreshDestination(); - void refreshBlockChain(); void refreshBlockCount(); void refreshBalances(); diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index fb89eb21e..95f1c38cb 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -123,11 +123,7 @@ bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _valu m_ext = new ExtVM(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_ms); } else - { m_endGas = _gas; - if (m_ext) - m_ext->sub.logs.push_back(LogEntry(_receiveAddress, {u256((u160)_senderAddress) + 1}, bytes())); - } return !m_ext; } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 5eb315439..ec2a640a9 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -21,9 +21,10 @@ #include "State.h" -#include -#include +#include #include +#include +#include #include #include #include @@ -553,10 +554,12 @@ h256s State::sync(TransactionQueue& _tq, bool* o_transactionQueueChanged) try { uncommitToMine(); +// boost::timer t; execute(i.second); ret.push_back(m_receipts.back().changes().bloom()); _tq.noteGood(i); ++goodTxs; +// cnote << "TX took:" << t.elapsed() * 1000; } catch (InvalidNonce const& in) { @@ -1242,12 +1245,6 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA return !revert; } - else - { - // non-contract call - if (o_sub) - o_sub->logs.push_back(LogEntry(_receiveAddress, {u256((u160)_senderAddress) + 1}, bytes())); - } return true; } diff --git a/libethereum/TransactionReceipt.h b/libethereum/TransactionReceipt.h index 26539c4a9..e24c224e7 100644 --- a/libethereum/TransactionReceipt.h +++ b/libethereum/TransactionReceipt.h @@ -55,6 +55,8 @@ public: l.streamRLP(_s); } + bytes rlp() const { RLPStream s; streamRLP(s); return s.out(); } + private: h256 m_stateRoot; u256 m_gasUsed; From 104dd114564d46376865e3e0923d9dab1bc9ab50 Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 11 Nov 2014 17:41:48 +0100 Subject: [PATCH 12/50] Provide interface for calls in JSON and some other formatting changes. --- alethzero/MainWin.cpp | 6 +- libdevcore/CommonData.cpp | 8 ++- libsolidity/AST.cpp | 15 +++++ libsolidity/AST.h | 2 + libsolidity/ASTPrinter.cpp | 8 +-- libsolidity/ASTPrinter.h | 4 +- libsolidity/CompilerStack.cpp | 100 +++++++++++++++++++++++++++++++--- libsolidity/CompilerStack.h | 41 +++++++++++++- solc/main.cpp | 39 +++++-------- test/solidityEndToEndTest.cpp | 2 +- 10 files changed, 181 insertions(+), 44 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 8fe76e24b..1e59a5f43 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1602,15 +1602,15 @@ void Main::on_data_textChanged() } else if (src.substr(0, 8) == "contract") // improve this heuristic { - shared_ptr scanner = make_shared(); + dev::solidity::CompilerStack compiler; try { - m_data = dev::solidity::CompilerStack::compile(src, scanner, m_enableOptimizer); + m_data = compiler.compile(src, m_enableOptimizer); } catch (dev::Exception const& exception) { ostringstream error; - solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", *scanner); + solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler.getScanner()); solidity = "

Solidity

" + QString::fromStdString(error.str()).toHtmlEscaped() + "
"; } catch (...) diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp index bfcbc5e2e..bd7841402 100644 --- a/libdevcore/CommonData.cpp +++ b/libdevcore/CommonData.cpp @@ -29,14 +29,20 @@ using namespace dev; std::string dev::escaped(std::string const& _s, bool _all) { + static const map prettyEscapes{{'\r', 'r'}, {'\n', 'n'}, {'\t', 't'}, {'\v', 'v'}}; std::string ret; - ret.reserve(_s.size()); + ret.reserve(_s.size() + 2); ret.push_back('"'); for (auto i: _s) if (i == '"' && !_all) ret += "\\\""; else if (i == '\\' && !_all) ret += "\\\\"; + else if (prettyEscapes.count(i)) + { + ret += '\\'; + ret += prettyEscapes.find(i)->second; + } else if (i < ' ' || _all) { ret += "\\x"; diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 565560adc..70af8f98e 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -263,6 +263,21 @@ TypeError ASTNode::createTypeError(string const& _description) return TypeError() << errinfo_sourceLocation(getLocation()) << errinfo_comment(_description); } +vector ContractDefinition::getInterfaceFunctions() const +{ + vector exportedFunctions; + for (ASTPointer const& f: m_definedFunctions) + if (f->isPublic() && f->getName() != getName()) + exportedFunctions.push_back(f.get()); + auto compareNames = [](FunctionDefinition const* _a, FunctionDefinition const* _b) + { + return _a->getName().compare(_b->getName()) < 0; + }; + + sort(exportedFunctions.begin(), exportedFunctions.end(), compareNames); + return exportedFunctions; +} + void Block::checkTypeRequirements() { for (shared_ptr const& statement: m_statements) diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 19328e5f7..7b266f132 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -120,6 +120,8 @@ public: std::vector> const& getStateVariables() const { return m_stateVariables; } std::vector> const& getDefinedFunctions() const { return m_definedFunctions; } + /// Returns the functions that make up the calling interface in the intended order. + std::vector getInterfaceFunctions() const; private: std::vector> m_definedStructs; std::vector> m_stateVariables; diff --git a/libsolidity/ASTPrinter.cpp b/libsolidity/ASTPrinter.cpp index eb9d92f08..987ad11cc 100644 --- a/libsolidity/ASTPrinter.cpp +++ b/libsolidity/ASTPrinter.cpp @@ -30,8 +30,8 @@ namespace dev namespace solidity { -ASTPrinter::ASTPrinter(ASTPointer const& _ast, string const& _source): - m_indentation(0), m_source(_source), m_ast(_ast) +ASTPrinter::ASTPrinter(ASTNode& _ast, string const& _source): + m_indentation(0), m_source(_source), m_ast(&_ast) { } @@ -430,8 +430,8 @@ void ASTPrinter::printSourcePart(ASTNode const& _node) if (!m_source.empty()) { Location const& location(_node.getLocation()); - *m_ostream << getIndentation() << " Source: |" - << m_source.substr(location.start, location.end - location.start) << "|" << endl; + *m_ostream << getIndentation() << " Source: " + << escaped(m_source.substr(location.start, location.end - location.start), false) << endl; } } diff --git a/libsolidity/ASTPrinter.h b/libsolidity/ASTPrinter.h index e87b2ba3b..e0757fbc4 100644 --- a/libsolidity/ASTPrinter.h +++ b/libsolidity/ASTPrinter.h @@ -38,7 +38,7 @@ class ASTPrinter: public ASTVisitor public: /// Create a printer for the given abstract syntax tree. If the source is specified, /// the corresponding parts of the source are printed with each node. - ASTPrinter(ASTPointer const& _ast, std::string const& _source = std::string()); + ASTPrinter(ASTNode& _ast, std::string const& _source = std::string()); /// Output the string representation of the AST to _stream. void print(std::ostream& _stream); @@ -114,7 +114,7 @@ private: int m_indentation; std::string m_source; - ASTPointer m_ast; + ASTNode* m_ast; std::ostream* m_ostream; }; diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp index c991171a5..d87c27916 100644 --- a/libsolidity/CompilerStack.cpp +++ b/libsolidity/CompilerStack.cpp @@ -34,17 +34,101 @@ namespace dev namespace solidity { -bytes CompilerStack::compile(std::string const& _sourceCode, shared_ptr _scanner, - bool _optimize) +void CompilerStack::setSource(string const& _sourceCode) { - if (!_scanner) - _scanner = make_shared(); - _scanner->reset(CharStream(_sourceCode)); + reset(); + m_scanner = make_shared(CharStream(_sourceCode)); +} + +void CompilerStack::parse() +{ + if (!m_scanner) + BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Source not available.")); + m_contractASTNode = Parser().parse(m_scanner); + NameAndTypeResolver().resolveNamesAndTypes(*m_contractASTNode); + m_parseSuccessful = true; +} + +void CompilerStack::parse(string const& _sourceCode) +{ + setSource(_sourceCode); + parse(); +} + +bytes const& CompilerStack::compile(bool _optimize) +{ + if (!m_parseSuccessful) + BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); + m_bytecode.clear(); + m_compiler = make_shared(); + m_compiler->compileContract(*m_contractASTNode); + return m_bytecode = m_compiler->getAssembledBytecode(_optimize); +} - ASTPointer contract = Parser().parse(_scanner); - NameAndTypeResolver().resolveNamesAndTypes(*contract); - return Compiler::compile(*contract, _optimize); +bytes const& CompilerStack::compile(string const& _sourceCode, bool _optimize) +{ + parse(_sourceCode); + return compile(_optimize); } +void CompilerStack::streamAssembly(ostream& _outStream) +{ + if (!m_compiler || m_bytecode.empty()) + BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + m_compiler->streamAssembly(_outStream); +} + +string const& CompilerStack::getInterface() +{ + if (!m_parseSuccessful) + BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); + if (m_interface.empty()) + { + stringstream interface; + interface << '['; + vector exportedFunctions = m_contractASTNode->getInterfaceFunctions(); + unsigned functionsCount = exportedFunctions.size(); + for (FunctionDefinition const* f: exportedFunctions) + { + auto streamVariables = [&](vector> const& _vars) + { + unsigned varCount = _vars.size(); + for (ASTPointer const& var: _vars) + { + interface << "{" + << "\"name\":" << escaped(var->getName(), false) << "," + << "\"type\":" << escaped(var->getType()->toString(), false) + << "}"; + if (--varCount > 0) + interface << ","; + } + }; + + interface << '{' + << "\"name\":" << escaped(f->getName(), false) << "," + << "\"inputs\":["; + streamVariables(f->getParameters()); + interface << "]," + << "\"outputs\":["; + streamVariables(f->getReturnParameters()); + interface << "]" + << "}"; + if (--functionsCount > 0) + interface << ","; + } + interface << ']'; + m_interface = interface.str(); + } + return m_interface; +} + +bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimize) +{ + CompilerStack stack; + return stack.compile(_sourceCode, _optimize); +} + + + } } diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h index b003745d2..2fb505897 100644 --- a/libsolidity/CompilerStack.h +++ b/libsolidity/CompilerStack.h @@ -22,6 +22,7 @@ #pragma once +#include #include #include #include @@ -30,13 +31,51 @@ namespace dev { namespace solidity { class Scanner; // forward +class ContractDefinition; // forward +class Compiler; // forward +/** + * Easy to use and self-contained Solidity compiler with as few header dependencies as possible. + * It holds state and can be used to either step through the compilation stages (and abort e.g. + * before compilation to bytecode) or run the whole compilation in one call. + */ class CompilerStack { public: + CompilerStack() {} + void reset() { *this = CompilerStack(); } + void setSource(std::string const& _sourceCode); + void parse(); + void parse(std::string const& _sourceCode); + /// Compiles the contract that was previously parsed. + bytes const& compile(bool _optimize = false); + /// Parses and compiles the given source code. + bytes const& compile(std::string const& _sourceCode, bool _optimize = false); + + bytes const& getBytecode() const { return m_bytecode; } + /// Streams a verbose version of the assembly to @a _outStream. + /// Prerequisite: Successful compilation. + void streamAssembly(std::ostream& _outStream); + + /// Returns a string representing the contract interface in JSON. + /// Prerequisite: Successful call to parse or compile. + std::string const& getInterface(); + + /// Returns the previously used scanner, useful for counting lines during error reporting. + Scanner const& getScanner() const { return *m_scanner; } + ContractDefinition& getAST() const { return *m_contractASTNode; } + /// Compile the given @a _sourceCode to bytecode. If a scanner is provided, it is used for /// scanning the source code - this is useful for printing exception information. - static bytes compile(std::string const& _sourceCode, std::shared_ptr _scanner = std::shared_ptr(), bool _optimize = false); + static bytes staticCompile(std::string const& _sourceCode, bool _optimize = false); + +private: + std::shared_ptr m_scanner; + std::shared_ptr m_contractASTNode; + bool m_parseSuccessful; + std::string m_interface; + std::shared_ptr m_compiler; + bytes m_bytecode; }; } diff --git a/solc/main.cpp b/solc/main.cpp index 04fdc0ee1..a7216e594 100644 --- a/solc/main.cpp +++ b/solc/main.cpp @@ -26,12 +26,13 @@ #include #include #include +#include #include #include #include #include #include -#include +#include #include using namespace std; @@ -85,48 +86,34 @@ int main(int argc, char** argv) else sourceCode = asString(dev::contents(infile)); - ASTPointer ast; - shared_ptr scanner = make_shared(CharStream(sourceCode)); - Parser parser; - bytes instructions; - Compiler compiler; + CompilerStack compiler; try { - ast = parser.parse(scanner); - - NameAndTypeResolver resolver; - resolver.resolveNamesAndTypes(*ast.get()); - - cout << "Syntax tree for the contract:" << endl; - dev::solidity::ASTPrinter printer(ast, sourceCode); - printer.print(cout); - - compiler.compileContract(*ast); - instructions = compiler.getAssembledBytecode(optimize); + compiler.compile(sourceCode, optimize); } catch (ParserError const& exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", *scanner); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", compiler.getScanner()); return -1; } catch (DeclarationError const& exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", *scanner); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", compiler.getScanner()); return -1; } catch (TypeError const& exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", *scanner); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", compiler.getScanner()); return -1; } catch (CompilerError const& exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", *scanner); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", compiler.getScanner()); return -1; } catch (InternalCompilerError const& exception) { - cerr << "Internal compiler error: " << boost::diagnostic_information(exception) << endl; + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Internal compiler error", compiler.getScanner()); return -1; } catch (Exception const& exception) @@ -140,11 +127,15 @@ int main(int argc, char** argv) return -1; } + cout << "Syntax tree for the contract:" << endl; + ASTPrinter printer(compiler.getAST(), sourceCode); + printer.print(cout); cout << "EVM assembly:" << endl; compiler.streamAssembly(cout); cout << "Opcodes:" << endl; - cout << eth::disassemble(instructions) << endl; - cout << "Binary: " << toHex(instructions) << endl; + cout << eth::disassemble(compiler.getBytecode()) << endl; + cout << "Binary: " << toHex(compiler.getBytecode()) << endl; + cout << "Interface specification: " << compiler.getInterface() << endl; return 0; } diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index 796adcb15..ffeab0a76 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -43,7 +43,7 @@ public: bytes const& compileAndRun(std::string const& _sourceCode) { - bytes code = dev::solidity::CompilerStack::compile(_sourceCode); + bytes code = dev::solidity::CompilerStack::staticCompile(_sourceCode); sendMessage(code, true); BOOST_REQUIRE(!m_output.empty()); return m_output; From 489fb2b430a24eb6b7e2617db3bb7b8646481ad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 11 Nov 2014 18:00:49 +0100 Subject: [PATCH 13/50] static const variable name fix --- libdevcrypto/EC.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index a54c0132d..a3438ede1 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -134,15 +134,15 @@ bool crypto::verify(Signature const& _signature, bytesConstRef _message) bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) { - static const size_t c_derMaxEncodingLength = 72; if (_hashed) { assert(_message.size() == 32); byte encpub[65] = {0x04}; memcpy(&encpub[1], _p.data(), 64); - byte dersig[derMaxEncodingLength]; - size_t cssz = DSAConvertSignatureFormat(dersig, derMaxEncodingLength, DSA_DER, _sig.data(), 64, DSA_P1363); - assert(cssz <= derMaxEncodingLength); + static const size_t c_derMaxEncodingLength = 72; + byte dersig[c_derMaxEncodingLength]; + size_t cssz = DSAConvertSignatureFormat(dersig, c_derMaxEncodingLength, DSA_DER, _sig.data(), 64, DSA_P1363); + assert(cssz <= c_derMaxEncodingLength); return (1 == secp256k1_ecdsa_verify(_message.data(), _message.size(), dersig, cssz, encpub, 65)); } From 845dce6f52a354b7b9abbf0f8bed89b5d1c86b88 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 11 Nov 2014 17:24:11 +0000 Subject: [PATCH 14/50] Version bumps. --- libdevcore/Common.cpp | 2 +- libethcore/CommonEth.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 78dbed65b..ae073b9b1 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -27,7 +27,7 @@ using namespace dev; namespace dev { -char const* Version = "0.7.9"; +char const* Version = "0.7.10"; } diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp index 8e21884ee..0ebf79669 100644 --- a/libethcore/CommonEth.cpp +++ b/libethcore/CommonEth.cpp @@ -34,7 +34,7 @@ namespace dev namespace eth { -const unsigned c_protocolVersion = 39; +const unsigned c_protocolVersion = 40; const unsigned c_databaseVersion = 4; static const vector> g_units = From 0f86ce7545b101e66cbb9089d0dddc137951467b Mon Sep 17 00:00:00 2001 From: subtly Date: Tue, 11 Nov 2014 18:31:23 +0100 Subject: [PATCH 15/50] ecdh, ecdhe, initial aes classes --- libdevcore/Common.h | 1 + libdevcore/FixedHash.h | 1 + libdevcrypto/AES.cpp | 28 ++++++++ libdevcrypto/AES.h | 22 +++--- libdevcrypto/All.h | 1 - libdevcrypto/CryptoPP.cpp | 6 +- libdevcrypto/CryptoPP.h | 8 ++- libdevcrypto/ECDHE.cpp | 19 +++-- libdevcrypto/ECDHE.h | 12 ++-- libethcore/CryptoHeaders.h | 36 ---------- test/TestHelperCrypto.h | 51 ------------- test/crypto.cpp | 143 +++++++++++++++++++++++-------------- 12 files changed, 164 insertions(+), 164 deletions(-) delete mode 100644 libethcore/CryptoHeaders.h delete mode 100644 test/TestHelperCrypto.h diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 87cc069b3..198119f24 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -59,6 +59,7 @@ using bytesConstRef = vector_ref; // Numeric types. using bigint = boost::multiprecision::number>; +using u128 = boost::multiprecision::number>; using u256 = boost::multiprecision::number>; using s256 = boost::multiprecision::number>; using u160 = boost::multiprecision::number>; diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 2353a100c..0e387ab8a 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -240,6 +240,7 @@ using h520 = FixedHash<65>; using h512 = FixedHash<64>; using h256 = FixedHash<32>; using h160 = FixedHash<20>; +using h128 = FixedHash<16>; using h512s = std::vector; using h256s = std::vector; using h160s = std::vector; diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp index 109ba9646..fc0cf15c4 100644 --- a/libdevcrypto/AES.cpp +++ b/libdevcrypto/AES.cpp @@ -19,5 +19,33 @@ * @date 2014 */ +#include "CryptoPP.h" #include "AES.h" +using namespace std; +using namespace dev::crypto::aes; +using namespace dev::crypto::pp; +using namespace CryptoPP; + +Stream::Stream(StreamType _t, h128 _ckey): + m_cSecret(_ckey) +{ + (void)_t; // encrypt and decrypt are same operation w/ctr mode + cryptor = new Aes128Ctr(_ckey); +} + +Stream::~Stream() +{ + delete cryptor; +} + +void Stream::update(bytesRef io_bytes) +{ + +} + +size_t Stream::streamOut(bytes& o_bytes) +{ + +} + diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h index 95525685b..753dcd14b 100644 --- a/libdevcrypto/AES.h +++ b/libdevcrypto/AES.h @@ -29,10 +29,10 @@ namespace dev { namespace crypto { +namespace pp { struct Aes128Ctr; } namespace aes { -using Secret128 = FixedHash<16>; enum StreamType { Encrypt, Decrypt }; /** @@ -41,18 +41,20 @@ enum StreamType { Encrypt, Decrypt }; class Stream { public: - Stream(StreamType _t, Secret128 _encS, bool _zero = true): m_type(_t), m_zeroInput(_zero), m_encSecret(_encS) {}; + // streamtype maybe irrelevant w/ctr + Stream(StreamType _t, h128 _ckey); + ~Stream(); - virtual void update(bytesRef io_bytes) {}; + virtual void update(bytesRef io_bytes); /// Move ciphertext to _bytes. - virtual size_t streamOut(bytes& o_bytes) {}; + virtual size_t streamOut(bytes& o_bytes); private: - StreamType m_type; - bool m_zeroInput; - Secret128 m_encSecret; + h128 m_cSecret; bytes m_text; + + pp::Aes128Ctr* cryptor; }; /** @@ -61,16 +63,16 @@ private: class AuthenticatedStream: public Stream { public: - AuthenticatedStream(StreamType _t, Secret128 _encS, Secret128 _macS, unsigned _interval, bool _zero = true): Stream(_t, _encS, _zero), m_macSecret(_macS) { m_macInterval = _interval; } + AuthenticatedStream(StreamType _t, h128 _ckey, h128 _mackey, unsigned _interval): Stream(_t, _ckey), m_macSecret(_mackey) { m_macInterval = _interval; } - AuthenticatedStream(StreamType _t, Secret const& _s, unsigned _interval, bool _zero = true): Stream(_t, Secret128(_s), _zero), m_macSecret(FixedHash<16>(_s[0]+16)) { m_macInterval = _interval; } + AuthenticatedStream(StreamType _t, Secret const& _s, unsigned _interval): Stream(_t, h128(_s)), m_macSecret(FixedHash<16>(_s[0]+16)) { m_macInterval = _interval; } /// Adjust mac interval. Next mac will be xored with value. void adjustInterval(unsigned _interval) { m_macInterval = _interval; }; private: std::atomic m_macInterval; - Secret128 m_macSecret; + h128 m_macSecret; }; } diff --git a/libdevcrypto/All.h b/libdevcrypto/All.h index db6d7c615..8018db4fb 100644 --- a/libdevcrypto/All.h +++ b/libdevcrypto/All.h @@ -1,7 +1,6 @@ #pragma once #include "Common.h" -#include "CryptoPP.h" #include "EC.h" #include "FileSystem.h" #include "MemoryDB.h" diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp index 87859ef9c..0694699ae 100644 --- a/libdevcrypto/CryptoPP.cpp +++ b/libdevcrypto/CryptoPP.cpp @@ -45,9 +45,11 @@ void pp::exponentToPublic(Integer const& _e, Public& _p) pp::exportPublicKey(pk, _p); } -void pp::ecdhAgree(Secret _s, Public _r, h256& o_s) +void pp::ecdhAgree(Secret const& _s, Public const& _r, h256& o_s) { ECDH::Domain d(secp256k1Curve); assert(d.AgreedValueLength() == sizeof(o_s)); - d.Agree(o_s.data(), _s.data(), _r.data()); + byte remote[65] = {0x04}; + memcpy(&remote[1], _r.data(), 64); + assert(d.Agree(o_s.data(), _s.data(), remote)); } diff --git a/libdevcrypto/CryptoPP.h b/libdevcrypto/CryptoPP.h index daf26bc3f..1ae4bee74 100644 --- a/libdevcrypto/CryptoPP.h +++ b/libdevcrypto/CryptoPP.h @@ -77,13 +77,19 @@ static void exportPrivateKey(CryptoPP::DL_PrivateKey_EC const& _k void exponentToPublic(Integer const& _e, Public& _p); -void ecdhAgree(Secret _s, Public _r, h256& o_s); +void ecdhAgree(Secret const& _s, Public const& _r, h256& o_s); template void initializeDLScheme(Secret const& _s, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, secretToExponent(_s)); } template void initializeDLScheme(Public const& _p, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, publicToPoint(_p)); } + +struct Aes128Ctr +{ + Aes128Ctr(h128 _k) { mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data()); } + CTR_Mode::Encryption mode; +}; } } diff --git a/libdevcrypto/ECDHE.cpp b/libdevcrypto/ECDHE.cpp index d785f467e..6b3979874 100644 --- a/libdevcrypto/ECDHE.cpp +++ b/libdevcrypto/ECDHE.cpp @@ -29,15 +29,24 @@ using namespace dev; using namespace dev::crypto; using namespace dev::crypto::pp; -void ECDHE::agree(Public _remote) +void ECDHE::agree(Public const& _remote, Secret& o_sharedSecret) { + if (m_remoteEphemeral) + // agreement can only occur once + BOOST_THROW_EXCEPTION(InvalidState()); + m_remoteEphemeral = _remote; - ecdhAgree(m_ephemeral.sec(), m_remoteEphemeral, m_sharedSecret); + ecdhAgree(m_ephemeral.sec(), m_remoteEphemeral, o_sharedSecret); +} + +void ECDHEKeyExchange::agree(Public const& _remoteEphemeral) +{ + ecdhAgree(m_ephemeral.sec(), _remoteEphemeral, m_ephemeralSecret); } void ECDHEKeyExchange::exchange(bytes& o_exchange) { - if (!m_sharedSecret) + if (!m_ephemeralSecret) // didn't agree on public remote BOOST_THROW_EXCEPTION(InvalidState()); @@ -60,12 +69,12 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange) memcpy(exchange.data() - v.size(), v.data(), v.size()); h256 auth; - sha3mac(m_alias.m_secret.ref(), m_sharedSecret.ref(), auth.ref()); + sha3mac(m_alias.m_secret.ref(), m_ephemeralSecret.ref(), auth.ref()); Signature sig = crypto::sign(m_alias.m_secret, auth); exchange.resize(exchange.size() + sizeof(sig)); memcpy(exchange.data() - sizeof(sig), sig.data(), sizeof(sig)); - aes::AuthenticatedStream aes(aes::Encrypt, m_sharedSecret, 0); + aes::AuthenticatedStream aes(aes::Encrypt, m_ephemeralSecret, 0); h256 prefix(sha3((h256)(m_known.second|m_remoteEphemeral))); aes.update(prefix.ref()); diff --git a/libdevcrypto/ECDHE.h b/libdevcrypto/ECDHE.h index 11a5afa5c..88e5ba764 100644 --- a/libdevcrypto/ECDHE.h +++ b/libdevcrypto/ECDHE.h @@ -48,6 +48,7 @@ private: /** * @brief Derive DH shared secret from EC keypairs. + * As ephemeral keys are single-use, agreement is limited to a single occurence. */ class ECDHE { @@ -58,13 +59,12 @@ public: /// Public key sent to remote. Public pubkey() { return m_ephemeral.pub(); } - /// Provide public key for dh agreement to generated shared secret. - void agree(Public _remoteEphemeral); + /// Input public key for dh agreement, output generated shared secret. + void agree(Public const& _remoteEphemeral, Secret& o_sharedSecret); protected: KeyPair m_ephemeral; ///< Ephemeral keypair; generated. Public m_remoteEphemeral; ///< Public key of remote; parameter. - Secret m_sharedSecret; ///< Derived secret; derived by agree. }; /** @@ -73,7 +73,7 @@ protected: * * Usage: Agree -> Exchange -> Authenticate */ -class ECDHEKeyExchange: public ECDHE +class ECDHEKeyExchange: private ECDHE { public: /// Exchange with unknown remote (pass public key for ingress exchange) @@ -82,6 +82,9 @@ public: /// Exchange with known remote ECDHEKeyExchange(Alias& _k, AliasSession _known): m_alias(_k), m_known(_known) {}; + /// Provide public key for dh agreement to generate shared secret. + void agree(Public const& _remoteEphemeral); + /// @returns encrypted payload of key exchange void exchange(bytes& o_exchange); @@ -89,6 +92,7 @@ public: bool authenticate(bytes _exchangeIn); private: + Secret m_ephemeralSecret; Alias m_alias; AliasSession m_known; Secret m_sharedAliasSecret; diff --git a/libethcore/CryptoHeaders.h b/libethcore/CryptoHeaders.h deleted file mode 100644 index 4ff63f1d7..000000000 --- a/libethcore/CryptoHeaders.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . -*/ -/** @file CryptoHeaders.h - * @author Tim Hughes - * @date 2014 - */ -#pragma once - -// need to leave this one disabled -#pragma GCC diagnostic ignored "-Wunused-function" - -#pragma warning(push) -#pragma warning(disable:4100 4244) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#include -#include -#include -#include -#pragma warning(pop) -#pragma GCC diagnostic pop diff --git a/test/TestHelperCrypto.h b/test/TestHelperCrypto.h deleted file mode 100644 index 01e97c21f..000000000 --- a/test/TestHelperCrypto.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . - */ -/** @file TestHelperCrypto.h - * @author Alex Leverington - * @date 2014 - */ - -#pragma once - -#include - -using namespace std; -using namespace CryptoPP; - -void SavePrivateKey(const PrivateKey& key, const string& file = "ecies.private.key") -{ - FileSink sink(file.c_str()); - key.Save(sink); -} - -void SavePublicKey(const PublicKey& key, const string& file = "ecies.public.key") -{ - FileSink sink(file.c_str()); - key.Save(sink); -} - -void LoadPrivateKey(PrivateKey& key, const string& file = "ecies.private.key") -{ - FileSource source(file.c_str(), true); - key.Load(source); -} - -void LoadPublicKey(PublicKey& key, const string& file = "ecies.public.key") -{ - FileSource source(file.c_str(), true); - key.Load(source); -} diff --git a/test/crypto.cpp b/test/crypto.cpp index 06e55658a..a84c1fbb5 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -27,9 +27,10 @@ #include #include #include -#include #include -#include "TestHelperCrypto.h" +#include +#include +#include using namespace std; using namespace dev; @@ -40,7 +41,7 @@ BOOST_AUTO_TEST_SUITE(devcrypto) BOOST_AUTO_TEST_CASE(common_encrypt_decrypt) { - string message("Now is the time for all good persons to come to the aide of humanity."); + string message("Now is the time for all good persons to come to the aid of humanity."); bytes m = asBytes(message); bytesConstRef bcr(&m); @@ -267,7 +268,7 @@ BOOST_AUTO_TEST_CASE(ecies_eckeypair) { KeyPair k = KeyPair::create(); - string message("Now is the time for all good persons to come to the aide of humanity."); + string message("Now is the time for all good persons to come to the aid of humanity."); string original = message; bytes b = asBytes(message); @@ -278,61 +279,87 @@ BOOST_AUTO_TEST_CASE(ecies_eckeypair) BOOST_REQUIRE(b == asBytes(original)); } -BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac) +BOOST_AUTO_TEST_CASE(ecdh) { - // New connections require new ECDH keypairs - // Every new connection requires a new EC keypair - // Every new trust requires a new EC keypair - // All connections should share seed for PRF (or PRNG) for nonces + cnote << "Testing ecdh..."; + + ECDH::Domain dhLocal(pp::secp256k1Curve); + SecByteBlock privLocal(dhLocal.PrivateKeyLength()); + SecByteBlock pubLocal(dhLocal.PublicKeyLength()); + dhLocal.GenerateKeyPair(pp::PRNG, privLocal, pubLocal); + + ECDH::Domain dhRemote(pp::secp256k1Curve); + SecByteBlock privRemote(dhRemote.PrivateKeyLength()); + SecByteBlock pubRemote(dhRemote.PublicKeyLength()); + dhRemote.GenerateKeyPair(pp::PRNG, privRemote, pubRemote); + assert(dhLocal.AgreedValueLength() == dhRemote.AgreedValueLength()); + // local: send public to remote; remote: send public to local + + // Local + SecByteBlock sharedLocal(dhLocal.AgreedValueLength()); + assert(dhLocal.Agree(sharedLocal, privLocal, pubRemote)); + + // Remote + SecByteBlock sharedRemote(dhRemote.AgreedValueLength()); + assert(dhRemote.Agree(sharedRemote, privRemote, pubLocal)); + + // Test + Integer ssLocal, ssRemote; + ssLocal.Decode(sharedLocal.BytePtr(), sharedLocal.SizeInBytes()); + ssRemote.Decode(sharedRemote.BytePtr(), sharedRemote.SizeInBytes()); + + assert(ssLocal != 0); + assert(ssLocal == ssRemote); + + + // Now use our keys + KeyPair a = KeyPair::create(); + byte puba[65] = {0x04}; + memcpy(&puba[1], a.pub().data(), 64); + + KeyPair b = KeyPair::create(); + byte pubb[65] = {0x04}; + memcpy(&pubb[1], b.pub().data(), 64); + + ECDH::Domain dhA(pp::secp256k1Curve); + Secret shared; + BOOST_REQUIRE(dhA.Agree(shared.data(), a.sec().data(), pubb)); + BOOST_REQUIRE(shared); } -BOOST_AUTO_TEST_CASE(cryptopp_ecies_message) +BOOST_AUTO_TEST_CASE(ecdhe) { - cnote << "Testing cryptopp_ecies_message..."; - - string const message("Now is the time for all good persons to come to the aide of humanity."); - - ECIES::Decryptor localDecryptor(pp::PRNG, pp::secp256k1Curve); - SavePrivateKey(localDecryptor.GetPrivateKey()); + cnote << "Testing ecdhe..."; - ECIES::Encryptor localEncryptor(localDecryptor); - SavePublicKey(localEncryptor.GetPublicKey()); - - ECIES::Decryptor futureDecryptor; - LoadPrivateKey(futureDecryptor.AccessPrivateKey()); - futureDecryptor.GetPrivateKey().ThrowIfInvalid(pp::PRNG, 3); + ECDHE a, b; + BOOST_CHECK_NE(a.pubkey(), b.pubkey()); - ECIES::Encryptor futureEncryptor; - LoadPublicKey(futureEncryptor.AccessPublicKey()); - futureEncryptor.GetPublicKey().ThrowIfInvalid(pp::PRNG, 3); - - // encrypt/decrypt with local - string cipherLocal; - StringSource ss1 (message, true, new PK_EncryptorFilter(pp::PRNG, localEncryptor, new StringSink(cipherLocal) ) ); - string plainLocal; - StringSource ss2 (cipherLocal, true, new PK_DecryptorFilter(pp::PRNG, localDecryptor, new StringSink(plainLocal) ) ); - - // encrypt/decrypt with future - string cipherFuture; - StringSource ss3 (message, true, new PK_EncryptorFilter(pp::PRNG, futureEncryptor, new StringSink(cipherFuture) ) ); - string plainFuture; - StringSource ss4 (cipherFuture, true, new PK_DecryptorFilter(pp::PRNG, futureDecryptor, new StringSink(plainFuture) ) ); + ECDHE local; + ECDHE remote; - // decrypt local w/future - string plainFutureFromLocal; - StringSource ss5 (cipherLocal, true, new PK_DecryptorFilter(pp::PRNG, futureDecryptor, new StringSink(plainFutureFromLocal) ) ); + // local tx pubkey -> remote + Secret sremote; + remote.agree(local.pubkey(), sremote); - // decrypt future w/local - string plainLocalFromFuture; - StringSource ss6 (cipherFuture, true, new PK_DecryptorFilter(pp::PRNG, localDecryptor, new StringSink(plainLocalFromFuture) ) ); + // remote tx pbukey -> local + Secret slocal; + local.agree(remote.pubkey(), slocal); + + BOOST_REQUIRE(sremote); + BOOST_REQUIRE(slocal); + BOOST_REQUIRE_EQUAL(sremote, slocal); +} + +BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac) +{ + // New connections require new ECDH keypairs + // Every new connection requires a new EC keypair + // Every new trust requires a new EC keypair + // All connections should share seed for PRF (or PRNG) for nonces - BOOST_REQUIRE(plainLocal == message); - BOOST_REQUIRE(plainFuture == plainLocal); - BOOST_REQUIRE(plainFutureFromLocal == plainLocal); - BOOST_REQUIRE(plainLocalFromFuture == plainLocal); } BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) @@ -346,21 +373,29 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) rng.GenerateBlock(key, key.size()); // cryptopp uses IV as nonce/counter which is same as using nonce w/0 ctr - byte ctr[AES::BLOCKSIZE]; - rng.GenerateBlock(ctr, sizeof(ctr)); + FixedHash ctr; + rng.GenerateBlock(ctr.data(), sizeof(ctr)); + + // used for decrypt + FixedHash ctrcopy(ctr); - string text = "Now is the time for all good persons to come to the aide of humanity."; - // c++11 ftw + string text = "Now is the time for all good persons to come to the aid of humanity."; unsigned char const* in = (unsigned char*)&text[0]; unsigned char* out = (unsigned char*)&text[0]; string original = text; + string doublespeak = text + text; string cipherCopy; try { CTR_Mode::Encryption e; - e.SetKeyWithIV(key, key.size(), ctr); + e.SetKeyWithIV(key, key.size(), ctr.data()); + + // 68 % 255 should be difference of counter e.ProcessData(out, in, text.size()); + + (u128)ctr += (u128)(text.size() % 16); + BOOST_REQUIRE(text != original); cipherCopy = text; } @@ -372,7 +407,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) try { CTR_Mode< AES >::Decryption d; - d.SetKeyWithIV(key, key.size(), ctr); + d.SetKeyWithIV(key, key.size(), ctrcopy.data()); d.ProcessData(out, in, text.size()); BOOST_REQUIRE(text == original); } @@ -390,7 +425,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) out = (unsigned char*)&cipherCopy[0]; CTR_Mode::Encryption e; - e.SetKeyWithIV(key, key.size(), ctr); + e.SetKeyWithIV(key, key.size(), ctrcopy.data()); e.ProcessData(out, in, text.size()); // yep, ctr mode. From df413e0a4f3578be898cca072a698f1089fd8753 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 11 Nov 2014 18:02:12 +0000 Subject: [PATCH 16/50] LOG fixes. --- libethereum/Executive.cpp | 3 +++ libevm/VM.h | 2 +- libevmcore/Instruction.cpp | 10 +++++----- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 95f1c38cb..f8c526ac7 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -173,7 +173,10 @@ bool Executive::go(OnOpFunc const& _onOp) { m_out = m_vm->go(*m_ext, _onOp); if (m_ext) + { m_endGas += min((m_t.gas() - m_endGas) / 2, m_ext->sub.refunds); + m_logs = m_ext->sub.logs; + } m_endGas = m_vm->gas(); } catch (StepsDone const&) diff --git a/libevm/VM.h b/libevm/VM.h index a35b3f005..91a769a04 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -206,7 +206,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con { unsigned n = (unsigned)inst - (unsigned)Instruction::LOG0; require(n + 2); - newTempSize = memNeed(m_stack[m_stack.size() - 1 - n], m_stack[m_stack.size() - 2 - n]); + newTempSize = memNeed(m_stack[m_stack.size() - 1 ], m_stack[m_stack.size() - 2]); break; } diff --git a/libevmcore/Instruction.cpp b/libevmcore/Instruction.cpp index 5d94a22ca..9062fd8ed 100644 --- a/libevmcore/Instruction.cpp +++ b/libevmcore/Instruction.cpp @@ -282,11 +282,11 @@ static const std::map c_instructionInfo = { Instruction::SWAP14, { "SWAP14", 0, 15, 15, false } }, { Instruction::SWAP15, { "SWAP15", 0, 16, 16, false } }, { Instruction::SWAP16, { "SWAP16", 0, 17, 17, false } }, - { Instruction::LOG0, { "LOG0", 0, 1, 0, true } }, - { Instruction::LOG1, { "LOG1", 0, 2, 0, true } }, - { Instruction::LOG2, { "LOG2", 0, 3, 0, true } }, - { Instruction::LOG3, { "LOG3", 0, 4, 0, true } }, - { Instruction::LOG4, { "LOG4", 0, 5, 0, true } }, + { Instruction::LOG0, { "LOG0", 0, 2, 0, true } }, + { Instruction::LOG1, { "LOG1", 0, 3, 0, true } }, + { Instruction::LOG2, { "LOG2", 0, 4, 0, true } }, + { Instruction::LOG3, { "LOG3", 0, 5, 0, true } }, + { Instruction::LOG4, { "LOG4", 0, 6, 0, true } }, { Instruction::CREATE, { "CREATE", 0, 3, 1, true } }, { Instruction::CALL, { "CALL", 0, 7, 1, true } }, { Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true } }, From 5750a091d7528b5683a6c156278a44543ed3978b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 11 Nov 2014 18:29:24 +0000 Subject: [PATCH 17/50] Fix for LOGs again. --- libevm/VM.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/libevm/VM.h b/libevm/VM.h index 91a769a04..b3a4c2828 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -743,18 +743,38 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con break;*/ case Instruction::LOG0: _ext.log({}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); + m_stack.pop_back(); + m_stack.pop_back(); break; case Instruction::LOG1: _ext.log({m_stack[m_stack.size() - 3]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); break; case Instruction::LOG2: _ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); break; case Instruction::LOG3: _ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); break; case Instruction::LOG4: _ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5], m_stack[m_stack.size() - 6]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); break; case Instruction::CREATE: { From eeb2b4dc58a58e20f535ab3aa2a2f8746e1cf62f Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Tue, 11 Nov 2014 21:56:17 +0100 Subject: [PATCH 18/50] Store return value of call to precompiled contract in test --- test/stPreCompiledContractsFiller.json | 38 +++++++++++++------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/test/stPreCompiledContractsFiller.json b/test/stPreCompiledContractsFiller.json index 8975f1aea..bb2b35756 100644 --- a/test/stPreCompiledContractsFiller.json +++ b/test/stPreCompiledContractsFiller.json @@ -12,7 +12,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -46,7 +46,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 500 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 500 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -80,7 +80,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 499 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 499 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -114,7 +114,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code": "{ (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) }", + "code": "{ [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) }", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -148,7 +148,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 1) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 1) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -182,7 +182,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 33 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 65 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 1000 1 0 0 97 97 32) [[ 0 ]] (MOD (MLOAD 97) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 33 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 65 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 1000 1 0 0 97 97 32) [[ 0 ]] (MOD (MLOAD 97) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -216,7 +216,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code": "{ (MSTORE 0 0x2f380a2dea7e778d81affc2443403b8fe4644db442ae4862ff5bb3732829cdb9) (MSTORE 32 27) (MSTORE 64 0x6b65ccb0558806e9b097f27a396d08f964e37b8b7af6ceeb516ff86739fbea0a) (MSTORE 96 0x37cbc8d883e129a4b1ef9d5f1df53c4f21a3ef147cf2a50a4ede0eb06ce092d4) (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "code": "{ (MSTORE 0 0x2f380a2dea7e778d81affc2443403b8fe4644db442ae4862ff5bb3732829cdb9) (MSTORE 32 27) (MSTORE 64 0x6b65ccb0558806e9b097f27a396d08f964e37b8b7af6ceeb516ff86739fbea0a) (MSTORE 96 0x37cbc8d883e129a4b1ef9d5f1df53c4f21a3ef147cf2a50a4ede0eb06ce092d4) [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -284,7 +284,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code" : "{ (CALL 500 2 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", + "code" : "{ [[ 2 ]] (CALL 500 2 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -318,7 +318,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code" : "{ (MSTORE 5 0xf34578907f) (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "code" : "{ (MSTORE 5 0xf34578907f) [[ 2 ]] (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -352,7 +352,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code" : "{ (MSTORE 0 0xf34578907f) (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -386,7 +386,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 100 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 100 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -420,7 +420,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 99 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 99 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -454,7 +454,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 500 2 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 500 2 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -522,7 +522,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code" : "{ (CALL 500 3 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", + "code" : "{ [[ 2 ]] (CALL 500 3 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -556,7 +556,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code" : "{ (MSTORE 5 0xf34578907f) (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "code" : "{ (MSTORE 5 0xf34578907f) [[ 2 ]] (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -590,7 +590,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code" : "{ (MSTORE 0 0xf34578907f) (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -624,7 +624,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 100 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 100 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -658,7 +658,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 99 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 99 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -692,7 +692,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20000000", "nonce" : 0, - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 500 3 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 500 3 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { From 0f94ad7dc458a9f0838dccdb067149129ffadb2b Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Tue, 11 Nov 2014 22:25:21 +0100 Subject: [PATCH 19/50] Create state test with commandline flag --- test/TestHelper.cpp | 47 ++++++++++++++++++++++++--------------------- test/state.cpp | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 22 deletions(-) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index c1a141abb..80482399a 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -27,8 +27,6 @@ #include #include -//#define FILL_TESTS - using namespace std; using namespace dev::eth; @@ -351,28 +349,33 @@ void executeTests(const string& _name, const string& _testPathAppendix, std::fun string testPath = getTestPath(); testPath += _testPathAppendix; -#ifdef FILL_TESTS - try - { - cnote << "Populating tests..."; - json_spirit::mValue v; - boost::filesystem::path p(__FILE__); - boost::filesystem::path dir = p.parent_path(); - string s = asString(dev::contents(dir.string() + "/" + _name + "Filler.json")); - BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + dir.string() + "/" + _name + "Filler.json is empty."); - json_spirit::read_string(s, v); - doTests(v, true); - writeFile(testPath + "/" + _name + ".json", asBytes(json_spirit::write_string(v, true))); - } - catch (Exception const& _e) - { - BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); - } - catch (std::exception const& _e) + for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) { - BOOST_ERROR("Failed test with Exception: " << _e.what()); + string arg = boost::unit_test::framework::master_test_suite().argv[i]; + if (arg == "--createtest") + { + try + { + cnote << "Populating tests..."; + json_spirit::mValue v; + boost::filesystem::path p(__FILE__); + boost::filesystem::path dir = p.parent_path(); + string s = asString(dev::contents(dir.string() + "/" + _name + "Filler.json")); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + dir.string() + "/" + _name + "Filler.json is empty."); + json_spirit::read_string(s, v); + doTests(v, true); + writeFile(testPath + "/" + _name + ".json", asBytes(json_spirit::write_string(v, true))); + } + catch (Exception const& _e) + { + BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); + } + catch (std::exception const& _e) + { + BOOST_ERROR("Failed test with Exception: " << _e.what()); + } + } } -#endif try { diff --git a/test/state.cpp b/test/state.cpp index 91d9f3e51..b5b238299 100644 --- a/test/state.cpp +++ b/test/state.cpp @@ -122,6 +122,40 @@ BOOST_AUTO_TEST_CASE(stPreCompiledContracts) dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests); } +BOOST_AUTO_TEST_CASE(stCreateTest) +{ + for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) + { + string arg = boost::unit_test::framework::master_test_suite().argv[i]; + if (arg == "--createtest") + { + if (boost::unit_test::framework::master_test_suite().argc <= i + 2) + { + cnote << "usage: ./testeth --createtest \n"; + return; + } + try + { + cnote << "Populating tests..."; + json_spirit::mValue v; + string s = asString(dev::contents(boost::unit_test::framework::master_test_suite().argv[i + 1])); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + (string)boost::unit_test::framework::master_test_suite().argv[i + 1] + " is empty."); + json_spirit::read_string(s, v); + dev::test::doStateTests(v, true); + writeFile(boost::unit_test::framework::master_test_suite().argv[i + 2], asBytes(json_spirit::write_string(v, true))); + } + catch (Exception const& _e) + { + BOOST_ERROR("Failed state test with Exception: " << diagnostic_information(_e)); + } + catch (std::exception const& _e) + { + BOOST_ERROR("Failed state test with Exception: " << _e.what()); + } + } + } +} + BOOST_AUTO_TEST_CASE(userDefinedFileState) { dev::test::userDefinedTest("--statetest", dev::test::doStateTests); From 0c4b5d7c2bd2c8fc2439f1f2f7985dcd4089d43b Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Tue, 11 Nov 2014 22:28:43 +0100 Subject: [PATCH 20/50] changed name of command line option to filltests --- test/TestHelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 80482399a..1b13f9e82 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -352,7 +352,7 @@ void executeTests(const string& _name, const string& _testPathAppendix, std::fun for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) { string arg = boost::unit_test::framework::master_test_suite().argv[i]; - if (arg == "--createtest") + if (arg == "--filltests") { try { From 98f3011aabcfb53399c17265705a908c17f9fbaf Mon Sep 17 00:00:00 2001 From: subtly Date: Wed, 12 Nov 2014 02:01:27 +0100 Subject: [PATCH 21/50] cryptopp recover public key --- libdevcrypto/EC.cpp | 39 ++++++++++++++++++++++++--------------- test/crypto.cpp | 8 ++++---- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index af6d0e65e..a509a5b41 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -153,24 +153,33 @@ bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _mess Public crypto::recover(Signature _signature, bytesConstRef _message) { - secp256k1_start(); + Integer heInt(_message.data(), 32); - int pubkeylen = 65; - byte pubkey[pubkeylen]; - if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _signature.data(), pubkey, &pubkeylen, 0, (int)_signature[64])) - return Public(); + // a different curve would require additional check for v (aka, recid) + Integer r(_signature.data(), 32); + Integer s(_signature.data()+32, 32); + unsigned recid = _signature[64]; -#if ETH_CRYPTO_TRACE - h256* sig = (h256 const*)_signature.data(); - cout << "---- RECOVER -------------------------------" << endl; - cout << "MSG: " << _message << endl; - cout << "R S V: " << sig[0] << " " << sig[1] << " " << (int)(_signature[64] - 27) << "+27" << endl; - cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl; -#endif + byte encodedpoint[33]; + encodedpoint[0] = recid|2; + memcpy(&encodedpoint[1], _signature.data(), 32); + + ECP::Element x; + secp256k1Params.GetCurve().DecodePoint(x, encodedpoint, 33); + + if (!secp256k1Params.GetCurve().VerifyPoint(x)) + BOOST_THROW_EXCEPTION(InvalidState()); - Public ret; - memcpy(&ret, &(pubkey[1]), sizeof(Public)); - return ret; + Integer rn = r.InverseMod(secp256k1Params.GetGroupOrder()); + Integer u1 = secp256k1Params.GetGroupOrder() - (rn.Times(heInt)).Modulo(secp256k1Params.GetGroupOrder()); + Integer u2 = (rn.Times(s)).Modulo(secp256k1Params.GetGroupOrder()); + + ECP::Point p = secp256k1Params.GetCurve().CascadeMultiply(u2, x, u1, secp256k1Params.GetSubgroupGenerator()); + byte recoveredbytes[65]; + secp256k1Params.GetCurve().EncodePoint(recoveredbytes, p, false); + Public recovered; + memcpy(recovered.data(), &recoveredbytes[1], 64); + return recovered; } bool crypto::verifySecret(Secret const& _s, Public const& _p) diff --git a/test/crypto.cpp b/test/crypto.cpp index a84c1fbb5..4e752fd1a 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -172,19 +172,19 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) Integer nB(fromHex("f2ee15ea639b73fa3db9b34a245bdfa015c260c598b211bf05a1ecc4b3e3b4f2").data(), 32); BOOST_REQUIRE(nHex == nB); - bytes sbytes(fromHex("0x01")); + bytes sbytes(fromHex("0xFFFF")); Secret secret(sha3(sbytes)); // 5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2 KeyPair key(secret); - bytes m(fromHex("0x01")); - int tests = 2; + bytes m(fromHex("0xFF")); + int tests = 3; while (m[0]++, tests--) { h256 hm(sha3(m)); Integer hInt(hm.asBytes().data(), 32); h256 k(hm ^ key.sec()); Integer kInt(k.asBytes().data(), 32); - + // raw sign w/cryptopp (doesn't pass through cryptopp hash filter) ECDSA::Signer signer; pp::initializeDLScheme(key.sec(), signer); From 759b85af9f4bc099420e30bf1ba82a01843caaf6 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 12 Nov 2014 08:32:09 +0000 Subject: [PATCH 22/50] Compilation fixes for windows. --- alethzero/MainWin.cpp | 15 ++++++--------- libdevcore/CommonIO.cpp | 2 +- libdevcore/RLP.h | 3 ++- libdevcrypto/EC.cpp | 8 ++++---- libwhisper/Common.h | 2 +- libwhisper/Message.h | 2 +- 6 files changed, 15 insertions(+), 17 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 155646bcb..40e5da683 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1238,7 +1238,6 @@ void Main::on_blocks_currentItemChanged() auto h = h256((byte const*)hba.data(), h256::ConstructFromPointer); auto details = ethereum()->blockChain().details(h); auto blockData = ethereum()->blockChain().block(h); - auto blockReceipts = ethereum()->blockChain().receipts(h); auto block = RLP(blockData); BlockInfo info(blockData); @@ -1259,17 +1258,10 @@ void Main::on_blocks_currentItemChanged() s << "
Coinbase: " << pretty(info.coinbaseAddress).toHtmlEscaped().toStdString() << " " << info.coinbaseAddress; s << "
Nonce: " << info.nonce << ""; s << "
Parent: " << info.parentHash << ""; - s << "
Bloom: " << details.bloom << ""; +// s << "
Bloom: " << details.bloom << ""; s << "
Log Bloom: " << info.logBloom << ""; s << "
Transactions: " << block[1].itemCount() << " @" << info.transactionsRoot << ""; s << "
Receipts: @" << info.receiptsRoot << ":"; - for (unsigned i = 0; i < blockReceipts.receipts.size(); ++i) - { - s << "
TX: " << toHex(block[1][i].data()) << "
"; - s << "
Receipt: " << toHex(blockReceipts.receipts[i].rlp()) << "
"; - auto r = blockReceipts.receipts[i].rlp(); - s << "
RLP: " << toString(RLP(r)) << "
"; - } s << "
Uncles: " << block[2].itemCount() << " @" << info.sha3Uncles << ""; for (auto u: block[2]) { @@ -1292,6 +1284,7 @@ void Main::on_blocks_currentItemChanged() Transaction tx(block[1][txi].data()); auto ss = tx.safeSender(); h256 th = sha3(rlpList(ss, tx.nonce())); + auto receipt = ethereum()->blockChain().receipts(h).receipts[txi]; s << "

" << th << "

"; s << "

" << h << "[" << txi << "]

"; s << "
From: " << pretty(ss).toHtmlEscaped().toStdString() << " " << ss; @@ -1307,6 +1300,10 @@ void Main::on_blocks_currentItemChanged() s << "
R: " << hex << nouppercase << tx.signature().r << ""; s << "
S: " << hex << nouppercase << tx.signature().s << ""; s << "
Msg: " << tx.sha3(eth::WithoutSignature) << ""; + s << "
Hex: " << toHex(block[1][txi].data()) << "
"; + auto r = receipt.rlp(); + s << "
Receipt: " << toString(RLP(r)) << "
"; + s << "
Receipt-Hex: " << toHex(receipt.rlp()) << "
"; if (tx.isCreation()) { if (tx.data().size()) diff --git a/libdevcore/CommonIO.cpp b/libdevcore/CommonIO.cpp index 3d2eccf13..8fc4fedb3 100644 --- a/libdevcore/CommonIO.cpp +++ b/libdevcore/CommonIO.cpp @@ -30,7 +30,7 @@ string dev::memDump(bytes const& _b, unsigned _w, bool _html) { stringstream ret; if (_html) - ret << "
";
+		ret << "
";
 	for (unsigned i = 0; i < _b.size(); i += _w)
 	{
 		ret << hex << setw(4) << setfill('0') << i << " ";
diff --git a/libdevcore/RLP.h b/libdevcore/RLP.h
index afedc68da..3101f63d6 100644
--- a/libdevcore/RLP.h
+++ b/libdevcore/RLP.h
@@ -158,6 +158,7 @@ public:
 
 	/// Best-effort conversion operators.
 	explicit operator std::string() const { return toString(); }
+	explicit operator bytes() const { return toBytes(); }
 	explicit operator RLPs() const { return toList(); }
 	explicit operator uint8_t() const { return toInt(); }
 	explicit operator uint16_t() const { return toInt(); }
@@ -341,7 +342,7 @@ public:
 	RLPStream& append(char const* _s) { return append(std::string(_s)); }
 	template  RLPStream& append(FixedHash _s, bool _compact = false, bool _allOrNothing = false) { return _allOrNothing && !_s ? append(bytesConstRef()) : append(_s.ref(), _compact); }
 
-	/// Appends an arbitrary RLP fragment - this *must* be a single item.
+	/// Appends an arbitrary RLP fragment - this *must* be a single item unless @a _itemCount is given.
 	RLPStream& append(RLP const& _rlp, unsigned _itemCount = 1) { return appendRaw(_rlp.data(), _itemCount); }
 
 	/// Appends a sequence of data to the stream as a list.
diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp
index af6d0e65e..c35eb17f2 100644
--- a/libdevcrypto/EC.cpp
+++ b/libdevcrypto/EC.cpp
@@ -134,15 +134,15 @@ bool crypto::verify(Signature const& _signature, bytesConstRef _message)
 
 bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed)
 {
-	static size_t derMaxEncodingLength = 72;
+	static const size_t c_derMaxEncodingLength = 72;
 	if (_hashed)
 	{
 		assert(_message.size() == 32);
 		byte encpub[65] = {0x04};
 		memcpy(&encpub[1], _p.data(), 64);
-		byte dersig[derMaxEncodingLength];
-		size_t cssz = DSAConvertSignatureFormat(dersig, derMaxEncodingLength, DSA_DER, _sig.data(), 64, DSA_P1363);
-		assert(cssz <= derMaxEncodingLength);
+		byte dersig[c_derMaxEncodingLength];
+		size_t cssz = DSAConvertSignatureFormat(dersig, c_derMaxEncodingLength, DSA_DER, _sig.data(), 64, DSA_P1363);
+		assert(cssz <= c_derMaxEncodingLength);
 		return (1 == secp256k1_ecdsa_verify(_message.data(), _message.size(), dersig, cssz, encpub, 65));
 	}
 	
diff --git a/libwhisper/Common.h b/libwhisper/Common.h
index f47778afe..436af8d11 100644
--- a/libwhisper/Common.h
+++ b/libwhisper/Common.h
@@ -92,7 +92,7 @@ public:
 	TopicFilter() {}
 	TopicFilter(TopicMask const& _m): m_topicMasks(1, _m) {}
 	TopicFilter(TopicMasks const& _m): m_topicMasks(_m) {}
-	TopicFilter(RLP const& _r): m_topicMasks((TopicMasks)_r) {}
+	TopicFilter(RLP const& _r): m_topicMasks(_r.toVector>>()) {}
 
 	void streamRLP(RLPStream& _s) const { _s << m_topicMasks; }
 	h256 sha3() const;
diff --git a/libwhisper/Message.h b/libwhisper/Message.h
index 3b0d14aae..ed26cf145 100644
--- a/libwhisper/Message.h
+++ b/libwhisper/Message.h
@@ -55,7 +55,7 @@ public:
 	{
 		m_expiry = _m[0].toInt();
 		m_ttl = _m[1].toInt();
-		m_topic = (Topic)_m[2];
+		m_topic = _m[2].toVector();
 		m_data = _m[3].toBytes();
 		m_nonce = _m[4].toInt();
 	}

From 5f83a9d525f292ab37ae0403413f17fdd0bd9458 Mon Sep 17 00:00:00 2001
From: Marek Kotewicz 
Date: Wed, 12 Nov 2014 11:39:42 +0100
Subject: [PATCH 23/50] solidity JSON interface tests

---
 test/solidityJSONInterfaceTest.cpp | 213 +++++++++++++++++++++++++++++
 1 file changed, 213 insertions(+)
 create mode 100644 test/solidityJSONInterfaceTest.cpp

diff --git a/test/solidityJSONInterfaceTest.cpp b/test/solidityJSONInterfaceTest.cpp
new file mode 100644
index 000000000..fec9f7db2
--- /dev/null
+++ b/test/solidityJSONInterfaceTest.cpp
@@ -0,0 +1,213 @@
+/*
+	This file is part of cpp-ethereum.
+
+	cpp-ethereum is free software: you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+
+	cpp-ethereum is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with cpp-ethereum.  If not, see .
+ */
+/**
+ * @author Marek Kotewicz 
+ * @date 2014
+ * Unit tests for the solidity compiler JSON Interface output.
+ */
+
+#include 
+#include 
+#include 
+
+namespace dev
+{
+namespace solidity
+{
+namespace test
+{
+
+class InterfaceChecker {
+public:
+	bool checkInterface(std::string const& _code, std::string const& _expectedInterfaceString)
+	{
+		m_compilerStack.compile(_code);
+		std::string generatedInterfaceString = m_compilerStack.getInterface();
+		Json::Value generatedInterface;
+		m_reader.parse(generatedInterfaceString, generatedInterface);
+		Json::Value expectedInterface;
+		m_reader.parse(_expectedInterfaceString, expectedInterface);
+		return expectedInterface == generatedInterface;
+	}
+	
+private:
+	CompilerStack m_compilerStack;
+	Json::Reader m_reader;
+};
+
+BOOST_FIXTURE_TEST_SUITE(SolidityCompilerJSONInterfaceOutput, InterfaceChecker)
+
+BOOST_AUTO_TEST_CASE(basic_test)
+{
+	char const* sourceCode = "contract test {\n"
+	"  function f(uint a) returns(uint d) { return a * 7; }\n"
+	"}\n";
+
+	char const* interface = R"([
+	{
+		"name": "f",
+		"inputs": [
+		{
+			"name": "a",
+			"type": "uint256"
+		}
+		],
+		"outputs": [
+		{
+			"name": "d",
+			"type": "uint256"
+		}
+		]
+	}
+	])";
+
+	BOOST_CHECK(checkInterface(sourceCode, interface));
+}
+
+BOOST_AUTO_TEST_CASE(empty_contract)
+{
+	char const* sourceCode = "contract test {\n"
+	"}\n";
+
+	char const* interface = "[]";
+
+	BOOST_CHECK(checkInterface(sourceCode, interface));
+}
+
+BOOST_AUTO_TEST_CASE(multiple_methods)
+{
+	char const* sourceCode = "contract test {\n"
+	"  function f(uint a) returns(uint d) { return a * 7; }\n"
+	"  function g(uint b) returns(uint e) { return b * 8; }\n"
+	"}\n";
+	
+	char const* interface = R"([
+	{
+		"name": "f",
+		"inputs": [
+		{
+			"name": "a",
+			"type": "uint256"
+		}
+		],
+		"outputs": [
+		{
+			"name": "d",
+			"type": "uint256"
+		}
+		]
+	},
+	{
+		"name": "g",
+		"inputs": [
+		{
+			"name": "b",
+			"type": "uint256"
+		}
+		],
+		"outputs": [
+		{
+			"name": "e",
+			"type": "uint256"
+		}
+		]
+	}
+	])";
+
+	BOOST_CHECK(checkInterface(sourceCode, interface));
+}
+
+BOOST_AUTO_TEST_CASE(multiple_params)
+{
+	char const* sourceCode = "contract test {\n"
+	"  function f(uint a, uint b) returns(uint d) { return a + b; }\n"
+	"}\n";
+
+	char const* interface = R"([
+	{
+		"name": "f",
+		"inputs": [
+		{
+			"name": "a",
+			"type": "uint256"
+		},
+		{
+			"name": "b",
+			"type": "uint256"
+		}
+		],
+		"outputs": [
+		{
+			"name": "d",
+			"type": "uint256"
+		}
+		]
+	}
+	])";
+
+	BOOST_CHECK(checkInterface(sourceCode, interface));
+}
+
+BOOST_AUTO_TEST_CASE(multiple_methods_order)
+{
+	// methods are expected to be in alpabetical order
+	char const* sourceCode = "contract test {\n"
+	"  function f(uint a) returns(uint d) { return a * 7; }\n"
+	"  function c(uint b) returns(uint e) { return b * 8; }\n"
+	"}\n";
+		
+	char const* interface = R"([
+	{
+		"name": "c",
+		"inputs": [
+		{
+			"name": "b",
+			"type": "uint256"
+		}
+		],
+		"outputs": [
+		{
+			"name": "e",
+			"type": "uint256"
+		}
+		]
+	},
+	{
+		"name": "f",
+		"inputs": [
+		{
+			"name": "a",
+			"type": "uint256"
+		}
+		],
+		"outputs": [
+		{
+			"name": "d",
+			"type": "uint256"
+		}
+		]
+	}
+	])";
+	
+	BOOST_CHECK(checkInterface(sourceCode, interface));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+}
+}
+}

From d1824e31ef461c42ae844285b1b510c7300b6d65 Mon Sep 17 00:00:00 2001
From: Marek Kotewicz 
Date: Wed, 12 Nov 2014 13:00:11 +0100
Subject: [PATCH 24/50] solidity json interface tests fixes

---
 test/solidityJSONInterfaceTest.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/test/solidityJSONInterfaceTest.cpp b/test/solidityJSONInterfaceTest.cpp
index fec9f7db2..1a443087f 100644
--- a/test/solidityJSONInterfaceTest.cpp
+++ b/test/solidityJSONInterfaceTest.cpp
@@ -20,9 +20,9 @@
  * Unit tests for the solidity compiler JSON Interface output.
  */
 
+#include 
 #include 
 #include 
-#include 
 
 namespace dev
 {
@@ -31,11 +31,12 @@ namespace solidity
 namespace test
 {
 
-class InterfaceChecker {
+class InterfaceChecker
+{
 public:
 	bool checkInterface(std::string const& _code, std::string const& _expectedInterfaceString)
 	{
-		m_compilerStack.compile(_code);
+		m_compilerStack.parse(_code);
 		std::string generatedInterfaceString = m_compilerStack.getInterface();
 		Json::Value generatedInterface;
 		m_reader.parse(generatedInterfaceString, generatedInterface);

From fab63ce0a086f0e261a3c0abda69bb19a6e4eb1c Mon Sep 17 00:00:00 2001
From: subtly 
Date: Thu, 13 Nov 2014 02:00:19 +0100
Subject: [PATCH 25/50] refactor and thread-safe cryptopp. for now, remove
 secp256klib calls. ecdh and tests. move sha3mac into sha3.

---
 libdevcrypto/AES.cpp      |  17 +++-
 libdevcrypto/AES.h        |   5 +-
 libdevcrypto/All.h        |   7 +-
 libdevcrypto/Common.cpp   | 103 +++++++++++--------
 libdevcrypto/Common.h     |  11 +-
 libdevcrypto/CryptoPP.cpp | 192 ++++++++++++++++++++++++++++++++---
 libdevcrypto/CryptoPP.h   |  90 ++++++++++++-----
 libdevcrypto/EC.cpp       | 208 --------------------------------------
 libdevcrypto/EC.h         |  62 ------------
 libdevcrypto/ECDHE.cpp    |  31 ++++--
 libdevcrypto/ECDHE.h      |   4 +-
 libdevcrypto/SHA3.cpp     |  10 ++
 libdevcrypto/SHA3.h       |   3 +
 libdevcrypto/SHA3MAC.cpp  |  40 --------
 libdevcrypto/SHA3MAC.h    |  38 -------
 libethcore/CommonEth.cpp  |  27 -----
 libethereum/State.cpp     |   4 -
 test/crypto.cpp           | 143 +++++++++-----------------
 18 files changed, 414 insertions(+), 581 deletions(-)
 delete mode 100644 libdevcrypto/EC.cpp
 delete mode 100644 libdevcrypto/EC.h
 delete mode 100644 libdevcrypto/SHA3MAC.cpp
 delete mode 100644 libdevcrypto/SHA3MAC.h

diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp
index fc0cf15c4..1807bad19 100644
--- a/libdevcrypto/AES.cpp
+++ b/libdevcrypto/AES.cpp
@@ -23,14 +23,21 @@
 #include "AES.h"
 
 using namespace std;
+using namespace dev;
+using namespace dev::crypto;
 using namespace dev::crypto::aes;
-using namespace dev::crypto::pp;
 using namespace CryptoPP;
 
+struct aes::Aes128Ctr
+{
+	Aes128Ctr(h128 _k) { mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data()); }
+	CryptoPP::CTR_Mode::Encryption mode;
+};
+
 Stream::Stream(StreamType _t, h128 _ckey):
 	m_cSecret(_ckey)
 {
-	(void)_t; // encrypt and decrypt are same operation w/ctr mode
+	(void)_t; // encrypt and decrypt are same operation w/ctr
 	cryptor = new Aes128Ctr(_ckey);
 }
 
@@ -39,13 +46,13 @@ Stream::~Stream()
 	delete cryptor;
 }
 
-void Stream::update(bytesRef io_bytes)
+void Stream::update(bytesRef)
 {
 
 }
 
-size_t Stream::streamOut(bytes& o_bytes)
+size_t Stream::streamOut(bytes&)
 {
-	
+	return 0;
 }
 
diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h
index 753dcd14b..2bb852653 100644
--- a/libdevcrypto/AES.h
+++ b/libdevcrypto/AES.h
@@ -29,10 +29,10 @@ namespace dev
 {
 namespace crypto
 {
-namespace pp { struct Aes128Ctr; }
 namespace aes
 {
 
+struct Aes128Ctr;
 enum StreamType { Encrypt, Decrypt };
 	
 /**
@@ -54,8 +54,9 @@ private:
 	h128 m_cSecret;
 	bytes m_text;
 
-	pp::Aes128Ctr* cryptor;
+	Aes128Ctr* cryptor;
 };
+	
 
 /**
  * @brief Encrypted stream with inband SHA3 mac at specific interval.
diff --git a/libdevcrypto/All.h b/libdevcrypto/All.h
index 8018db4fb..9070725e9 100644
--- a/libdevcrypto/All.h
+++ b/libdevcrypto/All.h
@@ -1,11 +1,8 @@
 #pragma once
 
 #include "Common.h"
-#include "EC.h"
+#include "AES.h"
+#include "ECDHE.h"
 #include "FileSystem.h"
-#include "MemoryDB.h"
-#include "OverlayDB.h"
 #include "SHA3.h"
-#include "SHA3MAC.h"
-#include "TrieCommon.h"
 #include "TrieDB.h"
diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp
index d82098655..2a105ff25 100644
--- a/libdevcrypto/Common.cpp
+++ b/libdevcrypto/Common.cpp
@@ -22,70 +22,46 @@
 
 #include 
 #include 
-#include "EC.h"
 #include "SHA3.h"
 #include "FileSystem.h"
+#include "CryptoPP.h"
 #include "Common.h"
 using namespace std;
 using namespace dev;
-using namespace crypto;
+using namespace dev::crypto;
 
-//#define ETH_ADDRESS_DEBUG 1
+static Secp256k1 s_secp256k1;
 
-Address dev::toAddress(Secret _secret)
+Public dev::toPublic(Secret _secret)
 {
-	return KeyPair(_secret).address();
+	Public p;
+	s_secp256k1.toPublic(_secret, p);
+	return std::move(p);
 }
 
-KeyPair KeyPair::create()
+Address dev::toAddress(Public _public)
 {
-	static mt19937_64 s_eng(time(0));
-	uniform_int_distribution d(0, 255);
-
-	for (int i = 0; i < 100; ++i)
-	{
-		h256 sec;
-		for (unsigned i = 0; i < 32; ++i)
-			sec[i] = (byte)d(s_eng);
-
-		KeyPair ret(sec);
-		if (ret.address())
-			return ret;
-	}
-	return KeyPair();
-}
-
-KeyPair::KeyPair(h256 _sec):
-	m_secret(_sec)
-{
-	toPublic(m_secret, m_public);
-	if (verifySecret(m_secret, m_public))
-		m_address = right160(dev::sha3(m_public.ref()));
-	
-#if ETH_ADDRESS_DEBUG
-	cout << "---- ADDRESS -------------------------------" << endl;
-	cout << "SEC: " << m_secret << endl;
-	cout << "PUB: " << m_public << endl;
-	cout << "ADR: " << m_address << endl;
-#endif
+	return s_secp256k1.toAddress(_public);
 }
 
-KeyPair KeyPair::fromEncryptedSeed(bytesConstRef _seed, std::string const& _password)
+Address dev::toAddress(Secret _secret)
 {
-	return KeyPair(sha3(aesDecrypt(_seed, _password)));
+	Public p;
+	s_secp256k1.toPublic(_secret, p);
+	return s_secp256k1.toAddress(p);
 }
 
 void dev::encrypt(Public _k, bytesConstRef _plain, bytes& o_cipher)
 {
 	bytes io = _plain.toBytes();
-	crypto::encrypt(_k, io);
+	s_secp256k1.encrypt(_k, io);
 	o_cipher = std::move(io);
 }
 
 bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext)
 {
 	bytes io = _cipher.toBytes();
-	crypto::decrypt(_k, io);
+	s_secp256k1.decrypt(_k, io);
 	if (io.empty())
 		return false;
 	o_plaintext = std::move(io);
@@ -94,17 +70,60 @@ bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext)
 
 Public dev::recover(Signature _sig, h256 _message)
 {
-	return crypto::recover(_sig, _message.ref());
+	return s_secp256k1.recover(_sig, _message.ref());
 }
 
 Signature dev::sign(Secret _k, h256 _hash)
 {
-	return crypto::sign(_k, _hash);
+	return s_secp256k1.sign(_k, _hash);
 }
 
 bool dev::verify(Public _p, Signature _s, h256 _hash)
 {
-	return crypto::verify(_p, _s, bytesConstRef(_hash.data(), 32), true);
+	return s_secp256k1.verify(_p, _s, bytesConstRef(_hash.data(), 32), true);
+}
+
+KeyPair KeyPair::create()
+{
+	static mt19937_64 s_eng(time(0));
+	uniform_int_distribution d(0, 255);
+
+	for (int i = 0; i < 100; ++i)
+	{
+		h256 sec;
+		for (unsigned i = 0; i < 32; ++i)
+			sec[i] = (byte)d(s_eng);
+
+		KeyPair ret(sec);
+		if (ret.address())
+			return ret;
+	}
+	return KeyPair();
+}
+
+KeyPair::KeyPair(h256 _sec):
+	m_secret(_sec)
+{
+	if (s_secp256k1.verifySecret(m_secret, m_public))
+		m_address = s_secp256k1.toAddress(m_public);
+}
+
+KeyPair KeyPair::fromEncryptedSeed(bytesConstRef _seed, std::string const& _password)
+{
+	return KeyPair(sha3(aesDecrypt(_seed, _password)));
+}
+
+h256 crypto::kdf(Secret const& _priv, h256 const& _hash)
+{
+	// H(H(r||k)^h)
+	h256 s;
+	sha3mac(Nonce::get().ref(), _priv.ref(), s.ref());
+	s ^= _hash;
+	sha3(s.ref(), s.ref());
+	
+	if (!s || !_hash || !_priv)
+		BOOST_THROW_EXCEPTION(InvalidState());
+	return std::move(s);
 }
 
 h256 Nonce::get(bool _commit)
diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h
index e95eefa40..cd0996826 100644
--- a/libdevcrypto/Common.h
+++ b/libdevcrypto/Common.h
@@ -30,7 +30,7 @@
 
 namespace dev
 {
-
+	
 /// A secret key: 32 bytes.
 /// @NOTE This is not endian-specific; it's just a bunch of bytes.
 using Secret = h256;
@@ -59,6 +59,12 @@ using AddressSet = std::set;
 using Secrets = h256s;
 
 /// Convert a secret key into the public key equivalent.
+Public toPublic(Secret _secret);
+
+/// Convert a public key to address.
+Address toAddress(Public _public);
+
+/// Convert a secret key into address of public key equivalent.
 /// @returns 0 if it's not a valid secret key.
 Address toAddress(Secret _secret);
 
@@ -119,6 +125,9 @@ namespace crypto
 {
 struct InvalidState: public dev::Exception {};
 
+/// Key derivation
+h256 kdf(Secret const& _priv, h256 const& _hash);
+	
 /**
  * @brief Generator for nonce material
  */
diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp
index 0694699ae..1edddefa1 100644
--- a/libdevcrypto/CryptoPP.cpp
+++ b/libdevcrypto/CryptoPP.cpp
@@ -21,35 +21,203 @@
 
 #include "CryptoPP.h"
 
+using namespace std;
 using namespace dev;
 using namespace dev::crypto;
 using namespace CryptoPP;
 
+static_assert(dev::Secret::size == 32, "Secret key must be 32 bytes.");
+static_assert(dev::Public::size == 64, "Public key must be 64 bytes.");
+static_assert(dev::Signature::size == 65, "Signature must be 65 bytes.");
 
-/// Integer and Point Conversion:
+void Secp256k1::encrypt(Public const& _k, bytes& io_cipher)
+{
+	ECIES::Encryptor e;
+	initializeDLScheme(_k, e);
 
-void pp::exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& _p)
+	size_t plen = io_cipher.size();
+	bytes ciphertext;
+	ciphertext.resize(e.CiphertextLength(plen));
+	
+	{
+		lock_guard l(x_rng);
+		e.Encrypt(m_rng, io_cipher.data(), plen, ciphertext.data());
+	}
+	
+	memset(io_cipher.data(), 0, io_cipher.size());
+	io_cipher = std::move(ciphertext);
+}
+
+void Secp256k1::decrypt(Secret const& _k, bytes& io_text)
 {
-	bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true));
+	CryptoPP::ECIES::Decryptor d;
+	initializeDLScheme(_k, d);
+	
+	size_t clen = io_text.size();
+	bytes plain;
+	plain.resize(d.MaxPlaintextLength(io_text.size()));
 	
-	secp256k1Params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false);
+	DecodingResult r;
+	{
+		lock_guard l(x_rng);
+		r = d.Decrypt(m_rng, io_text.data(), clen, plain.data());
+	}
+	
+	if (!r.isValidCoding)
+	{
+		io_text.clear();
+		return;
+	}
+	
+	io_text.resize(r.messageLength);
+	io_text = std::move(plain);
+}
 
-	assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true));
-	memcpy(_p.data(), &prefixedKey[1], Public::size);
+Signature Secp256k1::sign(Secret const& _k, bytesConstRef _message)
+{
+	return sign(_k, sha3(_message));
 }
 
-void pp::exponentToPublic(Integer const& _e, Public& _p)
+Signature Secp256k1::sign(Secret const& _key, h256 const& _hash)
 {
-	CryptoPP::DL_PublicKey_EC pk;
-	pk.Initialize(secp256k1Params, secp256k1Params.ExponentiateBase(_e));
-	pp::exportPublicKey(pk, _p);
+	Signature sig;
+	
+	Integer k(kdf(_key, _hash).data(), 32);
+	if (k == 0)
+		BOOST_THROW_EXCEPTION(InvalidState());
+	k = 1 + (k % (m_qs - 1));
+	
+	ECP::Point rp;
+	Integer r;
+	{
+		lock_guard l(x_params);
+		rp = m_params.ExponentiateBase(k);
+		r = m_params.ConvertElementToInteger(rp);
+	}
+	sig[64] = 0;
+//	sig[64] = (r >= m_q) ? 2 : 0;
+	
+	Integer kInv = k.InverseMod(m_q);
+	Integer z(_hash.asBytes().data(), 32);
+	Integer s = (kInv * (Integer(_key.asBytes().data(), 32)*r + z)) % m_q;
+	if (r == 0 || s == 0)
+		BOOST_THROW_EXCEPTION(InvalidState());
+	
+//	if (s > m_qs)
+//	{
+//		s = m_q - s;
+//		if (sig[64])
+//			sig[64] ^= 1;
+//	}
+	
+	sig[64] |= rp.y.IsOdd() ? 1 : 0;
+	r.Encode(sig.data(), 32);
+	s.Encode(sig.data() + 32, 32);
+	return sig;
 }
 
-void pp::ecdhAgree(Secret const& _s, Public const& _r, h256& o_s)
+bool Secp256k1::verify(Signature const& _signature, bytesConstRef _message)
 {
-	ECDH::Domain d(secp256k1Curve);
+	return !!recover(_signature, _message);
+}
+
+bool Secp256k1::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed)
+{
+	// todo: verify w/o recovery (if faster)
+	return _p == _hashed ? recover(_sig, _message) : recover(_sig, sha3(_message).ref());
+}
+
+Public Secp256k1::recover(Signature _signature, bytesConstRef _message)
+{
+	Public recovered;
+	
+	Integer r(_signature.data(), 32);
+	Integer s(_signature.data()+32, 32);
+	// cryptopp encodes sign of y as 0x02/0x03 instead of 0/1 or 27/28
+	byte encodedpoint[33];
+	encodedpoint[0] = _signature[64]|2;
+	memcpy(&encodedpoint[1], _signature.data(), 32);
+	
+	ECP::Element x;
+	{
+		lock_guard l(x_curve);
+		m_curve.DecodePoint(x, encodedpoint, 33);
+		if (!m_curve.VerifyPoint(x))
+			return recovered;
+	}
+	
+//	if (_signature[64] & 2)
+//	{
+//		r += m_q;
+//		lock_guard l(x_params);
+//		if (r >= m_params.GetMaxExponent())
+//			return recovered;
+//	}
+	
+	Integer z(_message.data(), 32);
+	Integer rn = r.InverseMod(m_q);
+	Integer u1 = m_q - (rn.Times(z)).Modulo(m_q);
+	Integer u2 = (rn.Times(s)).Modulo(m_q);
+	
+	ECP::Point p;
+	byte recoveredbytes[65];
+	{
+		lock_guard l(x_curve);
+		// todo: make generator member
+		p = m_curve.CascadeMultiply(u2, x, u1, m_params.GetSubgroupGenerator());
+		m_curve.EncodePoint(recoveredbytes, p, false);
+	}
+	memcpy(recovered.data(), &recoveredbytes[1], 64);
+	return recovered;
+}
+
+bool Secp256k1::verifySecret(Secret const& _s, Public& _p)
+{
+	DL_PrivateKey_EC k;
+	k.Initialize(m_params, secretToExponent(_s));
+	if (!k.Validate(m_rng, 3))
+		return false;
+	
+	DL_PublicKey_EC pub;
+	k.MakePublicKey(pub);
+	if (!k.Validate(m_rng, 3))
+		return false;
+
+	exportPublicKey(pub, _p);
+	return true;
+}
+
+void Secp256k1::agree(Secret const& _s, Public const& _r, h256& o_s)
+{
+	ECDH::Domain d(m_oid);
 	assert(d.AgreedValueLength() == sizeof(o_s));
 	byte remote[65] = {0x04};
 	memcpy(&remote[1], _r.data(), 64);
 	assert(d.Agree(o_s.data(), _s.data(), remote));
 }
+
+void Secp256k1::exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& _p)
+{
+	bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true));
+	
+	{
+		lock_guard l(x_params);
+		m_params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false);
+		assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true));
+	}
+
+	memcpy(_p.data(), &prefixedKey[1], Public::size);
+}
+
+void Secp256k1::exponentToPublic(Integer const& _e, Public& _p)
+{
+	CryptoPP::DL_PublicKey_EC pk;
+	
+	{
+		lock_guard l(x_params);
+		pk.Initialize(m_params, m_params.ExponentiateBase(_e));
+	}
+	
+	exportPublicKey(pk, _p);
+}
+
diff --git a/libdevcrypto/CryptoPP.h b/libdevcrypto/CryptoPP.h
index 1ae4bee74..b8c1272d9 100644
--- a/libdevcrypto/CryptoPP.h
+++ b/libdevcrypto/CryptoPP.h
@@ -23,6 +23,7 @@
 
 #pragma once
 
+#include 
 // need to leave this one disabled for link-time. blame cryptopp.
 #pragma GCC diagnostic ignored "-Wunused-function"
 #pragma warning(push)
@@ -48,50 +49,85 @@
 #include 
 #pragma warning(pop)
 #pragma GCC diagnostic pop
+#include "SHA3.h"
 #include "Common.h"
 
 namespace dev
 {
 namespace crypto
 {
-namespace pp
-{
-	
+
 using namespace CryptoPP;
+
+inline ECP::Point publicToPoint(Public const& _p) { Integer x(_p.data(), 32); Integer y(_p.data() + 32, 32); return std::move(ECP::Point(x,y)); }
+
+inline Integer secretToExponent(Secret const& _s) { return std::move(Integer(_s.data(), Secret::size)); }
 	
-/// CryptoPP random number pool
-static CryptoPP::AutoSeededRandomPool PRNG;
+/**
+ * CryptoPP secp256k1 algorithms.
+ */
+class Secp256k1
+{	
+public:
+	Secp256k1(): m_oid(ASN1::secp256k1()), m_params(m_oid), m_curve(m_params.GetCurve()), m_q(m_params.GetGroupOrder()), m_qs(m_params.GetSubgroupOrder()) {}
 	
-/// CryptoPP EC Cruve
-static const CryptoPP::OID secp256k1Curve = CryptoPP::ASN1::secp256k1();
+	Address toAddress(Public const& _p) { return right160(sha3(_p.ref())); }
 	
-static const CryptoPP::DL_GroupParameters_EC secp256k1Params(secp256k1Curve);
+	void toPublic(Secret const& _s, Public& o_public) { exponentToPublic(Integer(_s.data(), sizeof(_s)), o_public); }
 	
-static ECP::Point publicToPoint(Public const& _p) { Integer x(_p.data(), 32); Integer y(_p.data() + 32, 32); return std::move(ECP::Point(x,y)); }
+	/// Encrypts text (replace input).
+	void encrypt(Public const& _k, bytes& io_cipher);
 	
-static Integer secretToExponent(Secret const& _s) { return std::move(Integer(_s.data(), Secret::size)); }
-
-void exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& _p);
-
-static void exportPrivateKey(CryptoPP::DL_PrivateKey_EC const& _k, Secret& _s) { _k.GetPrivateExponent().Encode(_s.data(), Secret::size); }
+	/// Decrypts text (replace input).
+	void decrypt(Secret const& _k, bytes& io_text);
 	
-void exponentToPublic(Integer const& _e, Public& _p);
-
-void ecdhAgree(Secret const& _s, Public const& _r, h256& o_s);
-
-template 
-void initializeDLScheme(Secret const& _s, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, secretToExponent(_s)); }
+	/// @returns siganture of message.
+	Signature sign(Secret const& _k, bytesConstRef _message);
 	
-template 
-void initializeDLScheme(Public const& _p, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, publicToPoint(_p)); }
+	/// @returns compact siganture of message hash.
+	Signature sign(Secret const& _k, h256 const& _hash);
 	
-struct Aes128Ctr
-{
-	Aes128Ctr(h128 _k) { mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data()); }
-	CTR_Mode::Encryption mode;
+	/// Verify compact signature (public key is extracted from message).
+	bool verify(Signature const& _signature, bytesConstRef _message);
+	
+	/// Verify signature.
+	bool verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed = false);
+	
+	/// Recovers public key from compact signature. Uses libsecp256k1.
+	Public recover(Signature _signature, bytesConstRef _message);
+	
+	/// Verify secret key is valid.
+	bool verifySecret(Secret const& _s, Public& o_p);
+	
+	void agree(Secret const& _s, Public const& _r, h256& o_s);
+	
+protected:
+	void exportPrivateKey(DL_PrivateKey_EC const& _k, Secret& _s) { _k.GetPrivateExponent().Encode(_s.data(), Secret::size); }
+	
+	void exportPublicKey(DL_PublicKey_EC const& _k, Public& _p);
+	
+	void exponentToPublic(Integer const& _e, Public& _p);
+	
+	template  void initializeDLScheme(Secret const& _s, T& io_operator) { std::lock_guard l(x_params); io_operator.AccessKey().Initialize(m_params, secretToExponent(_s)); }
+	
+	template  void initializeDLScheme(Public const& _p, T& io_operator) { std::lock_guard l(x_params); io_operator.AccessKey().Initialize(m_params, publicToPoint(_p)); }
+	
+private:
+	OID m_oid;
+	
+	std::mutex x_rng;
+	AutoSeededRandomPool m_rng;
+	
+	std::mutex x_params;
+	DL_GroupParameters_EC m_params;
+	
+	std::mutex x_curve;
+	DL_GroupParameters_EC::EllipticCurve m_curve;
+	
+	Integer m_q;
+	Integer m_qs;
 };
 
 }
 }
-}
 
diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp
deleted file mode 100644
index a509a5b41..000000000
--- a/libdevcrypto/EC.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- This file is part of cpp-ethereum.
-
- cpp-ethereum is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- cpp-ethereum is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with cpp-ethereum.  If not, see .
- */
-/** @file EC.cpp
- * @author Alex Leverington 
- * @date 2014
- *
- * ECDSA, ECIES
- */
-
-#include 
-#include "CryptoPP.h"
-#include "SHA3.h"
-#include "SHA3MAC.h"
-#include "EC.h"
-
-static_assert(dev::Secret::size == 32, "Secret key must be 32 bytes.");
-static_assert(dev::Public::size == 64, "Public key must be 64 bytes.");
-static_assert(dev::Signature::size == 65, "Signature must be 65 bytes.");
-
-using namespace std;
-using namespace dev;
-using namespace dev::crypto;
-using namespace CryptoPP;
-using namespace pp;
-
-void crypto::toPublic(Secret const& _s, Public& o_public)
-{
-	exponentToPublic(Integer(_s.data(), sizeof(_s)), o_public);
-}
-
-h256 crypto::kdf(Secret const& _priv, h256 const& _hash)
-{
-	// H(H(r||k)^h)
-	h256 s;
-	sha3mac(Nonce::get().ref(), _priv.ref(), s.ref());
-	s ^= _hash;
-	sha3(s.ref(), s.ref());
-	
-	if (!s || !_hash || !_priv)
-		BOOST_THROW_EXCEPTION(InvalidState());
-	return std::move(s);
-}
-
-void crypto::encrypt(Public const& _k, bytes& io_cipher)
-{
-	ECIES::Encryptor e;
-	initializeDLScheme(_k, e);
-	size_t plen = io_cipher.size();
-	bytes c;
-	c.resize(e.CiphertextLength(plen));
-	// todo: use StringSource with io_cipher as input and output.
-	e.Encrypt(PRNG, io_cipher.data(), plen, c.data());
-	memset(io_cipher.data(), 0, io_cipher.size());
-	io_cipher = std::move(c);
-}
-
-void crypto::decrypt(Secret const& _k, bytes& io_text)
-{
-	CryptoPP::ECIES::Decryptor d;
-	initializeDLScheme(_k, d);
-	size_t clen = io_text.size();
-	bytes p;
-	p.resize(d.MaxPlaintextLength(io_text.size()));
-	// todo: use StringSource with io_text as input and output.
-	DecodingResult r = d.Decrypt(PRNG, io_text.data(), clen, p.data());
-	if (!r.isValidCoding)
-	{
-		io_text.clear();
-		return;
-	}
-	io_text.resize(r.messageLength);
-	io_text = std::move(p);
-}
-
-Signature crypto::sign(Secret const& _k, bytesConstRef _message)
-{
-	return crypto::sign(_k, sha3(_message));
-}
-
-Signature crypto::sign(Secret const& _key, h256 const& _hash)
-{
-	ECDSA::Signer signer;
-	initializeDLScheme(_key, signer);
-
-	Integer const& q = secp256k1Params.GetGroupOrder();
-	Integer const& qs = secp256k1Params.GetSubgroupOrder();
-	Integer e(_hash.asBytes().data(), 32);
-
-	Integer k(kdf(_key, _hash).data(), 32);
-	if (k == 0)
-		BOOST_THROW_EXCEPTION(InvalidState());
-	k = 1 + (k % (qs - 1));
-	
-	ECP::Point rp = secp256k1Params.ExponentiateBase(k);
-	Integer r = secp256k1Params.ConvertElementToInteger(rp);
-	int recid = ((r >= q) ? 2 : 0) | (rp.y.IsOdd() ? 1 : 0);
-	
-	Integer kInv = k.InverseMod(q);
-	Integer s = (kInv * (Integer(_key.asBytes().data(), 32)*r + e)) % q;
-	assert(!!r && !!s);
-	
-	if (s > qs)
-	{
-		s = q - s;
-		if (recid)
-			recid ^= 1;
-	}
-	
-	Signature sig;
-	r.Encode(sig.data(), 32);
-	s.Encode(sig.data() + 32, 32);
-	sig[64] = recid;
-	return sig;
-}
-
-bool crypto::verify(Signature const& _signature, bytesConstRef _message)
-{
-	return crypto::verify(crypto::recover(_signature, _message), _signature, _message);
-}
-
-bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed)
-{
-	static size_t derMaxEncodingLength = 72;
-	if (_hashed)
-	{
-		assert(_message.size() == 32);
-		byte encpub[65] = {0x04};
-		memcpy(&encpub[1], _p.data(), 64);
-		byte dersig[derMaxEncodingLength];
-		size_t cssz = DSAConvertSignatureFormat(dersig, derMaxEncodingLength, DSA_DER, _sig.data(), 64, DSA_P1363);
-		assert(cssz <= derMaxEncodingLength);
-		return (1 == secp256k1_ecdsa_verify(_message.data(), _message.size(), dersig, cssz, encpub, 65));
-	}
-	
-	ECDSA::Verifier verifier;
-	initializeDLScheme(_p, verifier);
-	return verifier.VerifyMessage(_message.data(), _message.size(), _sig.data(), sizeof(Signature) - 1);
-}
-
-Public crypto::recover(Signature _signature, bytesConstRef _message)
-{
-	Integer heInt(_message.data(), 32);
-	
-	// a different curve would require additional check for v (aka, recid)
-	Integer r(_signature.data(), 32);
-	Integer s(_signature.data()+32, 32);
-	unsigned recid = _signature[64];
-	
-	byte encodedpoint[33];
-	encodedpoint[0] = recid|2;
-	memcpy(&encodedpoint[1], _signature.data(), 32);
-
-	ECP::Element x;
-	secp256k1Params.GetCurve().DecodePoint(x, encodedpoint, 33);
-
-	if (!secp256k1Params.GetCurve().VerifyPoint(x))
-		BOOST_THROW_EXCEPTION(InvalidState());
-	
-	Integer rn = r.InverseMod(secp256k1Params.GetGroupOrder());
-	Integer u1 = secp256k1Params.GetGroupOrder() - (rn.Times(heInt)).Modulo(secp256k1Params.GetGroupOrder());
-	Integer u2 = (rn.Times(s)).Modulo(secp256k1Params.GetGroupOrder());
-
-	ECP::Point p = secp256k1Params.GetCurve().CascadeMultiply(u2, x, u1, secp256k1Params.GetSubgroupGenerator());
-	byte recoveredbytes[65];
-	secp256k1Params.GetCurve().EncodePoint(recoveredbytes, p, false);
-	Public recovered;
-	memcpy(recovered.data(), &recoveredbytes[1], 64);
-	return recovered;
-}
-
-bool crypto::verifySecret(Secret const& _s, Public const& _p)
-{
-	secp256k1_start();
-	int ok = secp256k1_ecdsa_seckey_verify(_s.data());
-	if (!ok)
-		return false;
-	
-	int pubkeylen = 65;
-	byte pubkey[pubkeylen];
-	ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _s.data(), 0);
-	if (!ok || pubkeylen != 65)
-		return false;
-	
-	ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65);
-	if (!ok)
-		return false;
-	
-	for (int i = 0; i < 32; i++)
-		if (pubkey[i+1]!=_p[i])
-			return false;
-
-	return true;
-}
-
diff --git a/libdevcrypto/EC.h b/libdevcrypto/EC.h
deleted file mode 100644
index 2a4155edf..000000000
--- a/libdevcrypto/EC.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- This file is part of cpp-ethereum.
-
- cpp-ethereum is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- cpp-ethereum is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with cpp-ethereum.  If not, see .
- */
-/** @file EC.h
- * @author Alex Leverington 
- * @date 2014
- *
- * ECDSA, ECIES
- */
-
-#pragma once
-
-#include "Common.h"
-
-namespace dev
-{
-namespace crypto
-{
-
-void toPublic(Secret const& _s, Public& o_public);
-h256 kdf(Secret const& _priv, h256 const& _hash);
-	
-/// Encrypts text (in place).
-void encrypt(Public const& _k, bytes& io_cipher);
-
-/// Decrypts text (in place).
-void decrypt(Secret const& _k, bytes& io_text);
-
-/// Returns siganture of message.
-Signature sign(Secret const& _k, bytesConstRef _message);
-	
-/// Returns compact siganture of message hash.
-Signature sign(Secret const& _k, h256 const& _hash);
-
-/// Verify compact signature (public key is extracted from message).
-bool verify(Signature const& _signature, bytesConstRef _message);
-	
-/// Verify signature.
-bool verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed = false);
-
-/// Recovers public key from compact signature. Uses libsecp256k1.
-Public recover(Signature _signature, bytesConstRef _message);
-
-bool verifySecret(Secret const& _s, Public const& _p);
-	
-}
-	
-}
-
diff --git a/libdevcrypto/ECDHE.cpp b/libdevcrypto/ECDHE.cpp
index 6b3979874..d6874fa33 100644
--- a/libdevcrypto/ECDHE.cpp
+++ b/libdevcrypto/ECDHE.cpp
@@ -20,14 +20,14 @@
  */
 
 #include "SHA3.h"
-#include "SHA3MAC.h"
 #include "CryptoPP.h"
 #include "ECDHE.h"
 
 using namespace std;
 using namespace dev;
 using namespace dev::crypto;
-using namespace dev::crypto::pp;
+
+static Secp256k1 s_secp256k1;
 
 void ECDHE::agree(Public const& _remote, Secret& o_sharedSecret)
 {
@@ -36,12 +36,12 @@ void ECDHE::agree(Public const& _remote, Secret& o_sharedSecret)
 		BOOST_THROW_EXCEPTION(InvalidState());
 	
 	m_remoteEphemeral = _remote;
-	ecdhAgree(m_ephemeral.sec(), m_remoteEphemeral, o_sharedSecret);
+	s_secp256k1.agree(m_ephemeral.sec(), m_remoteEphemeral, o_sharedSecret);
 }
 
 void ECDHEKeyExchange::agree(Public const& _remoteEphemeral)
 {
-	ecdhAgree(m_ephemeral.sec(), _remoteEphemeral, m_ephemeralSecret);
+	s_secp256k1.agree(m_ephemeral.sec(), _remoteEphemeral, m_ephemeralSecret);
 }
 
 void ECDHEKeyExchange::exchange(bytes& o_exchange)
@@ -50,16 +50,29 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange)
 		// didn't agree on public remote
 		BOOST_THROW_EXCEPTION(InvalidState());
 
+	// The key exchange payload is in two parts and is encrypted
+	// using ephemeral keypair.
+	//
+	// The first part is the 'prefix' which is a zero-knowledge proof
+	// allowing the remote to resume or emplace a previous session.
+	// If a session previously exists:
+	//	prefix is sha3(token) // todo: ephemeral entropy from both sides
+	// If a session doesn't exist:
+	//	prefix is sha3mac(m_ephemeralSecret,
+	//
+	// The second part is encrypted using the public key which relates to the prefix.
+	
 	Public encpk = m_known.first|m_remoteEphemeral;
 	bytes exchange(encpk.asBytes());
 	
 	// This is the public key which we would like the remote to use,
-	// which maybe different than previously-known public key.
-	// Here we would pick an appropriate alias or generate a new one,
+	// which maybe different than the previously-known public key.
+	//
+	// Here we should pick an appropriate alias or generate a new one,
 	// but for now, we use static alias passed to constructor.
 	//
 	Public p;
-	pp::exponentToPublic(pp::secretToExponent(m_alias.m_secret), p);
+	s_secp256k1.toPublic(m_alias.m_secret, p);
 	exchange.resize(exchange.size() + sizeof(p));
 	memcpy(exchange.data() - sizeof(p), p.data(), sizeof(p));
 	
@@ -70,7 +83,7 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange)
 	
 	h256 auth;
 	sha3mac(m_alias.m_secret.ref(), m_ephemeralSecret.ref(), auth.ref());
-	Signature sig = crypto::sign(m_alias.m_secret, auth);
+	Signature sig = s_secp256k1.sign(m_alias.m_secret, auth);
 	exchange.resize(exchange.size() + sizeof(sig));
 	memcpy(exchange.data() - sizeof(sig), sig.data(), sizeof(sig));
 	
@@ -78,7 +91,7 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange)
 	h256 prefix(sha3((h256)(m_known.second|m_remoteEphemeral)));
 	aes.update(prefix.ref());
 	
-	encrypt(encpk, exchange);
+	s_secp256k1.encrypt(encpk, exchange);
 	aes.update(&exchange);
 
 	aes.streamOut(o_exchange);
diff --git a/libdevcrypto/ECDHE.h b/libdevcrypto/ECDHE.h
index 88e5ba764..86c333cf9 100644
--- a/libdevcrypto/ECDHE.h
+++ b/libdevcrypto/ECDHE.h
@@ -24,7 +24,6 @@
 #pragma once
 
 #include "AES.h"
-#include "EC.h"
 
 namespace dev
 {
@@ -33,6 +32,9 @@ namespace crypto
 	
 typedef std::pair AliasSession;
 	
+/**
+ * @brief An addressable EC key pair.
+ */
 class Alias
 {
 	friend class ECDHEKeyExchange; // todo: remove
diff --git a/libdevcrypto/SHA3.cpp b/libdevcrypto/SHA3.cpp
index 4a0cd469e..1fc9be950 100644
--- a/libdevcrypto/SHA3.cpp
+++ b/libdevcrypto/SHA3.cpp
@@ -86,6 +86,16 @@ h256 sha3(bytesConstRef _input)
 	sha3(_input, bytesRef(&ret[0], 32));
 	return ret;
 }
+	
+void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output)
+{
+	CryptoPP::SHA3_256 ctx;
+	assert(_secret.size() > 0);
+	ctx.Update((byte*)_secret.data(), _secret.size());
+	ctx.Update((byte*)_plain.data(), _plain.size());
+	assert(_output.size() >= 32);
+	ctx.Final(_output.data());
+}
 
 bytes aesDecrypt(bytesConstRef _ivCipher, std::string const& _password, unsigned _rounds, bytesConstRef _salt)
 {
diff --git a/libdevcrypto/SHA3.h b/libdevcrypto/SHA3.h
index 7aa4db246..f27e378ba 100644
--- a/libdevcrypto/SHA3.h
+++ b/libdevcrypto/SHA3.h
@@ -55,6 +55,9 @@ inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef((bytes*)&_inpu
 
 /// Calculate SHA3-256 hash of the given input (presented as a binary-filled string), returning as a 256-bit hash.
 inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); }
+	
+/// Calculate SHA3-256 MAC
+void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output);
 
 /// Calculate SHA3-256 hash of the given input (presented as a FixedHash), returns a 256-bit hash.
 template inline h256 sha3(FixedHash const& _input) { return sha3(_input.ref()); }
diff --git a/libdevcrypto/SHA3MAC.cpp b/libdevcrypto/SHA3MAC.cpp
deleted file mode 100644
index 9498ef87b..000000000
--- a/libdevcrypto/SHA3MAC.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- This file is part of cpp-ethereum.
-
- cpp-ethereum is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- cpp-ethereum is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with cpp-ethereum.  If not, see .
- */
-/** @file SHA3MAC.cpp
- * @author Alex Leverington 
- * @date 2014
- *
- * SHA3 MAC
- */
-
-#include "CryptoPP.h"
-#include "SHA3MAC.h"
-
-using namespace dev;
-using namespace dev::crypto;
-using namespace CryptoPP;
-
-void crypto::sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output)
-{
-	CryptoPP::SHA3_256 ctx;
-	assert(_secret.size() > 0);
-	ctx.Update((byte*)_secret.data(), _secret.size());
-	ctx.Update((byte*)_plain.data(), _plain.size());
-	assert(_output.size() >= 32);
-	ctx.Final(_output.data());
-}
-
diff --git a/libdevcrypto/SHA3MAC.h b/libdevcrypto/SHA3MAC.h
deleted file mode 100644
index 4b2d06eac..000000000
--- a/libdevcrypto/SHA3MAC.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- This file is part of cpp-ethereum.
-
- cpp-ethereum is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- cpp-ethereum is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with cpp-ethereum.  If not, see .
- */
-/** @file SHA3MAC.h
- * @author Alex Leverington 
- * @date 2014
- *
- * SHA3 MAC
- */
-
-#pragma once
-
-#include 
-#include 
-
-namespace dev
-{
-namespace crypto
-{
-
-void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output);
-
-}
-}
-
diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp
index 8e21884ee..3918ff6c7 100644
--- a/libethcore/CommonEth.cpp
+++ b/libethcore/CommonEth.cpp
@@ -28,7 +28,6 @@ using namespace std;
 using namespace dev;
 using namespace dev::eth;
 
-//#define ETH_ADDRESS_DEBUG 1
 namespace dev
 {
 namespace eth
@@ -84,30 +83,4 @@ std::string formatBalance(u256 _b)
 	return ret.str();
 }
 
-Address toAddress(Secret _private)
-{
-	secp256k1_start();
-
-	byte pubkey[65];
-	int pubkeylen = 65;
-	int ok = secp256k1_ecdsa_seckey_verify(_private.data());
-	if (!ok)
-		return Address();
-	ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _private.data(), 0);
-	assert(pubkeylen == 65);
-	if (!ok)
-		return Address();
-	ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65);
-	if (!ok)
-		return Address();
-	auto ret = right160(dev::sha3(bytesConstRef(&(pubkey[1]), 64)));
-#if ETH_ADDRESS_DEBUG
-	cout << "---- ADDRESS -------------------------------" << endl;
-	cout << "SEC: " << _private << endl;
-	cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl;
-	cout << "ADR: " << ret << endl;
-#endif
-	return ret;
-}
-
 }}
diff --git a/libethereum/State.cpp b/libethereum/State.cpp
index 35e00f588..8add9e954 100644
--- a/libethereum/State.cpp
+++ b/libethereum/State.cpp
@@ -113,8 +113,6 @@ State::State(Address _coinbaseAddress, OverlayDB const& _db):
 	m_ourAddress(_coinbaseAddress),
 	m_blockReward(c_blockReward)
 {
-	secp256k1_start();
-
 	// Initialise to the state entailed by the genesis block; this guarantees the trie is built correctly.
 	m_state.init();
 
@@ -138,8 +136,6 @@ State::State(OverlayDB const& _db, BlockChain const& _bc, h256 _h):
 	m_state(&m_db),
 	m_blockReward(c_blockReward)
 {
-	secp256k1_start();
-
 	// TODO THINK: is this necessary?
 	m_state.init();
 
diff --git a/test/crypto.cpp b/test/crypto.cpp
index 4e752fd1a..2a206bdd7 100644
--- a/test/crypto.cpp
+++ b/test/crypto.cpp
@@ -27,8 +27,7 @@
 #include 
 #include 
 #include 
-#include 
-#include 
+#include 
 #include 
 #include 
 
@@ -39,6 +38,21 @@ using namespace CryptoPP;
 
 BOOST_AUTO_TEST_SUITE(devcrypto)
 
+static Secp256k1 s_secp256k1;
+static CryptoPP::AutoSeededRandomPool s_rng;
+static CryptoPP::OID s_curveOID(CryptoPP::ASN1::secp256k1());
+static CryptoPP::DL_GroupParameters_EC s_params(s_curveOID);
+static CryptoPP::DL_GroupParameters_EC::EllipticCurve s_curve(s_params.GetCurve());
+
+BOOST_AUTO_TEST_CASE(verify_secert)
+{
+	h256 empty;
+	KeyPair kNot(empty);
+	BOOST_REQUIRE(!kNot.address());
+	KeyPair k(sha3(empty));
+	BOOST_REQUIRE(k.address());
+}
+
 BOOST_AUTO_TEST_CASE(common_encrypt_decrypt)
 {
 	string message("Now is the time for all good persons to come to the aid of humanity.");
@@ -57,103 +71,50 @@ BOOST_AUTO_TEST_CASE(common_encrypt_decrypt)
 	BOOST_REQUIRE(plain == asBytes(message));
 }
 
-BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1)
-{
-	ECIES::Decryptor d(pp::PRNG, pp::secp256k1Curve);
-	ECIES::Encryptor e(d.GetKey());
-	
-	Secret s;
-	pp::exportPrivateKey(d.GetKey(), s);
-	
-	Public p;
-	pp::exportPublicKey(e.GetKey(), p);
-	
-	BOOST_REQUIRE(dev::toAddress(s) == right160(dev::sha3(p.ref())));
-	
-	Secret previous = s;
-	for (auto i = 0; i < 2; i++)
-	{
-		ECIES::Decryptor d(pp::PRNG, pp::secp256k1Curve);
-		ECIES::Encryptor e(d.GetKey());
-		
-		Secret s;
-		pp::exportPrivateKey(d.GetKey(), s);
-		BOOST_REQUIRE(s != previous);
-		
-		Public p;
-		pp::exportPublicKey(e.GetKey(), p);
-
-		h160 secp256k1Addr = dev::toAddress(s);
-		h160 cryptoppAddr = right160(dev::sha3(p.ref()));
-		if (secp256k1Addr != cryptoppAddr)
-		{
-			BOOST_REQUIRE(secp256k1Addr == cryptoppAddr);
-			break;
-		}
-	}
-}
-
 BOOST_AUTO_TEST_CASE(cryptopp_cryptopp_secp256k1libport)
 {
-	// cryptopp implementation of secp256k1lib sign_compact w/recid parameter and recovery of public key from signature
-		
+	secp256k1_start();
+	
 	// base secret
 	Secret secret(sha3("privacy"));
 	
 	// we get ec params from signer
-	const CryptoPP::DL_GroupParameters_EC params = pp::secp256k1Params;
 	ECDSA::Signer signer;
 	
 	// e := sha3(msg)
 	bytes e(fromHex("0x01"));
 	e.resize(32);
-	int tests = 2; // Oct 29: successful @ 1500
+	int tests = 2;
 	while (sha3(&e, &e), secret = sha3(secret.asBytes()), tests--)
 	{
 		KeyPair key(secret);
 		Public pkey = key.pub();
-		pp::initializeDLScheme(secret, signer);
+		signer.AccessKey().Initialize(s_params, secretToExponent(secret));
 		
 		h256 he(sha3(e));
 		Integer heInt(he.asBytes().data(), 32);
 		h256 k(crypto::kdf(secret, he));
 		Integer kInt(k.asBytes().data(), 32);
-		kInt %= params.GetSubgroupOrder()-1;
+		kInt %= s_params.GetSubgroupOrder()-1;
 
-		ECP::Point rp = params.ExponentiateBase(kInt);
-		Integer const& q = params.GetGroupOrder();
-		Integer r = params.ConvertElementToInteger(rp);
-		int recid = ((r >= q) ? 2 : 0) | (rp.y.IsOdd() ? 1 : 0);
+		ECP::Point rp = s_params.ExponentiateBase(kInt);
+		Integer const& q = s_params.GetGroupOrder();
+		Integer r = s_params.ConvertElementToInteger(rp);
 
 		Integer kInv = kInt.InverseMod(q);
 		Integer s = (kInv * (Integer(secret.asBytes().data(), 32)*r + heInt)) % q;
 		BOOST_REQUIRE(!!r && !!s);
-		
-/*
-		// For future reference:
-		// According to maths, this codepath can't be reached, however, it's in secp256k1.
-		// Commenting this out diverges from codebase implementation.
-		// To be removed after upstream PR and proof are evaulated.
- 
-		if (s > params.GetSubgroupOrder())
-		{
-			// note: this rarely happens
-			s = params.GetGroupOrder() - s;
-			if (recid)
-				recid ^= 1;
-		}
- */
 
 		Signature sig;
+		sig[64] = rp.y.IsOdd() ? 1 : 0;
 		r.Encode(sig.data(), 32);
 		s.Encode(sig.data() + 32, 32);
-		sig[64] = recid;
 
 		Public p = dev::recover(sig, he);
 		BOOST_REQUIRE(p == pkey);
 		
 		// verify w/cryptopp
-		BOOST_REQUIRE(crypto::verify(pkey, sig, bytesConstRef(&e)));
+		BOOST_REQUIRE(s_secp256k1.verify(pkey, sig, bytesConstRef(&e)));
 		
 		// verify with secp256k1lib
 		byte encpub[65] = {0x04};
@@ -167,17 +128,19 @@ BOOST_AUTO_TEST_CASE(cryptopp_cryptopp_secp256k1libport)
 
 BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1)
 {
+	secp256k1_start();
+	
 	// cryptopp integer encoding
 	Integer nHex("f2ee15ea639b73fa3db9b34a245bdfa015c260c598b211bf05a1ecc4b3e3b4f2H");
 	Integer nB(fromHex("f2ee15ea639b73fa3db9b34a245bdfa015c260c598b211bf05a1ecc4b3e3b4f2").data(), 32);
 	BOOST_REQUIRE(nHex == nB);
 	
 	bytes sbytes(fromHex("0xFFFF"));
-	Secret secret(sha3(sbytes)); // 5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2
+	Secret secret(sha3(sbytes));
 	KeyPair key(secret);
 	
 	bytes m(fromHex("0xFF"));
-	int tests = 3;
+	int tests = 2;
 	while (m[0]++, tests--)
 	{
 		h256 hm(sha3(m));
@@ -187,42 +150,42 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1)
 
 		// raw sign w/cryptopp (doesn't pass through cryptopp hash filter)
 		ECDSA::Signer signer;
-		pp::initializeDLScheme(key.sec(), signer);
+		signer.AccessKey().Initialize(s_params, secretToExponent(key.sec()));
 		Integer r, s;
 		signer.RawSign(kInt, hInt, r, s);
 
 		// verify cryptopp raw-signature w/cryptopp
 		ECDSA::Verifier verifier;
-		pp::initializeDLScheme(key.pub(), verifier);
+		verifier.AccessKey().Initialize(s_params, publicToPoint(key.pub()));
 		Signature sigppraw;
 		r.Encode(sigppraw.data(), 32);
 		s.Encode(sigppraw.data() + 32, 32);
 		BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), sigppraw.data(), 64));
-		BOOST_REQUIRE(crypto::verify(key.pub(), sigppraw, bytesConstRef(&m)));
+//		BOOST_REQUIRE(crypto::verify(key.pub(), sigppraw, bytesConstRef(&m)));
 		BOOST_REQUIRE(dev::verify(key.pub(), sigppraw, hm));
 		
 		// sign with cryptopp, verify, recover w/sec256lib
 		Signature seclibsig(dev::sign(key.sec(), hm));
 		BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), seclibsig.data(), 64));
-		BOOST_REQUIRE(crypto::verify(key.pub(), seclibsig, bytesConstRef(&m)));
+//		BOOST_REQUIRE(crypto::verify(key.pub(), seclibsig, bytesConstRef(&m)));
 		BOOST_REQUIRE(dev::verify(key.pub(), seclibsig, hm));
 		BOOST_REQUIRE(dev::recover(seclibsig, hm) == key.pub());
 
 		// sign with cryptopp (w/hash filter?), verify with cryptopp
 		bytes sigppb(signer.MaxSignatureLength());
-		size_t ssz = signer.SignMessage(pp::PRNG, m.data(), m.size(), sigppb.data());
+		size_t ssz = signer.SignMessage(s_rng, m.data(), m.size(), sigppb.data());
 		Signature sigpp;
 		memcpy(sigpp.data(), sigppb.data(), 64);
 		BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), sigppb.data(), ssz));
-		BOOST_REQUIRE(crypto::verify(key.pub(), sigpp, bytesConstRef(&m)));
+//		BOOST_REQUIRE(crypto::verify(key.pub(), sigpp, bytesConstRef(&m)));
 		BOOST_REQUIRE(dev::verify(key.pub(), sigpp, hm));
 
 		// sign with cryptopp and stringsource hash filter
 		string sigstr;
-		StringSource ssrc(asString(m), true, new SignerFilter(pp::PRNG, signer, new StringSink(sigstr)));
+		StringSource ssrc(asString(m), true, new SignerFilter(s_rng, signer, new StringSink(sigstr)));
 		FixedHash retsig((byte const*)sigstr.data(), Signature::ConstructFromPointer);
 		BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), retsig.data(), 64));
-		BOOST_REQUIRE(crypto::verify(key.pub(), retsig, bytesConstRef(&m)));
+//		BOOST_REQUIRE(crypto::verify(key.pub(), retsig, bytesConstRef(&m)));
 		BOOST_REQUIRE(dev::verify(key.pub(), retsig, hm));
 		
 		/// verification w/sec256lib
@@ -248,22 +211,6 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1)
 	}
 }
 
-BOOST_AUTO_TEST_CASE(cryptopp_public_export_import)
-{
-	ECIES::Decryptor d(pp::PRNG, pp::secp256k1Curve);
-	ECIES::Encryptor e(d.GetKey());
-
-	Secret s;
-	pp::exportPrivateKey(d.GetKey(), s);
-	Public p;
-	pp::exportPublicKey(e.GetKey(), p);
-	Address addr = right160(dev::sha3(p.ref()));
-	BOOST_REQUIRE(toAddress(s) == addr);
-	
-	KeyPair l(s);
-	BOOST_REQUIRE(l.address() == addr);
-}
-
 BOOST_AUTO_TEST_CASE(ecies_eckeypair)
 {
 	KeyPair k = KeyPair::create();
@@ -272,10 +219,10 @@ BOOST_AUTO_TEST_CASE(ecies_eckeypair)
 	string original = message;
 	
 	bytes b = asBytes(message);
-	encrypt(k.pub(), b);
+	s_secp256k1.encrypt(k.pub(), b);
 	BOOST_REQUIRE(b != asBytes(original));
 
-	decrypt(k.sec(), b);
+	s_secp256k1.decrypt(k.sec(), b);
 	BOOST_REQUIRE(b == asBytes(original));
 }
 
@@ -283,15 +230,15 @@ BOOST_AUTO_TEST_CASE(ecdh)
 {
 	cnote << "Testing ecdh...";
 
-	ECDH::Domain dhLocal(pp::secp256k1Curve);
+	ECDH::Domain dhLocal(s_curveOID);
 	SecByteBlock privLocal(dhLocal.PrivateKeyLength());
 	SecByteBlock pubLocal(dhLocal.PublicKeyLength());
-	dhLocal.GenerateKeyPair(pp::PRNG, privLocal, pubLocal);
+	dhLocal.GenerateKeyPair(s_rng, privLocal, pubLocal);
 	
-	ECDH::Domain dhRemote(pp::secp256k1Curve);
+	ECDH::Domain dhRemote(s_curveOID);
 	SecByteBlock privRemote(dhRemote.PrivateKeyLength());
 	SecByteBlock pubRemote(dhRemote.PublicKeyLength());
-	dhRemote.GenerateKeyPair(pp::PRNG, privRemote, pubRemote);
+	dhRemote.GenerateKeyPair(s_rng, privRemote, pubRemote);
 	
 	assert(dhLocal.AgreedValueLength() == dhRemote.AgreedValueLength());
 	
@@ -323,7 +270,7 @@ BOOST_AUTO_TEST_CASE(ecdh)
 	byte pubb[65] = {0x04};
 	memcpy(&pubb[1], b.pub().data(), 64);
 	
-	ECDH::Domain dhA(pp::secp256k1Curve);
+	ECDH::Domain dhA(s_curveOID);
 	Secret shared;
 	BOOST_REQUIRE(dhA.Agree(shared.data(), a.sec().data(), pubb));
 	BOOST_REQUIRE(shared);

From f560cfa78d23764636949f286edce8048fcfeb32 Mon Sep 17 00:00:00 2001
From: subtly 
Date: Thu, 13 Nov 2014 03:13:30 +0100
Subject: [PATCH 26/50] fix compile

---
 libdevcrypto/AES.cpp | 5 ++++-
 libdevcrypto/AES.h   | 2 ++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp
index 1807bad19..0682adea3 100644
--- a/libdevcrypto/AES.cpp
+++ b/libdevcrypto/AES.cpp
@@ -30,7 +30,10 @@ using namespace CryptoPP;
 
 struct aes::Aes128Ctr
 {
-	Aes128Ctr(h128 _k) { mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data()); }
+	Aes128Ctr(h128 _k)
+	{
+		mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data());
+	}
 	CryptoPP::CTR_Mode::Encryption mode;
 };
 
diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h
index 2bb852653..7a1beefe5 100644
--- a/libdevcrypto/AES.h
+++ b/libdevcrypto/AES.h
@@ -19,10 +19,12 @@
  * @date 2014
  *
  * AES
+ * todo: use openssl
  */
 
 #pragma once
 
+#include 
 #include "Common.h"
 
 namespace dev

From c99e09dc49d13201d425eff9e24ea23c444ff597 Mon Sep 17 00:00:00 2001
From: subtly 
Date: Thu, 13 Nov 2014 13:20:10 +0100
Subject: [PATCH 27/50] code review

---
 libdevcrypto/AES.cpp    |  2 +-
 libdevcrypto/AES.h      |  6 ++++++
 libdevcrypto/Common.cpp | 26 +++++++++++---------------
 libdevcrypto/Common.h   | 18 +++++++++---------
 4 files changed, 27 insertions(+), 25 deletions(-)

diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp
index 0682adea3..bcfbbbdc0 100644
--- a/libdevcrypto/AES.cpp
+++ b/libdevcrypto/AES.cpp
@@ -34,7 +34,7 @@ struct aes::Aes128Ctr
 	{
 		mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data());
 	}
-	CryptoPP::CTR_Mode::Encryption mode;
+	CTR_Mode::Encryption mode;
 };
 
 Stream::Stream(StreamType _t, h128 _ckey):
diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h
index 7a1beefe5..af4f781cd 100644
--- a/libdevcrypto/AES.h
+++ b/libdevcrypto/AES.h
@@ -53,6 +53,9 @@ public:
 	virtual size_t streamOut(bytes& o_bytes);
 	
 private:
+	Stream(Stream const&) = delete;
+	Stream& operator=(Stream const&) = delete;
+	
 	h128 m_cSecret;
 	bytes m_text;
 
@@ -74,6 +77,9 @@ public:
 	void adjustInterval(unsigned _interval) { m_macInterval = _interval; };
 	
 private:
+	AuthenticatedStream(AuthenticatedStream const&) = delete;
+	AuthenticatedStream& operator=(AuthenticatedStream const&) = delete;
+	
 	std::atomic m_macInterval;
 	h128 m_macSecret;
 };
diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp
index 9107fe9ca..fa5a544a1 100644
--- a/libdevcrypto/Common.cpp
+++ b/libdevcrypto/Common.cpp
@@ -33,33 +33,33 @@ using namespace dev::crypto;
 
 static Secp256k1 s_secp256k1;
 
-Public dev::toPublic(Secret _secret)
+Public dev::toPublic(Secret const& _secret)
 {
 	Public p;
 	s_secp256k1.toPublic(_secret, p);
 	return std::move(p);
 }
 
-Address dev::toAddress(Public _public)
+Address dev::toAddress(Public const& _public)
 {
 	return s_secp256k1.toAddress(_public);
 }
 
-Address dev::toAddress(Secret _secret)
+Address dev::toAddress(Secret const& _secret)
 {
 	Public p;
 	s_secp256k1.toPublic(_secret, p);
 	return s_secp256k1.toAddress(p);
 }
 
-void dev::encrypt(Public _k, bytesConstRef _plain, bytes& o_cipher)
+void dev::encrypt(Public const& _k, bytesConstRef _plain, bytes& o_cipher)
 {
 	bytes io = _plain.toBytes();
 	s_secp256k1.encrypt(_k, io);
 	o_cipher = std::move(io);
 }
 
-bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext)
+bool dev::decrypt(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext)
 {
 	bytes io = _cipher.toBytes();
 	s_secp256k1.decrypt(_k, io);
@@ -69,19 +69,19 @@ bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext)
 	return true;
 }
 
-Public dev::recover(Signature _sig, h256 _message)
+Public dev::recover(Signature const& _sig, h256 const& _message)
 {
 	return s_secp256k1.recover(_sig, _message.ref());
 }
 
-Signature dev::sign(Secret _k, h256 _hash)
+Signature dev::sign(Secret const& _k, h256 const& _hash)
 {
 	return s_secp256k1.sign(_k, _hash);
 }
 
-bool dev::verify(Public _p, Signature _s, h256 _hash)
+bool dev::verify(Public const& _p, Signature const& _s, h256 const& _hash)
 {
-	return s_secp256k1.verify(_p, _s, bytesConstRef(_hash.data(), 32), true);
+	return s_secp256k1.verify(_p, _s, _hash.ref(), true);
 }
 
 KeyPair KeyPair::create()
@@ -91,11 +91,7 @@ KeyPair KeyPair::create()
 
 	for (int i = 0; i < 100; ++i)
 	{
-		h256 sec;
-		for (unsigned i = 0; i < 32; ++i)
-			sec[i] = (byte)d(s_eng);
-
-		KeyPair ret(sec);
+		KeyPair ret(FixedHash<32>::random(s_eng));
 		if (ret.address())
 			return ret;
 	}
@@ -144,7 +140,7 @@ h256 Nonce::get(bool _commit)
 		else
 		{
 			// todo: replace w/entropy from user and system
-			std::mt19937_64 s_eng(time(0));
+			std::mt19937_64 s_eng(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count());
 			std::uniform_int_distribution d(0, 255);
 			for (unsigned i = 0; i < 32; ++i)
 				s_seed[i] = (byte)d(s_eng);
diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h
index cd0996826..87d47937e 100644
--- a/libdevcrypto/Common.h
+++ b/libdevcrypto/Common.h
@@ -30,7 +30,7 @@
 
 namespace dev
 {
-	
+
 /// A secret key: 32 bytes.
 /// @NOTE This is not endian-specific; it's just a bunch of bytes.
 using Secret = h256;
@@ -59,29 +59,29 @@ using AddressSet = std::set;
 using Secrets = h256s;
 
 /// Convert a secret key into the public key equivalent.
-Public toPublic(Secret _secret);
+Public toPublic(Secret const& _secret);
 
 /// Convert a public key to address.
-Address toAddress(Public _public);
+Address toAddress(Public const& _public);
 
 /// Convert a secret key into address of public key equivalent.
 /// @returns 0 if it's not a valid secret key.
-Address toAddress(Secret _secret);
+Address toAddress(Secret const& _secret);
 
 /// Encrypts plain text using Public key.
-void encrypt(Public _k, bytesConstRef _plain, bytes& o_cipher);
+void encrypt(Public const& _k, bytesConstRef _plain, bytes& o_cipher);
 
 /// Decrypts cipher using Secret key.
-bool decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext);
+bool decrypt(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext);
 	
 /// Recovers Public key from signed message hash.
-Public recover(Signature _sig, h256 _hash);
+Public recover(Signature const& _sig, h256 const& _hash);
 	
 /// Returns siganture of message hash.
-Signature sign(Secret _k, h256 _hash);
+Signature sign(Secret const& _k, h256 const& _hash);
 	
 /// Verify signature.
-bool verify(Public _k, Signature _s, h256 _hash);
+bool verify(Public const& _k, Signature const& _s, h256 const& _hash);
 
 /// Simple class that represents a "key pair".
 /// All of the data of the class can be regenerated from the secret key (m_secret) alone.

From fd5738ae64d3d1b0e68d010c78e69f6c283615d8 Mon Sep 17 00:00:00 2001
From: subtly 
Date: Thu, 13 Nov 2014 13:31:43 +0100
Subject: [PATCH 28/50] fix hash in constructor

---
 libdevcrypto/AES.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h
index af4f781cd..f0646eb85 100644
--- a/libdevcrypto/AES.h
+++ b/libdevcrypto/AES.h
@@ -71,10 +71,10 @@ class AuthenticatedStream: public Stream
 public:
 	AuthenticatedStream(StreamType _t, h128 _ckey, h128 _mackey, unsigned _interval): Stream(_t, _ckey), m_macSecret(_mackey) { m_macInterval = _interval; }
 	
-	AuthenticatedStream(StreamType _t, Secret const& _s, unsigned _interval): Stream(_t, h128(_s)), m_macSecret(FixedHash<16>(_s[0]+16)) { m_macInterval = _interval; }
+	AuthenticatedStream(StreamType _t, Secret const& _s, unsigned _interval): Stream(_t, h128(_s)), m_macSecret(FixedHash<16>((byte const*)_s.data()+16,h128::ConstructFromPointer)) { m_macInterval = _interval; }
 	
 	/// Adjust mac interval. Next mac will be xored with value.
-	void adjustInterval(unsigned _interval) { m_macInterval = _interval; };
+	void adjustInterval(unsigned _interval) { m_macInterval = _interval; }
 	
 private:
 	AuthenticatedStream(AuthenticatedStream const&) = delete;

From c1bc090104c1d2ca3bbaecb8dd145565d3c8db16 Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Thu, 13 Nov 2014 15:50:32 +0100
Subject: [PATCH 29/50] Log pricing update.

---
 libevm/FeeStructure.cpp               | 3 +++
 libevm/FeeStructure.h                 | 3 +++
 libevm/VM.h                           | 3 ++-
 libweb3jsonrpc/WebThreeStubServer.cpp | 3 +--
 libwhisper/Common.cpp                 | 4 ++--
 libwhisper/Common.h                   | 4 ++--
 libwhisper/Message.h                  | 2 +-
 7 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/libevm/FeeStructure.cpp b/libevm/FeeStructure.cpp
index 47236b506..6d868cac5 100644
--- a/libevm/FeeStructure.cpp
+++ b/libevm/FeeStructure.cpp
@@ -37,3 +37,6 @@ u256 const dev::eth::c_callGas = 20;
 u256 const dev::eth::c_memoryGas = 1;
 u256 const dev::eth::c_txDataGas = 5;
 u256 const dev::eth::c_txGas = 500;
+u256 const dev::eth::c_logGas = 32;
+u256 const dev::eth::c_logDataGas = 1;
+u256 const dev::eth::c_logTopicGas = 32;
diff --git a/libevm/FeeStructure.h b/libevm/FeeStructure.h
index 84a2551d9..e57f7ccf8 100644
--- a/libevm/FeeStructure.h
+++ b/libevm/FeeStructure.h
@@ -40,6 +40,9 @@ extern u256 const c_callGas;			///< Once per CALL operation & message call trans
 extern u256 const c_memoryGas;			///< Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
 extern u256 const c_txDataGas;			///< Per byte of data attached to a transaction. NOTE: Not payable on data of calls between transactions.
 extern u256 const c_txGas;				///< Per transaction. NOTE: Not payable on data of calls between transactions.
+extern u256 const c_logGas;				///< Per LOG* operation.
+extern u256 const c_logDataGas;			///< Per byte in a LOG* operation's data.
+extern u256 const c_logTopicGas;		///< Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas.
 
 }
 }
diff --git a/libevm/VM.h b/libevm/VM.h
index b3a4c2828..d495b6289 100644
--- a/libevm/VM.h
+++ b/libevm/VM.h
@@ -206,7 +206,8 @@ template  dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
 		{
 			unsigned n = (unsigned)inst - (unsigned)Instruction::LOG0;
 			require(n + 2);
-			newTempSize = memNeed(m_stack[m_stack.size() - 1 ], m_stack[m_stack.size() - 2]);
+			runGas = c_logGas + c_logTopicGas * n + c_logDataGas * m_stack[m_stack.size() - 2];
+			newTempSize = memNeed(m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]);
 			break;
 		}
 
diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp
index 3849fb4a8..092faae09 100644
--- a/libweb3jsonrpc/WebThreeStubServer.cpp
+++ b/libweb3jsonrpc/WebThreeStubServer.cpp
@@ -271,14 +271,13 @@ static Json::Value toJson(h256 const& _h, shh::Envelope const& _e, shh::Message
 	res["ttl"] = (int)_e.ttl();
 	res["workProved"] = (int)_e.workProved();
 	for (auto const& t: _e.topics())
-		res["topics"].append(toJS((u256)t));
+		res["topics"].append(toJS(t));
 	res["payload"] = toJS(_m.payload());
 	res["from"] = toJS(_m.from());
 	res["to"] = toJS(_m.to());
 	return res;
 }
 
-
 WebThreeStubServer::WebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, WebThreeDirect& _web3, std::vector const& _accounts):
 	AbstractWebThreeStubServer(_conn),
 	m_web3(_web3)
diff --git a/libwhisper/Common.cpp b/libwhisper/Common.cpp
index 8f58ae994..83f289875 100644
--- a/libwhisper/Common.cpp
+++ b/libwhisper/Common.cpp
@@ -33,7 +33,7 @@ Topic BuildTopic::toTopic() const
 	Topic ret;
 	ret.reserve(m_parts.size());
 	for (auto const& h: m_parts)
-		ret.push_back((TopicPart)u256(h));
+		ret.push_back(TopicPart(h));
 	return ret;
 }
 
@@ -69,7 +69,7 @@ TopicMask BuildTopicMask::toTopicMask() const
 	TopicMask ret;
 	ret.reserve(m_parts.size());
 	for (auto const& h: m_parts)
-		ret.push_back(make_pair((TopicPart)u256(h), h ? ~(uint32_t)0 : 0));
+		ret.push_back(make_pair(TopicPart(h), h ? ~TopicPart() : TopicPart()));
 	return ret;
 }
 
diff --git a/libwhisper/Common.h b/libwhisper/Common.h
index 436af8d11..c445ac506 100644
--- a/libwhisper/Common.h
+++ b/libwhisper/Common.h
@@ -59,7 +59,7 @@ enum WhisperPacket
 	PacketCount
 };
 
-using TopicPart = uint32_t;
+using TopicPart = FixedHash<4>;
 
 using Topic = std::vector;
 
@@ -92,7 +92,7 @@ public:
 	TopicFilter() {}
 	TopicFilter(TopicMask const& _m): m_topicMasks(1, _m) {}
 	TopicFilter(TopicMasks const& _m): m_topicMasks(_m) {}
-	TopicFilter(RLP const& _r): m_topicMasks(_r.toVector>>()) {}
+	TopicFilter(RLP const& _r): m_topicMasks(_r.toVector, FixedHash<4>>>>()) {}
 
 	void streamRLP(RLPStream& _s) const { _s << m_topicMasks; }
 	h256 sha3() const;
diff --git a/libwhisper/Message.h b/libwhisper/Message.h
index ed26cf145..954aed4a0 100644
--- a/libwhisper/Message.h
+++ b/libwhisper/Message.h
@@ -55,7 +55,7 @@ public:
 	{
 		m_expiry = _m[0].toInt();
 		m_ttl = _m[1].toInt();
-		m_topic = _m[2].toVector();
+		m_topic = _m[2].toVector>();
 		m_data = _m[3].toBytes();
 		m_nonce = _m[4].toInt();
 	}

From 26a9bf4ebef500d3ba26f834f264e759a899fa69 Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Thu, 13 Nov 2014 16:22:52 +0100
Subject: [PATCH 30/50] Version bump.

---
 libethcore/CommonEth.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp
index 0ebf79669..250761e12 100644
--- a/libethcore/CommonEth.cpp
+++ b/libethcore/CommonEth.cpp
@@ -34,7 +34,7 @@ namespace dev
 namespace eth
 {
 
-const unsigned c_protocolVersion = 40;
+const unsigned c_protocolVersion = 41;
 const unsigned c_databaseVersion = 4;
 
 static const vector> g_units =

From 5f8a974a17233843331e3ba2558514a9322578bd Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Thu, 13 Nov 2014 17:35:23 +0100
Subject: [PATCH 31/50] Don't cast to bytes for fear of MSVC's brokenness.

---
 libevm/ExtVMFace.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h
index 8a6b2edc9..65761e410 100644
--- a/libevm/ExtVMFace.h
+++ b/libevm/ExtVMFace.h
@@ -49,7 +49,7 @@ using LogBloom = h512;
 struct LogEntry
 {
 	LogEntry() {}
-	LogEntry(RLP const& _r) { address = (Address)_r[0]; topics = (h256Set)_r[1]; data = (bytes)_r[2]; }
+	LogEntry(RLP const& _r) { address = (Address)_r[0]; topics = (h256Set)_r[1]; data = _r[2].toBytes(); }
 	LogEntry(Address const& _address, h256s const& _ts, bytes&& _d): address(_address), topics(toSet(_ts)), data(std::move(_d)) {}
 
 	void streamRLP(RLPStream& _s) const { _s.appendList(3) << address << topics << data; }

From cf3f821d71058bee97da2e21f3978f0b949ab927 Mon Sep 17 00:00:00 2001
From: subtly 
Date: Thu, 13 Nov 2014 17:40:44 +0100
Subject: [PATCH 32/50] changes for code review

---
 libdevcrypto/AES.cpp      |  3 +--
 libdevcrypto/Common.h     |  2 +-
 libdevcrypto/CryptoPP.cpp | 11 +++++++----
 libdevcrypto/CryptoPP.h   | 12 ++++++------
 libdevcrypto/ECDHE.cpp    | 17 ++++++++---------
 libdevcrypto/ECDHE.h      |  3 ++-
 test/crypto.cpp           |  2 +-
 7 files changed, 26 insertions(+), 24 deletions(-)

diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp
index bcfbbbdc0..56885ae36 100644
--- a/libdevcrypto/AES.cpp
+++ b/libdevcrypto/AES.cpp
@@ -37,10 +37,9 @@ struct aes::Aes128Ctr
 	CTR_Mode::Encryption mode;
 };
 
-Stream::Stream(StreamType _t, h128 _ckey):
+Stream::Stream(StreamType, h128 _ckey):
 	m_cSecret(_ckey)
 {
-	(void)_t; // encrypt and decrypt are same operation w/ctr
 	cryptor = new Aes128Ctr(_ckey);
 }
 
diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h
index 87d47937e..2ec332d8d 100644
--- a/libdevcrypto/Common.h
+++ b/libdevcrypto/Common.h
@@ -52,7 +52,7 @@ using Address = h160;
 /// A vector of Ethereum addresses.
 using Addresses = h160s;
 
-/// A vector of Ethereum addresses.
+/// A set of Ethereum addresses.
 using AddressSet = std::set;
 
 /// A vector of secrets.
diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp
index 1edddefa1..858fd53ff 100644
--- a/libdevcrypto/CryptoPP.cpp
+++ b/libdevcrypto/CryptoPP.cpp
@@ -80,6 +80,9 @@ Signature Secp256k1::sign(Secret const& _k, bytesConstRef _message)
 
 Signature Secp256k1::sign(Secret const& _key, h256 const& _hash)
 {
+	// assumption made by signing alogrithm
+	asserts(m_q == m_qs);
+	
 	Signature sig;
 	
 	Integer k(kdf(_key, _hash).data(), 32);
@@ -196,7 +199,7 @@ void Secp256k1::agree(Secret const& _s, Public const& _r, h256& o_s)
 	assert(d.Agree(o_s.data(), _s.data(), remote));
 }
 
-void Secp256k1::exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& _p)
+void Secp256k1::exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& o_p)
 {
 	bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true));
 	
@@ -206,10 +209,10 @@ void Secp256k1::exportPublicKey(CryptoPP::DL_PublicKey_EC const&
 		assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true));
 	}
 
-	memcpy(_p.data(), &prefixedKey[1], Public::size);
+	memcpy(o_p.data(), &prefixedKey[1], Public::size);
 }
 
-void Secp256k1::exponentToPublic(Integer const& _e, Public& _p)
+void Secp256k1::exponentToPublic(Integer const& _e, Public& o_p)
 {
 	CryptoPP::DL_PublicKey_EC pk;
 	
@@ -218,6 +221,6 @@ void Secp256k1::exponentToPublic(Integer const& _e, Public& _p)
 		pk.Initialize(m_params, m_params.ExponentiateBase(_e));
 	}
 	
-	exportPublicKey(pk, _p);
+	exportPublicKey(pk, o_p);
 }
 
diff --git a/libdevcrypto/CryptoPP.h b/libdevcrypto/CryptoPP.h
index b8c1272d9..69189aaab 100644
--- a/libdevcrypto/CryptoPP.h
+++ b/libdevcrypto/CryptoPP.h
@@ -84,10 +84,10 @@ public:
 	/// @returns siganture of message.
 	Signature sign(Secret const& _k, bytesConstRef _message);
 	
-	/// @returns compact siganture of message hash.
+	/// @returns compact siganture of provided hash.
 	Signature sign(Secret const& _k, h256 const& _hash);
 	
-	/// Verify compact signature (public key is extracted from message).
+	/// Verify compact signature (public key is extracted from signature).
 	bool verify(Signature const& _signature, bytesConstRef _message);
 	
 	/// Verify signature.
@@ -96,17 +96,17 @@ public:
 	/// Recovers public key from compact signature. Uses libsecp256k1.
 	Public recover(Signature _signature, bytesConstRef _message);
 	
-	/// Verify secret key is valid.
+	/// Verifies _s is a valid secret key and returns corresponding public key in o_p.
 	bool verifySecret(Secret const& _s, Public& o_p);
 	
 	void agree(Secret const& _s, Public const& _r, h256& o_s);
 	
 protected:
-	void exportPrivateKey(DL_PrivateKey_EC const& _k, Secret& _s) { _k.GetPrivateExponent().Encode(_s.data(), Secret::size); }
+	void exportPrivateKey(DL_PrivateKey_EC const& _k, Secret& o_s) { _k.GetPrivateExponent().Encode(o_s.data(), Secret::size); }
 	
-	void exportPublicKey(DL_PublicKey_EC const& _k, Public& _p);
+	void exportPublicKey(DL_PublicKey_EC const& _k, Public& o_p);
 	
-	void exponentToPublic(Integer const& _e, Public& _p);
+	void exponentToPublic(Integer const& _e, Public& o_p);
 	
 	template  void initializeDLScheme(Secret const& _s, T& io_operator) { std::lock_guard l(x_params); io_operator.AccessKey().Initialize(m_params, secretToExponent(_s)); }
 	
diff --git a/libdevcrypto/ECDHE.cpp b/libdevcrypto/ECDHE.cpp
index d6874fa33..7968ab7cc 100644
--- a/libdevcrypto/ECDHE.cpp
+++ b/libdevcrypto/ECDHE.cpp
@@ -58,11 +58,11 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange)
 	// If a session previously exists:
 	//	prefix is sha3(token) // todo: ephemeral entropy from both sides
 	// If a session doesn't exist:
-	//	prefix is sha3mac(m_ephemeralSecret,
+	//	prefix is sha3(m_ephemeralSecret)
 	//
 	// The second part is encrypted using the public key which relates to the prefix.
 	
-	Public encpk = m_known.first|m_remoteEphemeral;
+	Public encpk = m_known.first | m_remoteEphemeral;
 	bytes exchange(encpk.asBytes());
 	
 	// This is the public key which we would like the remote to use,
@@ -71,24 +71,23 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange)
 	// Here we should pick an appropriate alias or generate a new one,
 	// but for now, we use static alias passed to constructor.
 	//
-	Public p;
-	s_secp256k1.toPublic(m_alias.m_secret, p);
+	Public p = toPublic(m_alias.m_secret);
 	exchange.resize(exchange.size() + sizeof(p));
-	memcpy(exchange.data() - sizeof(p), p.data(), sizeof(p));
+	memcpy(&exchange[exchange.size() - sizeof(p)], p.data(), sizeof(p));
 	
 	// protocol parameters; should be fixed size
-	bytes v(asBytes("\x80"));
+	bytes v({0x80});
 	exchange.resize(exchange.size() + v.size());
-	memcpy(exchange.data() - v.size(), v.data(), v.size());
+	memcpy(&exchange[exchange.size() - v.size()], v.data(), v.size());
 	
 	h256 auth;
 	sha3mac(m_alias.m_secret.ref(), m_ephemeralSecret.ref(), auth.ref());
 	Signature sig = s_secp256k1.sign(m_alias.m_secret, auth);
 	exchange.resize(exchange.size() + sizeof(sig));
-	memcpy(exchange.data() - sizeof(sig), sig.data(), sizeof(sig));
+	memcpy(&exchange[exchange.size() - sizeof(sig)], sig.data(), sizeof(sig));
 	
 	aes::AuthenticatedStream aes(aes::Encrypt, m_ephemeralSecret, 0);
-	h256 prefix(sha3((h256)(m_known.second|m_remoteEphemeral)));
+	h256 prefix(sha3((h256)m_remoteEphemeral | m_known.second));
 	aes.update(prefix.ref());
 	
 	s_secp256k1.encrypt(encpk, exchange);
diff --git a/libdevcrypto/ECDHE.h b/libdevcrypto/ECDHE.h
index 86c333cf9..f77f7fcff 100644
--- a/libdevcrypto/ECDHE.h
+++ b/libdevcrypto/ECDHE.h
@@ -30,6 +30,7 @@ namespace dev
 namespace crypto
 {
 	
+/// Public key of remote and corresponding shared secret.
 typedef std::pair AliasSession;
 	
 /**
@@ -41,7 +42,7 @@ class Alias
 public:
 	Alias(Secret _s): m_secret(_s) {};
 	
-	AliasSession session(Address _a) { return m_sessions.count(_a) ? AliasSession() : m_sessions.find(_a)->second; }
+	AliasSession session(Address _a) { return m_sessions.count(_a) ? m_sessions.find(_a)->second : AliasSession(); }
 	
 private:
 	std::map m_sessions;
diff --git a/test/crypto.cpp b/test/crypto.cpp
index 2a206bdd7..cd7d8e984 100644
--- a/test/crypto.cpp
+++ b/test/crypto.cpp
@@ -139,7 +139,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1)
 	Secret secret(sha3(sbytes));
 	KeyPair key(secret);
 	
-	bytes m(fromHex("0xFF"));
+	bytes m({0xFF});
 	int tests = 2;
 	while (m[0]++, tests--)
 	{

From b74250c6b40f2eb44bbd918f33c53f84340d51d6 Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Thu, 13 Nov 2014 17:56:09 +0100
Subject: [PATCH 33/50] Windows fixes(?)

---
 libdevcrypto/EC.cpp     | 21 ++++++++++++---------
 libserpent/compiler.cpp |  3 +--
 2 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp
index c35eb17f2..e6e6d2329 100644
--- a/libdevcrypto/EC.cpp
+++ b/libdevcrypto/EC.cpp
@@ -37,6 +37,8 @@ using namespace dev::crypto;
 using namespace CryptoPP;
 using namespace pp;
 
+static const int c_publicKeySize = 65;	// Public key size for I/O is 65 bytes (there's an extra byte that we don't really need).
+
 void crypto::toPublic(Secret const& _s, Public& o_public)
 {
 	exponentToPublic(Integer(_s.data(), sizeof(_s)), o_public);
@@ -143,7 +145,7 @@ bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _mess
 		byte dersig[c_derMaxEncodingLength];
 		size_t cssz = DSAConvertSignatureFormat(dersig, c_derMaxEncodingLength, DSA_DER, _sig.data(), 64, DSA_P1363);
 		assert(cssz <= c_derMaxEncodingLength);
-		return (1 == secp256k1_ecdsa_verify(_message.data(), _message.size(), dersig, cssz, encpub, 65));
+		return (1 == secp256k1_ecdsa_verify(_message.data(), _message.size(), dersig, cssz, encpub, c_publicKeySize));
 	}
 	
 	ECDSA::Verifier verifier;
@@ -155,9 +157,9 @@ Public crypto::recover(Signature _signature, bytesConstRef _message)
 {
 	secp256k1_start();
 	
-	int pubkeylen = 65;
-	byte pubkey[pubkeylen];
-	if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _signature.data(), pubkey, &pubkeylen, 0, (int)_signature[64]))
+	byte pubkey[c_publicKeySize];
+	int keySize;
+	if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _signature.data(), pubkey, &keySize, 0, (int)_signature[64]) || keySize != c_publicKeySize)
 		return Public();
 	
 #if ETH_CRYPTO_TRACE
@@ -180,13 +182,14 @@ bool crypto::verifySecret(Secret const& _s, Public const& _p)
 	if (!ok)
 		return false;
 	
-	int pubkeylen = 65;
-	byte pubkey[pubkeylen];
-	ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _s.data(), 0);
-	if (!ok || pubkeylen != 65)
+	byte pubkey[c_publicKeySize];
+
+	int keySize;
+	ok = secp256k1_ecdsa_pubkey_create(pubkey, &keySize, _s.data(), 0);
+	if (!ok || keySize != c_publicKeySize)
 		return false;
 	
-	ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65);
+	ok = secp256k1_ecdsa_pubkey_verify(pubkey, c_publicKeySize);
 	if (!ok)
 		return false;
 	
diff --git a/libserpent/compiler.cpp b/libserpent/compiler.cpp
index 623ab3950..30628fbc9 100644
--- a/libserpent/compiler.cpp
+++ b/libserpent/compiler.cpp
@@ -131,8 +131,7 @@ programData opcodeify(Node node,
         }
         // Declare variable
         else {
-            Node nodelist[] = { };
-            return pd(aux, multiToken(nodelist, 0, m), 0);
+			return pd(aux, multiToken(nullptr, 0, m), 0);
         }
     }
     // Define functions (TODO: eventually move to rewriter.cpp, keep

From c9dbdb6a7ed1ef6274bac38685b7ff14c23b65e1 Mon Sep 17 00:00:00 2001
From: subtly 
Date: Thu, 13 Nov 2014 18:00:58 +0100
Subject: [PATCH 34/50] fix ternary

---
 libdevcrypto/ECDHE.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libdevcrypto/ECDHE.cpp b/libdevcrypto/ECDHE.cpp
index 7968ab7cc..dd72e8176 100644
--- a/libdevcrypto/ECDHE.cpp
+++ b/libdevcrypto/ECDHE.cpp
@@ -62,7 +62,7 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange)
 	//
 	// The second part is encrypted using the public key which relates to the prefix.
 	
-	Public encpk = m_known.first | m_remoteEphemeral;
+	Public encpk = m_known.first ? m_known.first : m_remoteEphemeral;
 	bytes exchange(encpk.asBytes());
 	
 	// This is the public key which we would like the remote to use,
@@ -87,7 +87,7 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange)
 	memcpy(&exchange[exchange.size() - sizeof(sig)], sig.data(), sizeof(sig));
 	
 	aes::AuthenticatedStream aes(aes::Encrypt, m_ephemeralSecret, 0);
-	h256 prefix(sha3((h256)m_remoteEphemeral | m_known.second));
+	h256 prefix(sha3(m_known.second ? m_known.second : (h256)m_remoteEphemeral));
 	aes.update(prefix.ref());
 	
 	s_secp256k1.encrypt(encpk, exchange);

From 50c11a2151e4d76a1d4420f11c77659cae7f87c0 Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Thu, 13 Nov 2014 18:01:20 +0100
Subject: [PATCH 35/50] Stupid MSVC fixes.

---
 libwhisper/Common.h | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/libwhisper/Common.h b/libwhisper/Common.h
index c445ac506..312cbf6d3 100644
--- a/libwhisper/Common.h
+++ b/libwhisper/Common.h
@@ -92,7 +92,15 @@ public:
 	TopicFilter() {}
 	TopicFilter(TopicMask const& _m): m_topicMasks(1, _m) {}
 	TopicFilter(TopicMasks const& _m): m_topicMasks(_m) {}
-	TopicFilter(RLP const& _r): m_topicMasks(_r.toVector, FixedHash<4>>>>()) {}
+	TopicFilter(RLP const& _r)//: m_topicMasks(_r.toVector>())
+	{
+		for (RLP i: _r)
+		{
+			m_topicMasks.push_back(TopicMask());
+			for (RLP j: i)
+				m_topicMasks.back().push_back(j.toPair, FixedHash<4>>());
+		}
+	}
 
 	void streamRLP(RLPStream& _s) const { _s << m_topicMasks; }
 	h256 sha3() const;

From b1c67764298060992f8b2e3de5970c21f564934e Mon Sep 17 00:00:00 2001
From: Christoph Jentzsch 
Date: Thu, 13 Nov 2014 23:20:03 +0100
Subject: [PATCH 36/50] Fix stackoverflow bug in VM

---
 libevm/VM.h | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/libevm/VM.h b/libevm/VM.h
index d495b6289..5c153a6ea 100644
--- a/libevm/VM.h
+++ b/libevm/VM.h
@@ -206,7 +206,9 @@ template  dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
 		{
 			unsigned n = (unsigned)inst - (unsigned)Instruction::LOG0;
 			require(n + 2);
-			runGas = c_logGas + c_logTopicGas * n + c_logDataGas * m_stack[m_stack.size() - 2];
+			runGas = m_stack[m_stack.size() - 2];
+			runGas *= c_logDataGas;
+			runGas += c_logGas + c_logTopicGas * n;
 			newTempSize = memNeed(m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]);
 			break;
 		}
@@ -214,7 +216,8 @@ template  dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
 		case Instruction::CALL:
 		case Instruction::CALLCODE:
 			require(7);
-			runGas = c_callGas + m_stack[m_stack.size() - 1];
+			runGas = m_stack[m_stack.size() - 1];
+			runGas += c_callGas;
 			newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]));
 			break;
 

From b840730b4fb4ef87395a3f3c4fac17218e72d707 Mon Sep 17 00:00:00 2001
From: Christoph Jentzsch 
Date: Fri, 14 Nov 2014 07:55:10 +0100
Subject: [PATCH 37/50] explicit type cast

---
 libevm/VM.h | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/libevm/VM.h b/libevm/VM.h
index 5c153a6ea..52149a9a1 100644
--- a/libevm/VM.h
+++ b/libevm/VM.h
@@ -206,9 +206,7 @@ template  dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
 		{
 			unsigned n = (unsigned)inst - (unsigned)Instruction::LOG0;
 			require(n + 2);
-			runGas = m_stack[m_stack.size() - 2];
-			runGas *= c_logDataGas;
-			runGas += c_logGas + c_logTopicGas * n;
+			runGas = c_logGas + c_logTopicGas * n + (bigint)c_logDataGas * m_stack[m_stack.size() - 2];
 			newTempSize = memNeed(m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]);
 			break;
 		}
@@ -216,8 +214,7 @@ template  dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
 		case Instruction::CALL:
 		case Instruction::CALLCODE:
 			require(7);
-			runGas = m_stack[m_stack.size() - 1];
-			runGas += c_callGas;
+			runGas = (bigint)c_callGas + m_stack[m_stack.size() - 1];
 			newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]));
 			break;
 

From 0896a9cdb32c4e2431deb9baa83bcb674a380b92 Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Fri, 14 Nov 2014 10:56:13 +0100
Subject: [PATCH 38/50] Windows build fix?

---
 windows/LibEthereum.vcxproj | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj
index 30deea983..6ef491fd4 100644
--- a/windows/LibEthereum.vcxproj
+++ b/windows/LibEthereum.vcxproj
@@ -126,6 +126,7 @@
     
     
     
+    
     
       true
       true
@@ -145,7 +146,6 @@
       true
     
     
-    
     
     
     
@@ -341,6 +341,7 @@
     
     
     
+    
     
     
       true

From 2cae9066e70ddc5bf2065d16ac2995b1b1ffda2b Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Fri, 14 Nov 2014 11:14:19 +0100
Subject: [PATCH 39/50] Windows build fix?

---
 windows/LibEthereum.vcxproj | 1 -
 1 file changed, 1 deletion(-)

diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj
index 6ef491fd4..35ca956d3 100644
--- a/windows/LibEthereum.vcxproj
+++ b/windows/LibEthereum.vcxproj
@@ -368,7 +368,6 @@
       true
     
     
-	
     
     
     

From cbf22e3ce67db7a53f9af8ea56359a677ac863e5 Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Fri, 14 Nov 2014 12:45:20 +0100
Subject: [PATCH 40/50] Compile fixes. Version bump.

---
 libethcore/CommonEth.cpp      |  2 +-
 test/solidityEndToEndTest.cpp | 12 ++++++------
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp
index 250761e12..3c0a93481 100644
--- a/libethcore/CommonEth.cpp
+++ b/libethcore/CommonEth.cpp
@@ -34,7 +34,7 @@ namespace dev
 namespace eth
 {
 
-const unsigned c_protocolVersion = 41;
+const unsigned c_protocolVersion = 42;
 const unsigned c_databaseVersion = 4;
 
 static const vector> g_units =
diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp
index 1d09c114f..d905646cb 100644
--- a/test/solidityEndToEndTest.cpp
+++ b/test/solidityEndToEndTest.cpp
@@ -192,11 +192,11 @@ BOOST_AUTO_TEST_CASE(multiple_functions)
 							 "  function f() returns(uint n) { return 3; }\n"
 							 "}\n";
 	compileAndRun(sourceCode);
-	BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(0)));
-	BOOST_CHECK(callFunction(1, bytes()) == toBigEndian(u256(1)));
-	BOOST_CHECK(callFunction(2, bytes()) == toBigEndian(u256(2)));
-	BOOST_CHECK(callFunction(3, bytes()) == toBigEndian(u256(3)));
-	BOOST_CHECK(callFunction(4, bytes()) == bytes());
+	BOOST_CHECK(callContractFunction(0, bytes()) == toBigEndian(u256(0)));
+	BOOST_CHECK(callContractFunction(1, bytes()) == toBigEndian(u256(1)));
+	BOOST_CHECK(callContractFunction(2, bytes()) == toBigEndian(u256(2)));
+	BOOST_CHECK(callContractFunction(3, bytes()) == toBigEndian(u256(3)));
+	BOOST_CHECK(callContractFunction(4, bytes()) == bytes());
 }
 
 BOOST_AUTO_TEST_CASE(while_loop)
@@ -232,7 +232,7 @@ BOOST_AUTO_TEST_CASE(break_outside_loop)
 							 "  }\n"
 							 "}\n";
 	compileAndRun(sourceCode);
-	testSolidityAgainstCpp(0, [](u256 const& _a) -> u256 { return 2; }, u256(0));
+	testSolidityAgainstCpp(0, [](u256 const&) -> u256 { return 2; }, u256(0));
 }
 
 BOOST_AUTO_TEST_CASE(nested_loops)

From a25185172b8e3c03e3bb8f42c286b081fbeddf88 Mon Sep 17 00:00:00 2001
From: subtly 
Date: Fri, 14 Nov 2014 13:14:22 +0100
Subject: [PATCH 41/50] pr fix

---
 test/crypto.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/test/crypto.cpp b/test/crypto.cpp
index cd7d8e984..d8bd25035 100644
--- a/test/crypto.cpp
+++ b/test/crypto.cpp
@@ -340,8 +340,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr)
 		
 		// 68 % 255 should be difference of counter
 		e.ProcessData(out, in, text.size());
-
-		(u128)ctr += (u128)(text.size() % 16);
+		ctr = h128(u128(ctr) + text.size() % 16);
 		
 		BOOST_REQUIRE(text != original);
 		cipherCopy = text;

From 20f3b4b4c1799abc130a8dee843aab34b2cbe733 Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Fri, 14 Nov 2014 13:28:01 +0100
Subject: [PATCH 42/50] Spelling correction.

---
 libp2p/Host.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp
index bf8d96506..4b28a63a3 100644
--- a/libp2p/Host.cpp
+++ b/libp2p/Host.cpp
@@ -386,7 +386,7 @@ shared_ptr Host::noteNode(NodeId _id, bi::tcp::endpoint _a, Origin _o, boo
 {
 	RecursiveGuard l(x_peers);
 	if (_a.port() < 30300 || _a.port() > 30303)
-		cwarn << "Wierd port being recorded!";
+		cwarn << "Weird port being recorded: " << _a.port();
 
 	if (_a.port() >= /*49152*/32768)
 	{

From ffdfb74b45a29b57d61710e0d6bf6f5c2f8cb9d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pawe=C5=82=20Bylica?= 
Date: Fri, 14 Nov 2014 13:42:07 +0100
Subject: [PATCH 43/50] Update Visual Studio project files

---
 windows/LibEthereum.vcxproj         |  7 ++++---
 windows/LibEthereum.vcxproj.filters | 17 ++++++++++-------
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj
index 35ca956d3..0578a8f16 100644
--- a/windows/LibEthereum.vcxproj
+++ b/windows/LibEthereum.vcxproj
@@ -125,8 +125,8 @@
     
     
     
-    
     
+    
     
       true
       true
@@ -341,7 +341,8 @@
     
     
     
-    
+    
+    
     
     
       true
@@ -567,4 +568,4 @@
   
   
   
-
+
\ No newline at end of file
diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters
index 514320472..114364008 100644
--- a/windows/LibEthereum.vcxproj.filters
+++ b/windows/LibEthereum.vcxproj.filters
@@ -40,9 +40,6 @@
     
       libevmcore
     
-    
-      liblll
-    
     
       liblll
     
@@ -202,6 +199,9 @@
     
       libethereum
     
+    
+      libevmcore
+    
   
   
     
@@ -248,9 +248,6 @@
     
     
       liblll
-    
-	
-	  libevmcore
     
     
       liblll
@@ -435,6 +432,12 @@
     
       libethereum
     
+    
+      libevmcore
+    
+    
+      libevmcore
+    
   
   
     
@@ -471,4 +474,4 @@
       {d838fece-fc20-42f6-bff5-97c236159b80}
     
   
-
+
\ No newline at end of file

From bd4fe9d26fb85da7ec93152a7037596a8ad6d78e Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Fri, 14 Nov 2014 17:49:15 +0100
Subject: [PATCH 44/50] Don't log coinbases.

---
 libethereum/State.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/libethereum/State.cpp b/libethereum/State.cpp
index ec2a640a9..92793f65d 100644
--- a/libethereum/State.cpp
+++ b/libethereum/State.cpp
@@ -795,8 +795,6 @@ h256 State::oldBloom() const
 LogBloom State::logBloom() const
 {
 	LogBloom ret;
-	auto sa = sha3(m_currentBlock.coinbaseAddress.ref());
-	ret.shiftBloom<3>(sa);
 	for (TransactionReceipt const& i: m_receipts)
 		ret |= i.bloom();
 	return ret;

From 7dfd83e8f5bfe8ef084e9afd23890b2e1b11bc9e Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Sun, 16 Nov 2014 12:59:16 +0100
Subject: [PATCH 45/50] Whisper API change for topics. Don't keep dead nodes.

---
 libp2p/Host.cpp       | 6 +++---
 libwhisper/Common.cpp | 2 +-
 libwhisper/Common.h   | 7 +------
 3 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp
index 4b28a63a3..be9f2f7ae 100644
--- a/libp2p/Host.cpp
+++ b/libp2p/Host.cpp
@@ -778,7 +778,7 @@ bytes Host::saveNodes() const
 		{
 			Node const& n = *(i.second);
 			// TODO: PoC-7: Figure out why it ever shares these ports.//n.address.port() >= 30300 && n.address.port() <= 30305 &&
-			if (!n.dead && n.address.port() > 0 && n.address.port() < /*49152*/32768 && n.id != id() && !isPrivateAddress(n.address.address()))
+			if (!n.dead && chrono::system_clock::now() - n.lastConnected < chrono::seconds(3600 * 48) && n.address.port() > 0 && n.address.port() < /*49152*/32768 && n.id != id() && !isPrivateAddress(n.address.address()))
 			{
 				nodes.appendList(10);
 				if (n.address.address().is_v4())
@@ -786,8 +786,8 @@ bytes Host::saveNodes() const
 				else
 					nodes << n.address.address().to_v6().to_bytes();
 				nodes << n.address.port() << n.id << (int)n.idOrigin
-					<< std::chrono::duration_cast(n.lastConnected.time_since_epoch()).count()
-					<< std::chrono::duration_cast(n.lastAttempted.time_since_epoch()).count()
+					<< chrono::duration_cast(n.lastConnected.time_since_epoch()).count()
+					<< chrono::duration_cast(n.lastAttempted.time_since_epoch()).count()
 					<< n.failedAttempts << (unsigned)n.lastDisconnect << n.score << n.rating;
 				count++;
 			}
diff --git a/libwhisper/Common.cpp b/libwhisper/Common.cpp
index 83f289875..0d54af089 100644
--- a/libwhisper/Common.cpp
+++ b/libwhisper/Common.cpp
@@ -69,7 +69,7 @@ TopicMask BuildTopicMask::toTopicMask() const
 	TopicMask ret;
 	ret.reserve(m_parts.size());
 	for (auto const& h: m_parts)
-		ret.push_back(make_pair(TopicPart(h), h ? ~TopicPart() : TopicPart()));
+		ret.push_back(make_pair(TopicPart(h), ~TopicPart()));
 	return ret;
 }
 
diff --git a/libwhisper/Common.h b/libwhisper/Common.h
index 312cbf6d3..a704a2896 100644
--- a/libwhisper/Common.h
+++ b/libwhisper/Common.h
@@ -114,17 +114,12 @@ private:
 class BuildTopicMask: BuildTopic
 {
 public:
-	enum EmptyType { Empty };
-
-	BuildTopicMask() { shift(); }
-	BuildTopicMask(EmptyType) {}
+	template  BuildTopicMask() {}
 	template  BuildTopicMask(T const& _t) { shift(_t); }
 
 	template  BuildTopicMask& shift(T const& _r) { BuildTopic::shift(_r); return *this; }
 	BuildTopicMask& shiftRaw(h256 const& _h) { BuildTopic::shiftRaw(_h); return *this; }
-	BuildTopic& shift() { m_parts.push_back(h256()); return *this; }
 
-	BuildTopicMask& operator()() { shift(); return *this; }
 	template  BuildTopicMask& operator()(T const& _t) { shift(_t); return *this; }
 
 	operator TopicMask() const { return toTopicMask(); }

From 3b17797b4604c7ad6614c62edab5d7f2475f92b6 Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Sun, 16 Nov 2014 14:50:45 +0100
Subject: [PATCH 46/50] Build fixes.

---
 libweb3jsonrpc/WebThreeStubServer.cpp | 6 +-----
 libwhisper/Common.h                   | 2 +-
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp
index 092faae09..73c938ce2 100644
--- a/libweb3jsonrpc/WebThreeStubServer.cpp
+++ b/libweb3jsonrpc/WebThreeStubServer.cpp
@@ -240,7 +240,7 @@ static shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m,
 
 static pair toWatch(Json::Value const& _json)
 {
-	shh::BuildTopicMask bt(shh::BuildTopicMask::Empty);
+	shh::BuildTopicMask bt;
 	Public to;
 
 	if (!_json["to"].empty())
@@ -252,12 +252,8 @@ static pair toWatch(Json::Value const& _json)
 			bt.shift(jsToBytes(_json["topic"].asString()));
 		else if (_json["topic"].isArray())
 			for (auto i: _json["topic"])
-			{
 				if (i.isString())
 					bt.shift(jsToBytes(i.asString()));
-				else
-					bt.shift();
-			}
 	}
 	return make_pair(bt.toTopicMask(), to);
 }
diff --git a/libwhisper/Common.h b/libwhisper/Common.h
index a704a2896..5ce7d3b1c 100644
--- a/libwhisper/Common.h
+++ b/libwhisper/Common.h
@@ -114,7 +114,7 @@ private:
 class BuildTopicMask: BuildTopic
 {
 public:
-	template  BuildTopicMask() {}
+	BuildTopicMask() {}
 	template  BuildTopicMask(T const& _t) { shift(_t); }
 
 	template  BuildTopicMask& shift(T const& _r) { BuildTopic::shift(_r); return *this; }

From c0b3f93e8e8a61df944a3bbbb5b1b01931be05c1 Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Sun, 16 Nov 2014 15:14:40 +0100
Subject: [PATCH 47/50] Fix first part of stdserv.js. Still much to do.

---
 stdserv.js | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/stdserv.js b/stdserv.js
index 55ae90d86..887586874 100644
--- a/stdserv.js
+++ b/stdserv.js
@@ -1,7 +1,9 @@
 eth = web3.eth;
+env = web3.env;
 
 env.note('Creating Config...')
-var configCode = eth.lll("
+var config;
+eth.lll("
 {
   [[69]] (caller)
   (returnlll {
@@ -12,13 +14,19 @@ var configCode = eth.lll("
     )
     (return @@ $0)
   })
-}
-")
-env.note('Config code: ' + configCode)
-var config;
-eth.transact({ 'code': configCode }, function(a) { config = a; });
+}"
+).then(function(configCode)
+{
+	console.log('Config code: ' + configCode);
+	return eth.transact({ 'code': configCode });
+}).then(function(configAddress)
+{
+	config = configAddress;
+	console.log('Config at address ' + configAddress);
+});
 
-env.note('Config at address ' + config)
+// marek: TODO
+/*
 
 var nameRegCode = eth.lll("
 {
@@ -306,7 +314,7 @@ eth.transact({ 'to': exchange, 'data': [web3.fromAscii('new'), gavCoin, '5000',
 
 env.note('Register gav.eth...')
 eth.transact({ 'to': dnsReg, 'data': [web3.fromAscii('register'), web3.fromAscii('gav'), web3.fromAscii('opensecrecy.com')] });
-
+*/
 env.note('All done.')
 
 // env.load('/home/gav/Eth/cpp-ethereum/stdserv.js')

From e2b3925683ff58beaa2b7a0f7c0d8fa00e7bc80a Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Sun, 16 Nov 2014 15:38:30 +0100
Subject: [PATCH 48/50] More fixing for std serv

---
 alethzero/MainWin.cpp |  5 ++++-
 stdserv.js            | 40 +++++++++++++++++-----------------------
 2 files changed, 21 insertions(+), 24 deletions(-)

diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index 0ad5ba938..e10d01efc 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -355,6 +355,9 @@ void Main::on_enableOptimizer_triggered()
 
 void Main::load(QString _s)
 {
+	QString contents = QString::fromStdString(dev::asString(dev::contents(_s.toStdString())));
+	ui->webView->page()->currentFrame()->evaluateJavaScript(contents);
+	/*
 	QFile fin(_s);
 	if (!fin.open(QFile::ReadOnly))
 		return;
@@ -375,7 +378,7 @@ void Main::load(QString _s)
 			//eval(line);
 			line.clear();
 		}
-	}
+	}*/
 }
 
 void Main::on_loadJS_triggered()
diff --git a/stdserv.js b/stdserv.js
index 887586874..375a8379f 100644
--- a/stdserv.js
+++ b/stdserv.js
@@ -1,29 +1,23 @@
 eth = web3.eth;
 env = web3.env;
 
-env.note('Creating Config...')
-var config;
-eth.lll("
-{
-  [[69]] (caller)
-  (returnlll {
-    (when (&& (= (calldatasize) 64) (= (caller) @@69))
-      (for {} (< @i (calldatasize)) [i](+ @i 64)
-        [[ (calldataload @i) ]] (calldataload (+ @i 32))
-      )
-    )
-    (return @@ $0)
-  })
-}"
-).then(function(configCode)
-{
-	console.log('Config code: ' + configCode);
-	return eth.transact({ 'code': configCode });
-}).then(function(configAddress)
-{
-	config = configAddress;
-	console.log('Config at address ' + configAddress);
-});
+var configSource =
+"{"+
+"  [[69]] (caller)"+
+"  (returnlll {"+
+"    (when (&& (= (calldatasize) 64) (= (caller) @@69))"+
+"      (for {} (< @i (calldatasize)) [i](+ @i 64)"+
+"        [[ (calldataload @i) ]] (calldataload (+ @i 32))"+
+"      )"+
+"    )"+
+"    (return @@ $0)"+
+"  })"+
+"}";
+
+console.log('Creating Config...')
+var config = eth.lll(configSource);
+config = config.then(function (configCode) { console.log('Config code: ' + configCode); return eth.transact({ 'code': configCode }); });
+config.then(function(configAddress) { console.log('Config at address ' + configAddress); config = configAddress; return configAddress; });
 
 // marek: TODO
 /*

From c80fe4728988f66ef0bdaadbdf4d51ce8aec235f Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Sun, 16 Nov 2014 21:07:47 +0100
Subject: [PATCH 49/50] Fix std services except DNS Reg whose contract needs
 rewriting.

---
 alethzero/MainWin.cpp                 |   7 +-
 alethzero/MainWin.h                   |   1 +
 libdevcore/CommonJS.cpp               |  31 +--
 libdevcore/CommonJS.h                 |  11 +-
 libdevcore/Exceptions.h               |   4 +-
 libethereum/Executive.cpp             |   6 +-
 libevm/VM.h                           |   2 +-
 libqethereum/QEthereum.h              |   1 +
 libweb3jsonrpc/WebThreeStubServer.cpp |   4 +-
 stdserv.js                            | 324 +++-----------------------
 10 files changed, 62 insertions(+), 329 deletions(-)

diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index e10d01efc..dc5b326bc 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -353,6 +353,11 @@ void Main::on_enableOptimizer_triggered()
 	on_data_textChanged();
 }
 
+QString Main::contents(QString _s)
+{
+	return QString::fromStdString(dev::asString(dev::contents(_s.toStdString())));
+}
+
 void Main::load(QString _s)
 {
 	QString contents = QString::fromStdString(dev::asString(dev::contents(_s.toStdString())));
@@ -682,7 +687,7 @@ void Main::on_importKeyFile_triggered()
 	try
 	{
 		js::mValue val;
-		json_spirit::read_string(asString(contents(s.toStdString())), val);
+		json_spirit::read_string(asString(dev::contents(s.toStdString())), val);
 		auto obj = val.get_obj();
 		if (obj["encseed"].type() == js::str_type)
 		{
diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h
index 9f7ad97de..14877f610 100644
--- a/alethzero/MainWin.h
+++ b/alethzero/MainWin.h
@@ -85,6 +85,7 @@ public slots:
 	void note(QString _entry);
 	void debug(QString _entry);
 	void warn(QString _entry);
+	QString contents(QString _file);
 
 	void onKeysChanged();
 
diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp
index 96f4b1896..c09a5b565 100644
--- a/libdevcore/CommonJS.cpp
+++ b/libdevcore/CommonJS.cpp
@@ -38,31 +38,20 @@ bytes jsToBytes(std::string const& _s)
 		return bytes();
 }
 
-std::string jsPadded(std::string const& _s, unsigned _l, unsigned _r)
+bytes padded(bytes _b, unsigned _l)
 {
-	bytes b = jsToBytes(_s);
-	while (b.size() < _l)
-		b.insert(b.begin(), 0);
-	while (b.size() < _r)
-		b.push_back(0);
-	return asString(b).substr(b.size() - std::max(_l, _r));
+	while (_b.size() < _l)
+		_b.insert(_b.begin(), 0);
+	while (_b.size() < _l)
+		_b.push_back(0);
+	return asBytes(asString(_b).substr(_b.size() - std::max(_l, _l)));
 }
 
-std::string jsPadded(std::string const& _s, unsigned _l)
+bytes unpadded(bytes _b)
 {
-	if (_s.substr(0, 2) == "0x" || _s.find_first_not_of("0123456789") == std::string::npos)
-		// Numeric: pad to right
-		return jsPadded(_s, _l, _l);
-	else
-		// Text: pad to the left
-		return jsPadded(_s, 0, _l);
-}
-
-std::string jsUnpadded(std::string _s)
-{
-	auto p = _s.find_last_not_of((char)0);
-	_s.resize(p == std::string::npos ? 0 : (p + 1));
-	return _s;
+	auto p = asString(_b).find_last_not_of((char)0);
+	_b.resize(p == std::string::npos ? 0 : (p + 1));
+	return _b;
 }
 
 }
diff --git a/libdevcore/CommonJS.h b/libdevcore/CommonJS.h
index be98c2372..80e1a9ca1 100644
--- a/libdevcore/CommonJS.h
+++ b/libdevcore/CommonJS.h
@@ -47,9 +47,8 @@ inline std::string toJS(dev::bytes const& _n)
 }
 
 bytes jsToBytes(std::string const& _s);
-std::string jsPadded(std::string const& _s, unsigned _l, unsigned _r);
-std::string jsPadded(std::string const& _s, unsigned _l);
-std::string jsUnpadded(std::string _s);
+bytes padded(bytes _b, unsigned _l);
+bytes unpadded(bytes _s);
 
 template  FixedHash jsToFixed(std::string const& _s)
 {
@@ -61,7 +60,7 @@ template  FixedHash jsToFixed(std::string const& _s)
 		return (typename FixedHash::Arith)(_s);
 	else
 		// Binary
-		return FixedHash(asBytes(jsPadded(_s, N)));
+		return FixedHash();	// FAIL
 }
 
 inline std::string jsToFixed(double _s)
@@ -79,7 +78,7 @@ template  boost::multiprecision::number>(_s);
 	else
 		// Binary
-		return fromBigEndian>>(asBytes(jsPadded(_s, N)));
+		return 0;			// FAIL
 }
 
 inline Address jsToAddress(std::string const& _s) { return jsToFixed(_s); }
@@ -89,7 +88,7 @@ inline u256 jsToU256(std::string const& _s) { return jsToInt<32>(_s); }
 
 inline std::string jsToBinary(std::string const& _s)
 {
-	return jsUnpadded(dev::toString(jsToBytes(_s)));
+	return dev::toString(unpadded(jsToBytes(_s)));
 }
 
 inline std::string jsToDecimal(std::string const& _s)
diff --git a/libdevcore/Exceptions.h b/libdevcore/Exceptions.h
index bbc928da4..5d03c195f 100644
--- a/libdevcore/Exceptions.h
+++ b/libdevcore/Exceptions.h
@@ -45,7 +45,7 @@ struct FileError: virtual Exception {};
 typedef boost::error_info errinfo_invalidSymbol;
 typedef boost::error_info errinfo_wrongAddress;
 typedef boost::error_info errinfo_comment;
-typedef boost::error_info errinfo_required;
-typedef boost::error_info errinfo_got;
+typedef boost::error_info errinfo_required;
+typedef boost::error_info errinfo_got;
 typedef boost::tuple RequirementError;
 }
diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp
index f8c526ac7..c3a8b2a80 100644
--- a/libethereum/Executive.cpp
+++ b/libethereum/Executive.cpp
@@ -71,7 +71,7 @@ bool Executive::setup(bytesConstRef _rlp)
 	if (m_t.gas() < gasCost)
 	{
 		clog(StateDetail) << "Not enough gas to pay for the transaction: Require >" << gasCost << " Got" << m_t.gas();
-		BOOST_THROW_EXCEPTION(OutOfGas());
+		BOOST_THROW_EXCEPTION(OutOfGas() << RequirementError((bigint)gasCost, (bigint)m_t.gas()));
 	}
 
 	u256 cost = m_t.value() + m_t.gas() * m_t.gasPrice();
@@ -80,14 +80,14 @@ bool Executive::setup(bytesConstRef _rlp)
 	if (m_s.balance(m_sender) < cost)
 	{
 		clog(StateDetail) << "Not enough cash: Require >" << cost << " Got" << m_s.balance(m_sender);
-		BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError((int)cost, (int)m_s.balance(m_sender)));
+		BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError((bigint)cost, (bigint)m_s.balance(m_sender)));
 	}
 
 	u256 startGasUsed = m_s.gasUsed();
 	if (startGasUsed + m_t.gas() > m_s.m_currentBlock.gasLimit)
 	{
 		clog(StateDetail) << "Too much gas used in this block: Require <" << (m_s.m_currentBlock.gasLimit - startGasUsed) << " Got" << m_t.gas();
-		BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((int)(m_s.m_currentBlock.gasLimit - startGasUsed), (int)m_t.gas()));
+		BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((bigint)(m_s.m_currentBlock.gasLimit - startGasUsed), (bigint)m_t.gas()));
 	}
 
 	// Increment associated nonce for sender.
diff --git a/libevm/VM.h b/libevm/VM.h
index 52149a9a1..487c8cd1a 100644
--- a/libevm/VM.h
+++ b/libevm/VM.h
@@ -71,7 +71,7 @@ public:
 	template 
 	bytesConstRef go(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1);
 
-	void require(u256 _n) { if (m_stack.size() < _n) BOOST_THROW_EXCEPTION(StackTooSmall() << RequirementError(int(_n), m_stack.size())); }
+	void require(u256 _n) { if (m_stack.size() < _n) BOOST_THROW_EXCEPTION(StackTooSmall() << RequirementError((bigint)_n, (bigint)m_stack.size())); }
 	void requireMem(unsigned _n) { if (m_temp.size() < _n) { m_temp.resize(_n); } }
 	u256 gas() const { return m_gas; }
 	u256 curPC() const { return m_curPC; }
diff --git a/libqethereum/QEthereum.h b/libqethereum/QEthereum.h
index 4f276b7e1..0824b0139 100644
--- a/libqethereum/QEthereum.h
+++ b/libqethereum/QEthereum.h
@@ -83,6 +83,7 @@ private:
 { \
 	_frame->disconnect(); \
 	_frame->addToJavaScriptWindowObject("_web3", qweb, QWebFrame::ScriptOwnership); \
+	_frame->addToJavaScriptWindowObject("env", _env, QWebFrame::QtOwnership); \
 	_frame->evaluateJavaScript(contentsOfQResource(":/js/es6-promise-2.0.0.js")); \
 	_frame->evaluateJavaScript(contentsOfQResource(":/js/main.js")); \
 	_frame->evaluateJavaScript(contentsOfQResource(":/js/qt.js")); \
diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp
index 73c938ce2..03c2a37ac 100644
--- a/libweb3jsonrpc/WebThreeStubServer.cpp
+++ b/libweb3jsonrpc/WebThreeStubServer.cpp
@@ -370,10 +370,10 @@ static TransactionSkeleton toTransaction(Json::Value const& _json)
 			ret.data = jsToBytes(_json["code"].asString());
 		else if (_json["data"].isArray())
 			for (auto i: _json["data"])
-				dev::operator +=(ret.data, jsToBytes(jsPadded(i.asString(), 32)));
+				dev::operator +=(ret.data, padded(jsToBytes(i.asString()), 32));
 		else if (_json["code"].isArray())
 			for (auto i: _json["code"])
-				dev::operator +=(ret.data, jsToBytes(jsPadded(i.asString(), 32)));
+				dev::operator +=(ret.data, padded(jsToBytes(i.asString()), 32));
 		else if (_json["dataclose"].isArray())
 			for (auto i: _json["dataclose"])
 				dev::operator +=(ret.data, jsToBytes(i.asString()));
diff --git a/stdserv.js b/stdserv.js
index 375a8379f..fe681414e 100644
--- a/stdserv.js
+++ b/stdserv.js
@@ -1,69 +1,41 @@
-eth = web3.eth;
-env = web3.env;
-
-var configSource =
-"{"+
-"  [[69]] (caller)"+
-"  (returnlll {"+
-"    (when (&& (= (calldatasize) 64) (= (caller) @@69))"+
-"      (for {} (< @i (calldatasize)) [i](+ @i 64)"+
-"        [[ (calldataload @i) ]] (calldataload (+ @i 32))"+
-"      )"+
-"    )"+
-"    (return @@ $0)"+
-"  })"+
-"}";
-
-console.log('Creating Config...')
-var config = eth.lll(configSource);
-config = config.then(function (configCode) { console.log('Config code: ' + configCode); return eth.transact({ 'code': configCode }); });
-config.then(function(configAddress) { console.log('Config at address ' + configAddress); config = configAddress; return configAddress; });
-
-// marek: TODO
+var compile = function(name) { return web3.eth.lll(env.contents("../../dapp-bin/" + name + "/" + name + ".lll")); };
+var create = function(code) { return web3.eth.transact({ 'code': code }); };
+var send = function(from, val, to) { return web3.eth.transact({ 'from': from, 'value': val, 'to': to }); };
+var initService = function(name, index, dep) { return dep.then(function(){ var ret = compile(name).then(create); register(ret, index); return ret; }); };
+
+var config = compile("config").then(create);
+var register = function(address, index) { return web3.eth.transact({ 'to': config, 'gas': '10000', 'data': [index + '', address] }); };
+var nameReg = initService("namereg", 0, config);
+var regName = function(account, name) { return web3.eth.transact({ 'from': account, 'to': nameReg, 'gas': '10000', 'data': [ web3.fromAscii('register'), web3.fromAscii(name) ] }); };
+var coins = initService("coins", 1, nameReg);
+var coin = initService("coin", 2, coins);
+var approve = function(account, approvedAddress) { web3.eth.transact({ 'from': account, 'to': coin, 'gas': '10000', 'data': [ web3.fromAscii('approve'), approvedAddress ] }); };
+var exchange = initService("exchange", 3, coin);
+var offer = function(account, haveCoin, haveVal, wantCoin, wantVal) { web3.eth.transact({ 'from': account, 'to': exchange, 'gas': '10000', 'data': [web3.fromAscii('new'), haveCoin, haveVal, wantCoin, wantVal] }); };
+
+config.then(function() {
+	web3.eth.accounts.then(function(accounts)
+	{
+		var funded = send(accounts[0], '100000000000000000000', accounts[1]);
+		funded.then(function(){ env.note("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); regName(accounts[1], 'Gav Would'); env.note("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); approve(accounts[1], exchange); });
+		regName(accounts[0], 'Gav');
+		approve(accounts[0], exchange).then(function(){ offer(accounts[0], coin, '5000', '0', '5000000000000000000'); });
+
+		// TODO: once we have a new implementation of DNSReg.
+		//	env.note('Register gav.eth...')
+		//	eth.transact({ 'to': dnsReg, 'data': [web3.fromAscii('register'), web3.fromAscii('gav'), web3.fromAscii('opensecrecy.com')] });
+	});
+});
+
+// TODO
 /*
-
-var nameRegCode = eth.lll("
-{
-  [[(address)]] 'NameReg
-  [['NameReg]] (address)
-  [[config]] 'Config
-  [['Config]] config
-  [[69]] (caller)
-  (returnlll {
-    (when (= $0 'register) {
-      (when @@ $32 (stop))
-      (when @@(caller) [[@@(caller)]] 0)
-      [[$32]] (caller)
-      [[(caller)]] $32
-      (stop)
-    })
-    (when (&& (= $0 'unregister) @@(caller)) {
-      [[@@(caller)]] 0
-      [[(caller)]] 0
-      (stop)
-    })
-    (when (&& (= $0 'kill) (= (caller) @@69)) (suicide (caller)))
-    (return @@ $0)
-  })
-}
-");
-env.note('NameReg code: ' + nameRegCode)
-
-var nameReg;
-
-env.note('Create NameReg...')
-eth.transact({ 'code': nameRegCode }, function(a) { nameReg = a; });
-
-env.note('Register NameReg...')
-eth.transact({ 'to': config, 'data': ['0', nameReg] });
-
 var nameRegJeff;
 
 env.note('Create NameRegJeff...')
 eth.transact({ 'code': nameRegCode }, function(a) { nameRegJeff = a; });
 
 env.note('Register NameRegJeff...')
-eth.transact({ 'to': config, 'data': ['4', nameReg] });
+eth.transact({ 'to': config, 'data': ['4', nameRegJeff] });
 
 var dnsRegCode = '0x60006000546000600053602001546000600053604001546020604060206020600073661005d2720d855f1d9976f88bb10c1a3398c77f6103e8f17f7265676973746572000000000000000000000000000000000000000000000000600053606001600060200201547f446e735265670000000000000000000000000000000000000000000000000000600053606001600160200201546000600060006000604060606000600053604001536103e8f1327f6f776e65720000000000000000000000000000000000000000000000000000005761011663000000e46000396101166000f20060006000547f72656769737465720000000000000000000000000000000000000000000000006000602002350e0f630000006d596000600160200235560e0f630000006c59600032560e0f0f6300000057596000325657600260200235600160200235576001602002353257007f64657265676973746572000000000000000000000000000000000000000000006000602002350e0f63000000b95960016020023532560e0f63000000b959600032576000600160200235577f6b696c6c000000000000000000000000000000000000000000000000000000006000602002350e0f630000011559327f6f776e6572000000000000000000000000000000000000000000000000000000560e0f63000001155932ff00';
 
@@ -75,240 +47,6 @@ env.note('DnsReg at address ' + dnsReg)
 
 env.note('Register DnsReg...')
 eth.transact({ 'to': config, 'data': ['4', dnsReg] });
-
-var coinRegCode = eth.lll("
-{
-(regname 'CoinReg)
-(returnlll {
-	(def 'name $0)
-	(def 'denom $32)
-	(def 'address (caller))
-	(when (|| (& 0xffffffffffffffffffffffffff name) @@name) (stop))
-	(set 'n (+ @@0 1))
-	[[0]] @n
-	[[@n]] name
-	[[name]] address
-	[[(sha3 name)]] denom
-})
-}
-");
-
-var coinReg;
-env.note('Create CoinReg...')
-eth.transact({ 'code': coinRegCode }, function(a) { coinReg = a; });
-
-env.note('Register CoinReg...')
-eth.transact({ 'to': config, 'data': ['1', coinReg] });
-
-var gavCoinCode = eth.lll("
-{
-[[ (caller) ]] 0x1000000
-[[ 0x69 ]] (caller)
-[[ 0x42 ]] (number)
-
-(regname 'GavCoin)
-(regcoin 'GAV 1000)
-
-(returnlll {
-	(when (&& (= $0 'kill) (= (caller) @@0x69)) (suicide (caller)))
-	(when (= $0 'balance) (return @@$32))
-	(when (= $0 'approved) (return @@ (sha3pair (if (= (calldatasize) 64) (caller) $64) $32)) )
-	
-	(when (= $0 'approve) {
-		[[(sha3pair (caller) $32)]] $32
-		(stop)
-	})
-
-	(when (= $0 'send) {
-		(set 'fromVar (if (= (calldatasize) 96)
-			(caller)
-			{
-				(when (! @@ (sha3pair (origin) (caller))) (return 0))
-				(origin)
-			}
-		))
-		(def 'to $32)
-		(def 'value $64)
-		(def 'from (get 'fromVar))
-		(set 'fromBal @@from)
-		(when (< @fromBal value) (return 0))
-		[[ from ]]: (- @fromBal value)
-		[[ to ]]: (+ @@to value)
-		(return 1)
-	})
-
-	(set 'n @@0x42)
-	(when (&& (|| (= $0 'mine) (! (calldatasize))) (> (number) @n)) {
-		(set 'b (- (number) @n))
-		[[(coinbase)]] (+ @@(coinbase) (* 1000 @b))
-		[[(caller)]] (+ @@(caller) (* 1000 @b))
-		[[0x42]] (number)
-		(return @b)
-	})
-
-	(return @@ $0)
-})
-}
-");
-
-var gavCoin;
-env.note('Create GavCoin...')
-eth.transact({ 'code': gavCoinCode }, function(a) { gavCoin = a; });
-
-env.note('Register GavCoin...')
-eth.transact({ 'to': config, 'data': ['2', gavCoin] });
-
-
-var exchangeCode = eth.lll("
-{
-(regname 'Exchange)
-
-(def 'min (a b) (if (< a b) a b))
-
-(def 'head (_list) @@ _list)
-(def 'next (_item) @@ _item)
-(def 'inc (itemref) [itemref]: (next @itemref))
-(def 'rateof (_item) @@ (+ _item 1))
-(def 'idof (_item) @@ (+ _item 2))
-(def 'wantof (_item) @@ (+ _item 3))
-(def 'newitem (rate who want list) {
-	(set 'pos (sha3trip rate who list))
-	[[ (+ @pos 1) ]] rate
-	[[ (+ @pos 2) ]] who
-	[[ (+ @pos 3) ]] want
-	@pos
-})
-(def 'stitchitem (parent pos) {
-	[[ pos ]] @@ parent
-	[[ parent ]] pos
-})
-(def 'addwant (_item amount) [[ (+ _item 3) ]] (+ @@ (+ _item 3) amount))
-(def 'deductwant (_item amount) [[ (+ _item 3) ]] (- @@ (+ _item 3) amount))
-
-(def 'xfer (contract to amount)
-	(if contract {
-		[0] 'send
-		[32] to
-		[64] amount
-		(msg allgas contract 0 0 96)
-	}
-		(send to amount)
-	)
-)
-
-(def 'fpdiv (a b) (/ (+ (/ b 2) (* a (exp 2 128))) b))
-(def 'fpmul (a b) (/ (* a b) (exp 2 128)) )
-
-(returnlll {
-	(when (= $0 'new) {
-		(set 'offer $32)
-		(set 'xoffer (if @offer $64 (callvalue)))
-		(set 'want $96)
-		(set 'xwant $128)
-		(set 'rate (fpdiv @xoffer @xwant))
-		(set 'irate (fpdiv @xwant @xoffer))
-
-		(unless (&& @rate @irate @xoffer @xwant) (stop))
-
-		(when @offer {
-			(set 'arg1 'send)
-			(set 'arg2 (address))
-			(set 'arg3 @xoffer)
-			(set 'arg4 (caller))
-			(unless (msg allgas @offer 0 arg1 128) (stop))
-		})
-		(set 'list (sha3pair @offer @want))
-		(set 'ilist (sha3pair @want @offer))
-
-		(set 'last @ilist)
-		(set 'item @@ @last)
-		
-		(for {} (&& @item (>= (rateof @item) @irate)) {} {
-			(set 'offerA (min @xoffer (wantof @item)))
-			(set 'wantA (fpmul @offerA (rateof @item)))
-
-			(set 'xoffer (- @xoffer @offerA))
-			(set 'xwant (- @xwant @wantA))
-
-			(deductwant @item @offerA)
-
-			(xfer @offer (idof @item) @offerA)
-			(xfer @want (caller) @wantA)
-
-			(unless @xoffer (stop))
-
-			(set 'item @@ @item)
-			[[ @last ]] @item
-		})
-
-		(set 'last @list)
-		(set 'item @@ @last)
-		
-		(set 'newpos (newitem @rate (caller) @xwant @list))
-
-		(for {} (&& @item (!= @item @newpos) (>= (rateof @item) @rate)) { (set 'last @item) (inc item) } {})
-		(if (= @item @newpos)
-			(addwant @item @wantx)
-			(stitchitem @last @newpos)
-		)
-		(stop)
-	})
-	(when (= $0 'delete) {
-		(set 'offer $32)
-		(set 'want $64)
-		(set 'rate $96)
-		(set 'list (sha3pair @offer @want))
-		(set 'last @list)
-		(set 'item @@ @last)
-		(for {} (&& @item (!= (idof @item) (caller)) (!= (rateof @item) @rate)) { (set 'last @item) (inc item) } {})
-		(when @item {
-			(set 'xoffer (fpmul (wantof @item) (rateof @item)))
-			[[ @last ]] @@ @item
-			(xfer @offer (caller) @xoffer)
-		})
-		(stop)
-	})
-	(when (= $0 'price) {
-		(set 'offer $32)
-		(set 'want $96)
-		(set 'item (head (sha3pair @offer @want)))
-		(return (if @item (rateof @list) 0))
-	})
-})
-}
-");
-
-var exchange;
-env.note('Create Exchange...')
-eth.transact({ 'code': exchangeCode }, function(a) { exchange = a; });
-
-env.note('Register Exchange...')
-eth.transact({ 'to': config, 'data': ['3', exchange] });
-
-
-
-
-env.note('Register my name...')
-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': [ web3.fromAscii('register'), web3.fromAscii("Gav Would") ] });
-
-env.note('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': [ web3.fromAscii('approve'), exchange ] });
-
-env.note('Make offer 5000GAV/5ETH...')
-eth.transact({ 'to': exchange, 'data': [web3.fromAscii('new'), gavCoin, '5000', '0', '5000000000000000000'] });
-
-env.note('Register gav.eth...')
-eth.transact({ 'to': dnsReg, 'data': [web3.fromAscii('register'), web3.fromAscii('gav'), web3.fromAscii('opensecrecy.com')] });
 */
-env.note('All done.')
 
 // env.load('/home/gav/Eth/cpp-ethereum/stdserv.js')

From d7972e726dccccdcecc826944dba49de731ef9b1 Mon Sep 17 00:00:00 2001
From: Gav Wood 
Date: Sun, 16 Nov 2014 21:26:39 +0100
Subject: [PATCH 50/50] Minor UI changes and reduction of verbosity.

---
 alethzero/MainWin.cpp                 | 2 +-
 libethereum/State.cpp                 | 4 ++--
 libp2p/Host.cpp                       | 2 +-
 libweb3jsonrpc/WebThreeStubServer.cpp | 4 ++--
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index dc5b326bc..280a70fe1 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -956,7 +956,7 @@ void Main::refreshBlockCount()
 	cwatch << "refreshBlockCount()";
 	auto d = ethereum()->blockChain().details();
 	auto diff = BlockInfo(ethereum()->blockChain().block()).difficulty;
-	ui->blockCount->setText(QString("%6 #%1 @%3 T%2 N%4 D%5").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(dev::eth::c_protocolVersion).arg(dev::eth::c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet"));
+	ui->blockCount->setText(QString("%6 #%1 @%3 T%2 PV%4 D%5").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(dev::eth::c_protocolVersion).arg(dev::eth::c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet"));
 }
 
 static bool blockMatch(string const& _f, dev::eth::BlockDetails const& _b, h256 _h, BlockChain const& _bc)
diff --git a/libethereum/State.cpp b/libethereum/State.cpp
index ee93fdc55..69faf983c 100644
--- a/libethereum/State.cpp
+++ b/libethereum/State.cpp
@@ -322,8 +322,8 @@ StateDiff State::diff(State const& _c) const
 	for (auto i: _c.m_cache)
 		ads.insert(i.first);
 
-	cnote << *this;
-	cnote << _c;
+//	cnote << *this;
+//	cnote << _c;
 
 	for (auto i: ads)
 	{
diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp
index be9f2f7ae..996e219db 100644
--- a/libp2p/Host.cpp
+++ b/libp2p/Host.cpp
@@ -385,7 +385,7 @@ void Host::populateAddresses()
 shared_ptr Host::noteNode(NodeId _id, bi::tcp::endpoint _a, Origin _o, bool _ready, NodeId _oldId)
 {
 	RecursiveGuard l(x_peers);
-	if (_a.port() < 30300 || _a.port() > 30303)
+	if (_a.port() < 30300 || _a.port() > 30305)
 		cwarn << "Weird port being recorded: " << _a.port();
 
 	if (_a.port() >= /*49152*/32768)
diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp
index 03c2a37ac..5b362cde5 100644
--- a/libweb3jsonrpc/WebThreeStubServer.cpp
+++ b/libweb3jsonrpc/WebThreeStubServer.cpp
@@ -507,7 +507,7 @@ std::string WebThreeStubServer::shh_newGroup(std::string const& _id, std::string
 
 std::string WebThreeStubServer::shh_newIdentity()
 {
-	cnote << this << m_ids;
+//	cnote << this << m_ids;
 	KeyPair kp = KeyPair::create();
 	m_ids[kp.pub()] = kp.secret();
 	return toJS(kp.pub());
@@ -535,7 +535,7 @@ int WebThreeStubServer::eth_peerCount()
 
 bool WebThreeStubServer::shh_post(Json::Value const& _json)
 {
-	cnote << this << m_ids;
+//	cnote << this << m_ids;
 	shh::Message m = toMessage(_json);
 	Secret from;