From 9aecd10a6658e075277dab224ca71def29da39f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Apr 2015 12:56:01 +0200 Subject: [PATCH 001/290] Revert not needed LLVM workarounds --- evmjit/libevmjit/Arith256.cpp | 104 ++++++++++++++++------------------ evmjit/libevmjit/Compiler.cpp | 13 ++--- 2 files changed, 55 insertions(+), 62 deletions(-) diff --git a/evmjit/libevmjit/Arith256.cpp b/evmjit/libevmjit/Arith256.cpp index 029eb9370..c7608c5b8 100644 --- a/evmjit/libevmjit/Arith256.cpp +++ b/evmjit/libevmjit/Arith256.cpp @@ -360,18 +360,17 @@ llvm::Value* Arith256::mul(llvm::Value* _arg1, llvm::Value* _arg2) std::pair Arith256::div(llvm::Value* _arg1, llvm::Value* _arg2) { - // FIXME: Disabled because of llvm::APInt::urem bug -// if (auto c1 = llvm::dyn_cast(_arg1)) -// { -// if (auto c2 = llvm::dyn_cast(_arg2)) -// { -// if (!c2->getValue()) -// return std::make_pair(Constant::get(0), Constant::get(0)); -// auto div = Constant::get(c1->getValue().udiv(c2->getValue())); -// auto mod = Constant::get(c1->getValue().urem(c2->getValue())); -// return std::make_pair(div, mod); -// } -// } + if (auto c1 = llvm::dyn_cast(_arg1)) + { + if (auto c2 = llvm::dyn_cast(_arg2)) + { + if (!c2->getValue()) + return std::make_pair(Constant::get(0), Constant::get(0)); + auto div = Constant::get(c1->getValue().udiv(c2->getValue())); + auto mod = Constant::get(c1->getValue().urem(c2->getValue())); + return std::make_pair(div, mod); + } + } auto r = createCall(getDivFunc(Type::Word), {_arg1, _arg2}); auto div = m_builder.CreateExtractValue(r, 0, "div"); @@ -381,18 +380,17 @@ std::pair Arith256::div(llvm::Value* _arg1, llvm::Va std::pair Arith256::sdiv(llvm::Value* _x, llvm::Value* _y) { - // FIXME: Disabled because of llvm::APInt::urem bug -// if (auto c1 = llvm::dyn_cast(_x)) -// { -// if (auto c2 = llvm::dyn_cast(_y)) -// { -// if (!c2->getValue()) -// return std::make_pair(Constant::get(0), Constant::get(0)); -// auto div = Constant::get(c1->getValue().sdiv(c2->getValue())); -// auto mod = Constant::get(c1->getValue().srem(c2->getValue())); -// return std::make_pair(div, mod); -// } -// } + if (auto c1 = llvm::dyn_cast(_x)) + { + if (auto c2 = llvm::dyn_cast(_y)) + { + if (!c2->getValue()) + return std::make_pair(Constant::get(0), Constant::get(0)); + auto div = Constant::get(c1->getValue().sdiv(c2->getValue())); + auto mod = Constant::get(c1->getValue().srem(c2->getValue())); + return std::make_pair(div, mod); + } + } auto xIsNeg = m_builder.CreateICmpSLT(_x, Constant::get(0)); auto xNeg = m_builder.CreateSub(Constant::get(0), _x); @@ -447,42 +445,40 @@ llvm::Value* Arith256::exp(llvm::Value* _arg1, llvm::Value* _arg2) llvm::Value* Arith256::addmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3) { - // FIXME: Disabled because of llvm::APInt::urem bug -// if (auto c1 = llvm::dyn_cast(_arg1)) -// { -// if (auto c2 = llvm::dyn_cast(_arg2)) -// { -// if (auto c3 = llvm::dyn_cast(_arg3)) -// { -// if (!c3->getValue()) -// return Constant::get(0); -// auto s = c1->getValue().zext(256+64) + c2->getValue().zext(256+64); -// auto r = s.urem(c3->getValue().zext(256+64)).trunc(256); -// return Constant::get(r); -// } -// } -// } + if (auto c1 = llvm::dyn_cast(_arg1)) + { + if (auto c2 = llvm::dyn_cast(_arg2)) + { + if (auto c3 = llvm::dyn_cast(_arg3)) + { + if (!c3->getValue()) + return Constant::get(0); + auto s = c1->getValue().zext(256+64) + c2->getValue().zext(256+64); + auto r = s.urem(c3->getValue().zext(256+64)).trunc(256); + return Constant::get(r); + } + } + } return createCall(getAddModFunc(), {_arg1, _arg2, _arg3}); } llvm::Value* Arith256::mulmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3) { - // FIXME: Disabled because of llvm::APInt::urem bug -// if (auto c1 = llvm::dyn_cast(_arg1)) -// { -// if (auto c2 = llvm::dyn_cast(_arg2)) -// { -// if (auto c3 = llvm::dyn_cast(_arg3)) -// { -// if (!c3->getValue()) -// return Constant::get(0); -// auto p = c1->getValue().zext(512) * c2->getValue().zext(512); -// auto r = p.urem(c3->getValue().zext(512)).trunc(256); -// return Constant::get(r); -// } -// } -// } + if (auto c1 = llvm::dyn_cast(_arg1)) + { + if (auto c2 = llvm::dyn_cast(_arg2)) + { + if (auto c3 = llvm::dyn_cast(_arg3)) + { + if (!c3->getValue()) + return Constant::get(0); + auto p = c1->getValue().zext(512) * c2->getValue().zext(512); + auto r = p.urem(c3->getValue().zext(512)).trunc(256); + return Constant::get(r); + } + } + } return createCall(getMulModFunc(), {_arg1, _arg2, _arg3}); } diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index d5cb493ab..25f5932df 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -417,17 +417,14 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti case Instruction::BYTE: { - const auto byteNum = stack.pop(); - auto value = stack.pop(); + const auto idx = stack.pop(); + auto value = Endianness::toBE(m_builder, stack.pop()); - value = Endianness::toBE(m_builder, value); + auto idxValid = m_builder.CreateICmpULT(idx, Constant::get(32), "idxValid"); auto bytes = m_builder.CreateBitCast(value, llvm::VectorType::get(Type::Byte, 32), "bytes"); - auto safeByteNum = m_builder.CreateZExt(m_builder.CreateTrunc(byteNum, m_builder.getIntNTy(5)), Type::lowPrecision); // Trim index, large values can crash - auto byte = m_builder.CreateExtractElement(bytes, safeByteNum, "byte"); + auto byte = m_builder.CreateExtractElement(bytes, idx, "byte"); value = m_builder.CreateZExt(byte, Type::Word); - - auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32)); - value = m_builder.CreateSelect(byteNumValid, value, Constant::get(0)); + value = m_builder.CreateSelect(idxValid, value, Constant::get(0)); stack.push(value); break; } From e968c6537259b38e0ed77871dc0cc49a70f36e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Apr 2015 13:34:16 +0200 Subject: [PATCH 002/290] Remove unused stuff --- evmjit/libevmjit/Compiler.cpp | 9 ++------- evmjit/libevmjit/CompilerHelper.h | 25 +------------------------ evmjit/libevmjit/Memory.cpp | 5 ++--- evmjit/libevmjit/RuntimeManager.cpp | 3 +-- evmjit/libevmjit/Type.cpp | 3 --- evmjit/libevmjit/Type.h | 4 ---- 6 files changed, 6 insertions(+), 43 deletions(-) diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 25f5932df..92a2b0e0c 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -455,7 +455,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti auto word = stack.pop(); auto k32_ = m_builder.CreateTrunc(idx, m_builder.getIntNTy(5), "k_32"); - auto k32 = m_builder.CreateZExt(k32_, Type::lowPrecision); + auto k32 = m_builder.CreateZExt(k32_, Type::Size); auto k32x8 = m_builder.CreateMul(k32, m_builder.getInt64(8), "kx8"); // test for word >> (k * 8 + 7) @@ -492,11 +492,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti case Instruction::POP: { - auto val = stack.pop(); - static_cast(val); - // Generate a dummy use of val to make sure that a get(0) will be emitted at this point, - // so that StackUnderflow will be thrown - // m_builder.CreateICmpEQ(val, val, "dummy"); + stack.pop(); break; } @@ -653,7 +649,6 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti } case Instruction::CODESIZE: - // TODO: Use constant stack.push(_runtimeManager.getCodeSize()); break; diff --git a/evmjit/libevmjit/CompilerHelper.h b/evmjit/libevmjit/CompilerHelper.h index cd6d09a58..5eeae9a6e 100644 --- a/evmjit/libevmjit/CompilerHelper.h +++ b/evmjit/libevmjit/CompilerHelper.h @@ -37,7 +37,6 @@ protected: friend class RuntimeHelper; }; - /// Compiler helper that depends on runtime data class RuntimeHelper : public CompilerHelper { @@ -50,29 +49,7 @@ private: RuntimeManager& m_runtimeManager; }; - -/// Saves the insert point of the IR builder and restores it when destructed -struct InsertPointGuard -{ - InsertPointGuard(llvm::IRBuilder<>& _builder) : - m_builder(_builder), - m_insertBB(m_builder.GetInsertBlock()), - m_insertPt(m_builder.GetInsertPoint()) - {} - - InsertPointGuard(const InsertPointGuard&) = delete; - void operator=(InsertPointGuard) = delete; - - ~InsertPointGuard() - { - m_builder.SetInsertPoint(m_insertBB, m_insertPt); - } - -private: - llvm::IRBuilder<>& m_builder; - llvm::BasicBlock* m_insertBB; - llvm::BasicBlock::iterator m_insertPt; -}; +using InsertPointGuard = llvm::IRBuilderBase::InsertPointGuard; } } diff --git a/evmjit/libevmjit/Memory.cpp b/evmjit/libevmjit/Memory.cpp index 79a82a8ae..6d5b72024 100644 --- a/evmjit/libevmjit/Memory.cpp +++ b/evmjit/libevmjit/Memory.cpp @@ -191,8 +191,7 @@ llvm::Value* Memory::getSize() llvm::Value* Memory::getBytePtr(llvm::Value* _index) { - auto idx = m_builder.CreateTrunc(_index, Type::Size, "idx"); // Never allow memory index be a type bigger than i64 - return m_builder.CreateGEP(getData(), idx, "ptr"); + return m_builder.CreateGEP(getData(), _index, "ptr"); } void Memory::require(llvm::Value* _offset, llvm::Value* _size) @@ -235,7 +234,7 @@ void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* auto bytesToZero = m_builder.CreateNUWSub(reqBytes, bytesToCopy, "bytesToZero"); auto src = m_builder.CreateGEP(_srcPtr, idx64, "src"); - auto dstIdx = m_builder.CreateTrunc(_destMemIdx, Type::Size, "dstIdx"); // Never allow memory index be a type bigger than i64 + auto dstIdx = m_builder.CreateTrunc(_destMemIdx, Type::Size, "dstIdx"); auto padIdx = m_builder.CreateNUWAdd(dstIdx, bytesToCopy, "padIdx"); auto dst = m_memory.getPtr(getRuntimeManager().getMem(), dstIdx); auto pad = m_memory.getPtr(getRuntimeManager().getMem(), padIdx); diff --git a/evmjit/libevmjit/RuntimeManager.cpp b/evmjit/libevmjit/RuntimeManager.cpp index 5c66a5a21..8d000f4c8 100644 --- a/evmjit/libevmjit/RuntimeManager.cpp +++ b/evmjit/libevmjit/RuntimeManager.cpp @@ -194,8 +194,7 @@ void RuntimeManager::registerReturnData(llvm::Value* _offset, llvm::Value* _size { auto memPtr = m_builder.CreateBitCast(getMem(), Type::BytePtr->getPointerTo()); auto mem = getBuilder().CreateLoad(memPtr, "memory"); - auto idx = m_builder.CreateTrunc(_offset, Type::Size, "idx"); // Never allow memory index be a type bigger than i64 // TODO: Report bug & fix to LLVM - auto returnDataPtr = getBuilder().CreateGEP(mem, idx); + auto returnDataPtr = getBuilder().CreateGEP(mem, _offset); set(RuntimeData::ReturnData, returnDataPtr); auto size64 = getBuilder().CreateTrunc(_size, Type::Size); diff --git a/evmjit/libevmjit/Type.cpp b/evmjit/libevmjit/Type.cpp index 00a143dea..6ac9a6467 100644 --- a/evmjit/libevmjit/Type.cpp +++ b/evmjit/libevmjit/Type.cpp @@ -13,7 +13,6 @@ namespace jit llvm::IntegerType* Type::Word; llvm::PointerType* Type::WordPtr; -llvm::IntegerType* Type::lowPrecision; llvm::IntegerType* Type::Bool; llvm::IntegerType* Type::Size; llvm::IntegerType* Type::Gas; @@ -34,8 +33,6 @@ void Type::init(llvm::LLVMContext& _context) { Word = llvm::Type::getIntNTy(_context, 256); WordPtr = Word->getPointerTo(); - lowPrecision = llvm::Type::getInt64Ty(_context); - // TODO: Size should be architecture-dependent Bool = llvm::Type::getInt1Ty(_context); Size = llvm::Type::getInt64Ty(_context); Gas = Size; diff --git a/evmjit/libevmjit/Type.h b/evmjit/libevmjit/Type.h index fcca98d74..ba9181f6b 100644 --- a/evmjit/libevmjit/Type.h +++ b/evmjit/libevmjit/Type.h @@ -20,10 +20,6 @@ struct Type static llvm::IntegerType* Word; static llvm::PointerType* WordPtr; - /// Type for doing low precision arithmetics where 256-bit precision is not supported by native target - /// @TODO: Use 64-bit for now. In 128-bit compiler-rt library functions are required - static llvm::IntegerType* lowPrecision; - static llvm::IntegerType* Bool; static llvm::IntegerType* Size; static llvm::IntegerType* Gas; From 008ca8d4f9d74bfa791d619382630c386400aa9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Apr 2015 16:24:57 +0200 Subject: [PATCH 003/290] Move calldataload procedure to LLVM IR --- evmjit/libevmjit/Compiler.cpp | 4 ++-- evmjit/libevmjit/Ext.cpp | 23 ++++++++++++++++++----- evmjit/libevmjit/Ext.h | 1 - evmjit/libevmjit/Stack.cpp | 29 ----------------------------- 4 files changed, 20 insertions(+), 37 deletions(-) diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 92a2b0e0c..d7240a415 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -721,8 +721,8 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti case Instruction::CALLDATALOAD: { - auto index = stack.pop(); - auto value = _ext.calldataload(index); + auto idx = stack.pop(); + auto value = _ext.calldataload(idx); stack.push(value); break; } diff --git a/evmjit/libevmjit/Ext.cpp b/evmjit/libevmjit/Ext.cpp index d35aebc68..9b1e0983b 100644 --- a/evmjit/libevmjit/Ext.cpp +++ b/evmjit/libevmjit/Ext.cpp @@ -45,7 +45,6 @@ std::array::value> const& getEnvFuncDescs() FuncDesc{"env_log", getFunctionType(Type::Void, {Type::EnvPtr, Type::BytePtr, Type::Size, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr})}, FuncDesc{"env_blockhash", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})}, FuncDesc{"env_extcode", getFunctionType(Type::BytePtr, {Type::EnvPtr, Type::WordPtr, Type::Size->getPointerTo()})}, - FuncDesc{"ext_calldataload", getFunctionType(Type::Void, {Type::RuntimeDataPtr, Type::WordPtr, Type::WordPtr})}, }}; return descs; @@ -101,12 +100,26 @@ void Ext::sstore(llvm::Value* _index, llvm::Value* _value) createCall(EnvFunc::sstore, {getRuntimeManager().getEnvPtr(), byPtr(_index), byPtr(_value)}); // Uses native endianness } -llvm::Value* Ext::calldataload(llvm::Value* _index) +llvm::Value* Ext::calldataload(llvm::Value* _idx) { auto ret = getArgAlloca(); - createCall(EnvFunc::calldataload, {getRuntimeManager().getDataPtr(), byPtr(_index), ret}); - ret = m_builder.CreateLoad(ret); - return Endianness::toNative(m_builder, ret); + auto result = m_builder.CreateBitCast(ret, Type::BytePtr); + + auto callDataSize = getRuntimeManager().getCallDataSize(); + auto callDataSize64 = m_builder.CreateTrunc(callDataSize, Type::Size); + auto idxValid = m_builder.CreateICmpULT(_idx, callDataSize); + auto idx = m_builder.CreateTrunc(m_builder.CreateSelect(idxValid, _idx, callDataSize), Type::Size, "idx"); + + auto end = m_builder.CreateNUWAdd(idx, m_builder.getInt64(32)); + end = m_builder.CreateSelect(m_builder.CreateICmpULE(end, callDataSize64), end, callDataSize64); + auto copySize = m_builder.CreateNUWSub(end, idx); + auto padSize = m_builder.CreateNUWSub(m_builder.getInt64(32), copySize); + auto dataBegin = m_builder.CreateGEP(Type::Byte, getRuntimeManager().getCallData(), idx); + m_builder.CreateMemCpy(result, dataBegin, copySize, 1); + auto pad = m_builder.CreateGEP(Type::Byte, result, copySize); + m_builder.CreateMemSet(pad, m_builder.getInt8(0), padSize, 1); + + return Endianness::toNative(m_builder, m_builder.CreateLoad(ret)); } llvm::Value* Ext::balance(llvm::Value* _address) diff --git a/evmjit/libevmjit/Ext.h b/evmjit/libevmjit/Ext.h index b0048d2e9..760f77df5 100644 --- a/evmjit/libevmjit/Ext.h +++ b/evmjit/libevmjit/Ext.h @@ -35,7 +35,6 @@ enum class EnvFunc log, blockhash, extcode, - calldataload, // Helper function, not client Env interface _size }; diff --git a/evmjit/libevmjit/Stack.cpp b/evmjit/libevmjit/Stack.cpp index 3a686c766..7cf514dea 100644 --- a/evmjit/libevmjit/Stack.cpp +++ b/evmjit/libevmjit/Stack.cpp @@ -175,32 +175,3 @@ void Stack::push(llvm::Value* _value) } } } - -extern "C" -{ - using namespace dev::eth::jit; - - EXPORT void ext_calldataload(RuntimeData* _rtData, i256* _index, byte* o_value) - { - // It asumes all indexes are less than 2^64 - - auto index = _index->a; - if (_index->b || _index->c || _index->d) // if bigger that 2^64 - index = std::numeric_limits::max(); // set max to fill with 0 leter - - auto data = _rtData->callData; - auto size = _rtData->callDataSize; - for (auto i = 0; i < 32; ++i) - { - if (index < size) - { - o_value[i] = data[index]; - ++index; // increment only if in range - } - else - o_value[i] = 0; - } - } - -} // extern "C" - From 78c97ea0af6421af9c539b8cdb66db20b31bb619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Apr 2015 17:50:01 +0200 Subject: [PATCH 004/290] Implementation of MUL workaround in "LLVM pass" way. --- evmjit/libevmjit/Arith256.cpp | 125 +++++++++++++-------------- evmjit/libevmjit/Arith256.h | 5 +- evmjit/libevmjit/Compiler.cpp | 2 +- evmjit/libevmjit/ExecutionEngine.cpp | 2 + evmjit/libevmjit/Optimizer.cpp | 59 +++++++++++++ evmjit/libevmjit/Optimizer.h | 2 + 6 files changed, 124 insertions(+), 71 deletions(-) diff --git a/evmjit/libevmjit/Arith256.cpp b/evmjit/libevmjit/Arith256.cpp index c7608c5b8..d8e4c5138 100644 --- a/evmjit/libevmjit/Arith256.cpp +++ b/evmjit/libevmjit/Arith256.cpp @@ -4,6 +4,7 @@ #include #include "preprocessor/llvm_includes_start.h" +#include #include #include "preprocessor/llvm_includes_end.h" @@ -32,57 +33,56 @@ void Arith256::debug(llvm::Value* _value, char _c) createCall(m_debug, {m_builder.CreateZExtOrTrunc(_value, Type::Word), m_builder.getInt8(_c)}); } -llvm::Function* Arith256::getMulFunc() +llvm::Function* Arith256::getMulFunc(llvm::Module& _module) { - auto& func = m_mul; - if (!func) - { - llvm::Type* argTypes[] = {Type::Word, Type::Word}; - func = llvm::Function::Create(llvm::FunctionType::get(Type::Word, argTypes, false), llvm::Function::PrivateLinkage, "mul", getModule()); - func->setDoesNotThrow(); - func->setDoesNotAccessMemory(); - - auto x = &func->getArgumentList().front(); - x->setName("x"); - auto y = x->getNextNode(); - y->setName("y"); - - InsertPointGuard guard{m_builder}; - auto bb = llvm::BasicBlock::Create(m_builder.getContext(), {}, func); - m_builder.SetInsertPoint(bb); - auto i64 = Type::Size; - auto i128 = m_builder.getIntNTy(128); - auto i256 = Type::Word; - auto c64 = Constant::get(64); - auto c128 = Constant::get(128); - auto c192 = Constant::get(192); - - auto x_lo = m_builder.CreateTrunc(x, i64, "x.lo"); - auto y_lo = m_builder.CreateTrunc(y, i64, "y.lo"); - auto x_mi = m_builder.CreateTrunc(m_builder.CreateLShr(x, c64), i64); - auto y_mi = m_builder.CreateTrunc(m_builder.CreateLShr(y, c64), i64); - auto x_hi = m_builder.CreateTrunc(m_builder.CreateLShr(x, c128), i128); - auto y_hi = m_builder.CreateTrunc(m_builder.CreateLShr(y, c128), i128); - - auto t1 = m_builder.CreateMul(m_builder.CreateZExt(x_lo, i128), m_builder.CreateZExt(y_lo, i128)); - auto t2 = m_builder.CreateMul(m_builder.CreateZExt(x_lo, i128), m_builder.CreateZExt(y_mi, i128)); - auto t3 = m_builder.CreateMul(m_builder.CreateZExt(x_lo, i128), y_hi); - auto t4 = m_builder.CreateMul(m_builder.CreateZExt(x_mi, i128), m_builder.CreateZExt(y_lo, i128)); - auto t5 = m_builder.CreateMul(m_builder.CreateZExt(x_mi, i128), m_builder.CreateZExt(y_mi, i128)); - auto t6 = m_builder.CreateMul(m_builder.CreateZExt(x_mi, i128), y_hi); - auto t7 = m_builder.CreateMul(x_hi, m_builder.CreateZExt(y_lo, i128)); - auto t8 = m_builder.CreateMul(x_hi, m_builder.CreateZExt(y_mi, i128)); - - auto p = m_builder.CreateZExt(t1, i256); - p = m_builder.CreateAdd(p, m_builder.CreateShl(m_builder.CreateZExt(t2, i256), c64)); - p = m_builder.CreateAdd(p, m_builder.CreateShl(m_builder.CreateZExt(t3, i256), c128)); - p = m_builder.CreateAdd(p, m_builder.CreateShl(m_builder.CreateZExt(t4, i256), c64)); - p = m_builder.CreateAdd(p, m_builder.CreateShl(m_builder.CreateZExt(t5, i256), c128)); - p = m_builder.CreateAdd(p, m_builder.CreateShl(m_builder.CreateZExt(t6, i256), c192)); - p = m_builder.CreateAdd(p, m_builder.CreateShl(m_builder.CreateZExt(t7, i256), c128)); - p = m_builder.CreateAdd(p, m_builder.CreateShl(m_builder.CreateZExt(t8, i256), c192)); - m_builder.CreateRet(p); - } + static const auto funcName = "evm.mul.i256"; + if (auto func = _module.getFunction(funcName)) + return func; + + llvm::Type* argTypes[] = {Type::Word, Type::Word}; + auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Word, argTypes, false), llvm::Function::PrivateLinkage, funcName, &_module); + func->setDoesNotThrow(); + func->setDoesNotAccessMemory(); + + auto x = &func->getArgumentList().front(); + x->setName("x"); + auto y = x->getNextNode(); + y->setName("y"); + + auto bb = llvm::BasicBlock::Create(_module.getContext(), {}, func); + auto builder = llvm::IRBuilder<>{bb}; + auto i64 = Type::Size; + auto i128 = builder.getIntNTy(128); + auto i256 = Type::Word; + auto c64 = Constant::get(64); + auto c128 = Constant::get(128); + auto c192 = Constant::get(192); + + auto x_lo = builder.CreateTrunc(x, i64, "x.lo"); + auto y_lo = builder.CreateTrunc(y, i64, "y.lo"); + auto x_mi = builder.CreateTrunc(builder.CreateLShr(x, c64), i64); + auto y_mi = builder.CreateTrunc(builder.CreateLShr(y, c64), i64); + auto x_hi = builder.CreateTrunc(builder.CreateLShr(x, c128), i128); + auto y_hi = builder.CreateTrunc(builder.CreateLShr(y, c128), i128); + + auto t1 = builder.CreateMul(builder.CreateZExt(x_lo, i128), builder.CreateZExt(y_lo, i128)); + auto t2 = builder.CreateMul(builder.CreateZExt(x_lo, i128), builder.CreateZExt(y_mi, i128)); + auto t3 = builder.CreateMul(builder.CreateZExt(x_lo, i128), y_hi); + auto t4 = builder.CreateMul(builder.CreateZExt(x_mi, i128), builder.CreateZExt(y_lo, i128)); + auto t5 = builder.CreateMul(builder.CreateZExt(x_mi, i128), builder.CreateZExt(y_mi, i128)); + auto t6 = builder.CreateMul(builder.CreateZExt(x_mi, i128), y_hi); + auto t7 = builder.CreateMul(x_hi, builder.CreateZExt(y_lo, i128)); + auto t8 = builder.CreateMul(x_hi, builder.CreateZExt(y_mi, i128)); + + auto p = builder.CreateZExt(t1, i256); + p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t2, i256), c64)); + p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t3, i256), c128)); + p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t4, i256), c64)); + p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t5, i256), c128)); + p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t6, i256), c192)); + p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t7, i256), c128)); + p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t8, i256), c192)); + builder.CreateRet(p); return func; } @@ -112,10 +112,11 @@ llvm::Function* Arith256::getMul512Func() auto x_hi = m_builder.CreateZExt(m_builder.CreateTrunc(m_builder.CreateLShr(x, Constant::get(128)), i128, "x.hi"), i256); auto y_hi = m_builder.CreateZExt(m_builder.CreateTrunc(m_builder.CreateLShr(y, Constant::get(128)), i128, "y.hi"), i256); - auto t1 = createCall(getMulFunc(), {x_lo, y_lo}); - auto t2 = createCall(getMulFunc(), {x_lo, y_hi}); - auto t3 = createCall(getMulFunc(), {x_hi, y_lo}); - auto t4 = createCall(getMulFunc(), {x_hi, y_hi}); + auto mul256Func = getMulFunc(*getModule()); + auto t1 = createCall(mul256Func, {x_lo, y_lo}); + auto t2 = createCall(mul256Func, {x_lo, y_hi}); + auto t3 = createCall(mul256Func, {x_hi, y_lo}); + auto t4 = createCall(mul256Func, {x_hi, y_hi}); auto p = m_builder.CreateZExt(t1, i512); p = m_builder.CreateAdd(p, m_builder.CreateShl(m_builder.CreateZExt(t2, i512), m_builder.getIntN(512, 128))); @@ -260,14 +261,15 @@ llvm::Function* Arith256::getExpFunc() m_builder.CreateCondBr(eOdd, updateBB, continueBB); m_builder.SetInsertPoint(updateBB); - auto r0 = createCall(getMulFunc(), {r, b}); + auto mul256Func = getMulFunc(*getModule()); + auto r0 = createCall(mul256Func, {r, b}); m_builder.CreateBr(continueBB); m_builder.SetInsertPoint(continueBB); auto r1 = m_builder.CreatePHI(Type::Word, 2, "r1"); r1->addIncoming(r, bodyBB); r1->addIncoming(r0, updateBB); - auto b1 = createCall(getMulFunc(), {b, b}); + auto b1 = createCall(mul256Func, {b, b}); auto e1 = m_builder.CreateLShr(e, Constant::get(1), "e1"); m_builder.CreateBr(headerBB); @@ -347,17 +349,6 @@ llvm::Function* Arith256::getMulModFunc() return m_mulmod; } -llvm::Value* Arith256::mul(llvm::Value* _arg1, llvm::Value* _arg2) -{ - if (auto c1 = llvm::dyn_cast(_arg1)) - { - if (auto c2 = llvm::dyn_cast(_arg2)) - return Constant::get(c1->getValue() * c2->getValue()); - } - - return createCall(getMulFunc(), {_arg1, _arg2}); -} - std::pair Arith256::div(llvm::Value* _arg1, llvm::Value* _arg2) { if (auto c1 = llvm::dyn_cast(_arg1)) diff --git a/evmjit/libevmjit/Arith256.h b/evmjit/libevmjit/Arith256.h index 2513ca568..a5762429d 100644 --- a/evmjit/libevmjit/Arith256.h +++ b/evmjit/libevmjit/Arith256.h @@ -14,7 +14,6 @@ class Arith256 : public CompilerHelper public: Arith256(llvm::IRBuilder<>& _builder); - llvm::Value* mul(llvm::Value* _arg1, llvm::Value* _arg2); std::pair div(llvm::Value* _arg1, llvm::Value* _arg2); std::pair sdiv(llvm::Value* _arg1, llvm::Value* _arg2); llvm::Value* exp(llvm::Value* _arg1, llvm::Value* _arg2); @@ -23,15 +22,15 @@ public: void debug(llvm::Value* _value, char _c); + static llvm::Function* getMulFunc(llvm::Module& _module); + private: - llvm::Function* getMulFunc(); llvm::Function* getMul512Func(); llvm::Function* getDivFunc(llvm::Type* _type); llvm::Function* getExpFunc(); llvm::Function* getAddModFunc(); llvm::Function* getMulModFunc(); - llvm::Function* m_mul = nullptr; llvm::Function* m_mul512 = nullptr; llvm::Function* m_div = nullptr; llvm::Function* m_div512 = nullptr; diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index d7240a415..a2f58c770 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -270,7 +270,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res = _arith.mul(lhs, rhs); + auto res = m_builder.CreateMul(lhs, rhs); stack.push(res); break; } diff --git a/evmjit/libevmjit/ExecutionEngine.cpp b/evmjit/libevmjit/ExecutionEngine.cpp index fba9cfd96..b7cf41010 100644 --- a/evmjit/libevmjit/ExecutionEngine.cpp +++ b/evmjit/libevmjit/ExecutionEngine.cpp @@ -162,6 +162,8 @@ ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env) listener->stateChanged(ExecState::Optimization); optimize(*module); } + + prepare(*module); } if (g_dump) module->dump(); diff --git a/evmjit/libevmjit/Optimizer.cpp b/evmjit/libevmjit/Optimizer.cpp index df88b4df8..4913dcaa0 100644 --- a/evmjit/libevmjit/Optimizer.cpp +++ b/evmjit/libevmjit/Optimizer.cpp @@ -1,11 +1,16 @@ #include "Optimizer.h" #include "preprocessor/llvm_includes_start.h" +#include +#include #include #include #include #include "preprocessor/llvm_includes_end.h" +#include "Arith256.h" +#include "Type.h" + namespace dev { namespace eth @@ -24,6 +29,60 @@ bool optimize(llvm::Module& _module) return pm.run(_module); } +namespace +{ + +class LowerEVMPass : public llvm::BasicBlockPass +{ + static char ID; + + bool m_mulFuncNeeded = false; + +public: + LowerEVMPass(): + llvm::BasicBlockPass(ID) + {} + + virtual bool runOnBasicBlock(llvm::BasicBlock& _bb) override; + + virtual bool doFinalization(llvm::Module& _module) override; +}; + +char LowerEVMPass::ID = 0; + +bool LowerEVMPass::runOnBasicBlock(llvm::BasicBlock& _bb) +{ + auto modified = false; + auto module = _bb.getParent()->getParent(); + for (auto&& inst : _bb) + { + if (inst.getOpcode() == llvm::Instruction::Mul) + { + if (inst.getType() == Type::Word) + { + auto call = llvm::CallInst::Create(Arith256::getMulFunc(*module), {inst.getOperand(0), inst.getOperand(1)}, "", &inst); + inst.replaceAllUsesWith(call); + modified = true; + } + } + } + return modified; +} + +bool LowerEVMPass::doFinalization(llvm::Module&) +{ + return false; +} + +} + +bool prepare(llvm::Module& _module) +{ + auto pm = llvm::legacy::PassManager{}; + pm.add(new LowerEVMPass{}); + return pm.run(_module); +} + } } } diff --git a/evmjit/libevmjit/Optimizer.h b/evmjit/libevmjit/Optimizer.h index 4a3147a7f..4b7ab7e9a 100644 --- a/evmjit/libevmjit/Optimizer.h +++ b/evmjit/libevmjit/Optimizer.h @@ -14,6 +14,8 @@ namespace jit bool optimize(llvm::Module& _module); +bool prepare(llvm::Module& _module); + } } } From 73cc4e5b97fa382efd2eb41c3d9947d3c9b6819a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 4 May 2015 12:34:38 +0200 Subject: [PATCH 005/290] Return divrem results using vector <2 x i256> --- evmjit/libevmjit/Arith256.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/evmjit/libevmjit/Arith256.cpp b/evmjit/libevmjit/Arith256.cpp index d8e4c5138..107eb5b05 100644 --- a/evmjit/libevmjit/Arith256.cpp +++ b/evmjit/libevmjit/Arith256.cpp @@ -137,7 +137,7 @@ llvm::Function* Arith256::getDivFunc(llvm::Type* _type) // The following algorithm also handles divisor of value 0 returning 0 for both quotient and reminder llvm::Type* argTypes[] = {_type, _type}; - auto retType = llvm::StructType::get(m_builder.getContext(), llvm::ArrayRef{argTypes}); + auto retType = llvm::VectorType::get(_type, 2); auto funcName = _type == Type::Word ? "div" : "div512"; func = llvm::Function::Create(llvm::FunctionType::get(retType, argTypes, false), llvm::Function::PrivateLinkage, funcName, getModule()); func->setDoesNotThrow(); @@ -209,8 +209,8 @@ llvm::Function* Arith256::getDivFunc(llvm::Type* _type) auto rRet = m_builder.CreatePHI(_type, 2, "r.ret"); rRet->addIncoming(r0, entryBB); rRet->addIncoming(r1, loopBB); - auto ret = m_builder.CreateInsertValue(llvm::UndefValue::get(retType), qRet, 0, "ret0"); - ret = m_builder.CreateInsertValue(ret, rRet, 1, "ret"); + auto ret = m_builder.CreateInsertElement(llvm::UndefValue::get(retType), qRet, uint64_t(0), "ret0"); + ret = m_builder.CreateInsertElement(ret, rRet, 1, "ret"); m_builder.CreateRet(ret); } return func; @@ -312,7 +312,7 @@ llvm::Function* Arith256::getAddModFunc() auto m512 = m_builder.CreateZExt(mod, i512Ty, "m512"); auto s = m_builder.CreateAdd(x512, y512, "s"); auto d = createCall(getDivFunc(i512Ty), {s, m512}); - auto r = m_builder.CreateExtractValue(d, 1, "r"); + auto r = m_builder.CreateExtractElement(d, 1, "r"); m_builder.CreateRet(m_builder.CreateTrunc(r, Type::Word)); } return m_addmod; @@ -342,9 +342,8 @@ llvm::Function* Arith256::getMulModFunc() auto p = createCall(getMul512Func(), {x, y}); auto m = m_builder.CreateZExt(mod, i512Ty, "m"); auto d = createCall(getDivFunc(i512Ty), {p, m}); - auto r = m_builder.CreateExtractValue(d, 1, "r"); - r = m_builder.CreateTrunc(r, Type::Word); - m_builder.CreateRet(r); + auto r = m_builder.CreateExtractElement(d, 1, "r"); + m_builder.CreateRet(m_builder.CreateTrunc(r, Type::Word)); } return m_mulmod; } @@ -364,8 +363,8 @@ std::pair Arith256::div(llvm::Value* _arg1, llvm::Va } auto r = createCall(getDivFunc(Type::Word), {_arg1, _arg2}); - auto div = m_builder.CreateExtractValue(r, 0, "div"); - auto mod = m_builder.CreateExtractValue(r, 1, "mod"); + auto div = m_builder.CreateExtractElement(r, uint64_t(0), "div"); + auto mod = m_builder.CreateExtractElement(r, 1, "mod"); return std::make_pair(div, mod); } From 77f9d13977523aafa363b15afef00ca84b185441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 7 May 2015 11:28:01 +0200 Subject: [PATCH 006/290] Unpack runtime data at front. Not used one are removed by DCE pass. --- evmjit/libevmjit/Optimizer.cpp | 1 + evmjit/libevmjit/RuntimeManager.cpp | 46 +++++++++++++++-------------- evmjit/libevmjit/RuntimeManager.h | 2 ++ 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/evmjit/libevmjit/Optimizer.cpp b/evmjit/libevmjit/Optimizer.cpp index 4913dcaa0..23550a7ea 100644 --- a/evmjit/libevmjit/Optimizer.cpp +++ b/evmjit/libevmjit/Optimizer.cpp @@ -79,6 +79,7 @@ bool LowerEVMPass::doFinalization(llvm::Module&) bool prepare(llvm::Module& _module) { auto pm = llvm::legacy::PassManager{}; + pm.add(llvm::createDeadCodeEliminationPass()); pm.add(new LowerEVMPass{}); return pm.run(_module); } diff --git a/evmjit/libevmjit/RuntimeManager.cpp b/evmjit/libevmjit/RuntimeManager.cpp index 8d000f4c8..154aa0fd0 100644 --- a/evmjit/libevmjit/RuntimeManager.cpp +++ b/evmjit/libevmjit/RuntimeManager.cpp @@ -64,22 +64,22 @@ llvm::Twine getName(RuntimeData::Index _index) { switch (_index) { - default: return "data"; - case RuntimeData::Address: return "address"; - case RuntimeData::Caller: return "caller"; - case RuntimeData::Origin: return "origin"; - case RuntimeData::CallValue: return "callvalue"; - case RuntimeData::GasPrice: return "gasprice"; - case RuntimeData::CoinBase: return "coinbase"; - case RuntimeData::Difficulty: return "difficulty"; - case RuntimeData::GasLimit: return "gaslimit"; - case RuntimeData::CallData: return "callData"; - case RuntimeData::Code: return "code"; - case RuntimeData::CodeSize: return "code"; - case RuntimeData::CallDataSize: return "callDataSize"; - case RuntimeData::Gas: return "gas"; - case RuntimeData::Number: return "number"; - case RuntimeData::Timestamp: return "timestamp"; + default: return ""; + case RuntimeData::Gas: return "msg.gas"; + case RuntimeData::GasPrice: return "tx.gasprice"; + case RuntimeData::CallData: return "msg.data.ptr"; + case RuntimeData::CallDataSize: return "msg.data.size"; + case RuntimeData::Address: return "this.address"; + case RuntimeData::Caller: return "msg.caller"; + case RuntimeData::Origin: return "tx.origin"; + case RuntimeData::CallValue: return "msg.value"; + case RuntimeData::CoinBase: return "block.coinbase"; + case RuntimeData::Difficulty: return "block.difficulty"; + case RuntimeData::GasLimit: return "block.gaslimit"; + case RuntimeData::Number: return "block.number"; + case RuntimeData::Timestamp: return "block.timestamp"; + case RuntimeData::Code: return "code.ptr"; + case RuntimeData::CodeSize: return "code.size"; } } } @@ -93,9 +93,9 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB // Unpack data auto rtPtr = getRuntimePtr(); - m_dataPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(getRuntimeType(), rtPtr, 0), "data"); + m_dataPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(getRuntimeType(), rtPtr, 0), "dataPtr"); assert(m_dataPtr->getType() == Type::RuntimeDataPtr); - m_gasPtr = m_builder.CreateStructGEP(getRuntimeDataType(), m_dataPtr, 0, "gas"); + m_gasPtr = m_builder.CreateStructGEP(getRuntimeDataType(), m_dataPtr, 0, "gasPtr"); assert(m_gasPtr->getType() == Type::Gas->getPointerTo()); m_memPtr = m_builder.CreateStructGEP(getRuntimeType(), rtPtr, 2, "mem"); assert(m_memPtr->getType() == Array::getType()->getPointerTo()); @@ -105,6 +105,10 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB m_stackSize = m_builder.CreateAlloca(Type::Size, nullptr, "stackSize"); m_builder.CreateStore(m_builder.getInt64(0), m_stackSize); + auto data = m_builder.CreateLoad(m_dataPtr, "data"); + for (unsigned i = 0; i < m_dataElts.size(); ++i) + m_dataElts[i] = m_builder.CreateExtractValue(data, i, getName(RuntimeData::Index(i))); + llvm::Type* checkStackLimitArgs[] = {Type::Size->getPointerTo(), Type::Size, Type::Size, Type::BytePtr}; m_checkStackLimit = llvm::Function::Create(llvm::FunctionType::get(Type::Void, checkStackLimitArgs, false), llvm::Function::PrivateLinkage, "stack.checkSize", getModule()); m_checkStackLimit->setDoesNotThrow(); @@ -180,7 +184,7 @@ llvm::Value* RuntimeManager::getPtr(RuntimeData::Index _index) llvm::Value* RuntimeManager::get(RuntimeData::Index _index) { - return getBuilder().CreateLoad(getPtr(_index), getName(_index)); + return m_dataElts[_index]; } void RuntimeManager::set(RuntimeData::Index _index, llvm::Value* _value) @@ -264,9 +268,7 @@ llvm::Value* RuntimeManager::getCallDataSize() llvm::Value* RuntimeManager::getGas() { - auto gas = get(RuntimeData::Gas); - assert(gas->getType() == Type::Gas); - return gas; + return getBuilder().CreateLoad(getGasPtr(), "gas"); } llvm::Value* RuntimeManager::getGasPtr() diff --git a/evmjit/libevmjit/RuntimeManager.h b/evmjit/libevmjit/RuntimeManager.h index c430a1098..4c36c4ef3 100644 --- a/evmjit/libevmjit/RuntimeManager.h +++ b/evmjit/libevmjit/RuntimeManager.h @@ -61,6 +61,8 @@ private: llvm::Value* m_memPtr = nullptr; llvm::Value* m_envPtr = nullptr; + std::array(RuntimeData::Index::CodeSize) + 1> m_dataElts; + llvm::Value* m_stackSize = nullptr; llvm::Function* m_checkStackLimit = nullptr; From 08d94e0f5221b28479810ab162b2c11d9487d641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 7 May 2015 16:20:04 +0200 Subject: [PATCH 007/290] Always exit through exit blocks (Stop, Abort, etc). Fixes ethereum/evmjit#6. --- evmjit/libevmjit/Compiler.cpp | 10 +++++----- evmjit/libevmjit/Compiler.h | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index a2f58c770..038d9ef3f 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -159,10 +159,10 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera // TODO: Create Stop basic block on demand m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); - auto abortBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Abort", m_mainFunc); + m_abortBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Abort", m_mainFunc); auto firstBB = m_basicBlocks.empty() ? m_stopBB : m_basicBlocks.begin()->second.llvm(); - m_builder.CreateCondBr(normalFlow, firstBB, abortBB, Type::expectTrue); + m_builder.CreateCondBr(normalFlow, firstBB, m_abortBB, Type::expectTrue); for (auto basicBlockPairIt = m_basicBlocks.begin(); basicBlockPairIt != m_basicBlocks.end(); ++basicBlockPairIt) { @@ -178,7 +178,7 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera m_builder.SetInsertPoint(m_stopBB); runtimeManager.exit(ReturnCode::Stop); - m_builder.SetInsertPoint(abortBB); + m_builder.SetInsertPoint(m_abortBB); runtimeManager.exit(ReturnCode::OutOfGas); removeDeadBlocks(); @@ -789,7 +789,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti case Instruction::STOP: { - m_builder.CreateRet(Constant::get(ReturnCode::Stop)); + m_builder.CreateBr(m_stopBB); break; } @@ -816,7 +816,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti } default: // Invalid instruction - abort - m_builder.CreateRet(Constant::get(ReturnCode::BadInstruction)); + m_builder.CreateBr(m_abortBB); it = _basicBlock.end() - 1; // finish block compilation } } diff --git a/evmjit/libevmjit/Compiler.h b/evmjit/libevmjit/Compiler.h index 4469389bb..9b9fe7160 100644 --- a/evmjit/libevmjit/Compiler.h +++ b/evmjit/libevmjit/Compiler.h @@ -65,6 +65,9 @@ private: /// Stop basic block - terminates execution with STOP code (0) llvm::BasicBlock* m_stopBB = nullptr; + /// Abort basic block - terminates execution with OOG-like state + llvm::BasicBlock* m_abortBB = nullptr; + /// Block with a jump table. std::unique_ptr m_jumpTableBlock; From e659d3e761b4f4e5c7607aec5e5fa32cb018b541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 7 May 2015 16:34:44 +0200 Subject: [PATCH 008/290] Copy gas counter to local function stack (alloca) --- evmjit/libevmjit/RuntimeManager.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/evmjit/libevmjit/RuntimeManager.cpp b/evmjit/libevmjit/RuntimeManager.cpp index 154aa0fd0..d48b64bb1 100644 --- a/evmjit/libevmjit/RuntimeManager.cpp +++ b/evmjit/libevmjit/RuntimeManager.cpp @@ -95,8 +95,6 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB auto rtPtr = getRuntimePtr(); m_dataPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(getRuntimeType(), rtPtr, 0), "dataPtr"); assert(m_dataPtr->getType() == Type::RuntimeDataPtr); - m_gasPtr = m_builder.CreateStructGEP(getRuntimeDataType(), m_dataPtr, 0, "gasPtr"); - assert(m_gasPtr->getType() == Type::Gas->getPointerTo()); m_memPtr = m_builder.CreateStructGEP(getRuntimeType(), rtPtr, 2, "mem"); assert(m_memPtr->getType() == Array::getType()->getPointerTo()); m_envPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(getRuntimeType(), rtPtr, 1), "env"); @@ -109,6 +107,9 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB for (unsigned i = 0; i < m_dataElts.size(); ++i) m_dataElts[i] = m_builder.CreateExtractValue(data, i, getName(RuntimeData::Index(i))); + m_gasPtr = m_builder.CreateAlloca(Type::Gas, nullptr, "gas.ptr"); + m_builder.CreateStore(m_dataElts[RuntimeData::Index::Gas], m_gasPtr); + llvm::Type* checkStackLimitArgs[] = {Type::Size->getPointerTo(), Type::Size, Type::Size, Type::BytePtr}; m_checkStackLimit = llvm::Function::Create(llvm::FunctionType::get(Type::Void, checkStackLimitArgs, false), llvm::Function::PrivateLinkage, "stack.checkSize", getModule()); m_checkStackLimit->setDoesNotThrow(); @@ -215,6 +216,8 @@ void RuntimeManager::exit(ReturnCode _returnCode) if (m_stack) m_stack->free(); + auto extGasPtr = m_builder.CreateStructGEP(getRuntimeDataType(), getDataPtr(), RuntimeData::Index::Gas, "msg.gas.ptr"); + m_builder.CreateStore(getGas(), extGasPtr); m_builder.CreateRet(Constant::get(_returnCode)); } @@ -286,7 +289,7 @@ llvm::Value* RuntimeManager::getMem() void RuntimeManager::setGas(llvm::Value* _gas) { assert(_gas->getType() == Type::Gas); - set(RuntimeData::Gas, _gas); + getBuilder().CreateStore(_gas, getGasPtr()); } } From ad40e852bfbd3c64c24f00515b93abccd7a91480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 8 May 2015 11:00:17 +0200 Subject: [PATCH 009/290] testeth: fix --singletest option --- test/TestHelper.cpp | 89 +++++++++++++++----------------- test/TestHelper.h | 3 +- test/libethereum/blockchain.cpp | 2 +- test/libethereum/state.cpp | 2 +- test/libethereum/transaction.cpp | 2 +- test/libevm/vm.cpp | 2 +- 6 files changed, 47 insertions(+), 53 deletions(-) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 46718c5dd..3171f91cb 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -549,58 +549,50 @@ void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _e } } -void userDefinedTest(string testTypeFlag, std::function doTests) +void userDefinedTest(std::function doTests) { - Options::get(); // parse command line options, e.g. to enable JIT + if (!Options::get().singleTest) + { + cnote << "Missing user test specification\nUsage: testeth --singletest \n"; + return; + } - for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) + auto& filename = Options::get().singleTestFile; + auto& testname = Options::get().singleTestName; + int currentVerbosity = g_logVerbosity; + g_logVerbosity = 12; + try { - string arg = boost::unit_test::framework::master_test_suite().argv[i]; - if (arg == testTypeFlag) - { - if (boost::unit_test::framework::master_test_suite().argc <= i + 2) - { - cnote << "Missing filename\nUsage: testeth " << testTypeFlag << " \n"; - return; - } - string filename = boost::unit_test::framework::master_test_suite().argv[i + 1]; - string testname = boost::unit_test::framework::master_test_suite().argv[i + 2]; - int currentVerbosity = g_logVerbosity; - g_logVerbosity = 12; - try - { - cnote << "Testing user defined test: " << filename; - json_spirit::mValue v; - string s = asString(contents(filename)); - BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + filename + " is empty. "); - json_spirit::read_string(s, v); - json_spirit::mObject oSingleTest; - - json_spirit::mObject::const_iterator pos = v.get_obj().find(testname); - if (pos == v.get_obj().end()) - { - cnote << "Could not find test: " << testname << " in " << filename << "\n"; - return; - } - else - oSingleTest[pos->first] = pos->second; + cnote << "Testing user defined test: " << filename; + json_spirit::mValue v; + string s = asString(contents(filename)); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + filename + " is empty. "); + json_spirit::read_string(s, v); + json_spirit::mObject oSingleTest; - json_spirit::mValue v_singleTest(oSingleTest); - doTests(v_singleTest, false); - } - catch (Exception const& _e) - { - BOOST_ERROR("Failed Test with Exception: " << diagnostic_information(_e)); - g_logVerbosity = currentVerbosity; - } - catch (std::exception const& _e) - { - BOOST_ERROR("Failed Test with Exception: " << _e.what()); - g_logVerbosity = currentVerbosity; - } - g_logVerbosity = currentVerbosity; + json_spirit::mObject::const_iterator pos = v.get_obj().find(testname); + if (pos == v.get_obj().end()) + { + cnote << "Could not find test: " << testname << " in " << filename << "\n"; + return; } + else + oSingleTest[pos->first] = pos->second; + + json_spirit::mValue v_singleTest(oSingleTest); + doTests(v_singleTest, false); + } + catch (Exception const& _e) + { + BOOST_ERROR("Failed Test with Exception: " << diagnostic_information(_e)); + g_logVerbosity = currentVerbosity; + } + catch (std::exception const& _e) + { + BOOST_ERROR("Failed Test with Exception: " << _e.what()); + g_logVerbosity = currentVerbosity; } + g_logVerbosity = currentVerbosity; } void executeTests(const string& _name, const string& _testPathAppendix, const boost::filesystem::path _pathToFiller, std::function doTests) @@ -739,10 +731,11 @@ Options::Options() inputLimits = true; bigData = true; } - else if (arg == "--singletest" && i + 1 < argc) + else if (arg == "--singletest" && i + 2 < argc) { singleTest = true; - singleTestName = argv[i + 1]; + singleTestFile = argv[i + 1]; + singleTestName = argv[i + 2]; } } } diff --git a/test/TestHelper.h b/test/TestHelper.h index 00b520d06..d1da7e24b 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -157,7 +157,7 @@ void checkLog(eth::LogEntries _resultLogs, eth::LogEntries _expectedLogs); void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _expectedCallCreates); void executeTests(const std::string& _name, const std::string& _testPathAppendix, const boost::filesystem::path _pathToFiller, std::function doTests); -void userDefinedTest(std::string testTypeFlag, std::function doTests); +void userDefinedTest(std::function doTests); RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject& _tObj); eth::LastHashes lastHashes(u256 _currentBlockNumber); json_spirit::mObject fillJsonWithState(eth::State _state); @@ -188,6 +188,7 @@ public: /// Test selection /// @{ bool singleTest = false; + std::string singleTestFile; std::string singleTestName; bool performance = false; bool quadratic = false; diff --git a/test/libethereum/blockchain.cpp b/test/libethereum/blockchain.cpp index 954e65c8a..9eddb4657 100644 --- a/test/libethereum/blockchain.cpp +++ b/test/libethereum/blockchain.cpp @@ -711,7 +711,7 @@ BOOST_AUTO_TEST_CASE(bcWalletTest) BOOST_AUTO_TEST_CASE(userDefinedFile) { - dev::test::userDefinedTest("--singletest", dev::test::doBlockchainTests); + dev::test::userDefinedTest(dev::test::doBlockchainTests); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libethereum/state.cpp b/test/libethereum/state.cpp index 93f7498b8..b7b45f93a 100644 --- a/test/libethereum/state.cpp +++ b/test/libethereum/state.cpp @@ -265,7 +265,7 @@ BOOST_AUTO_TEST_CASE(stRandom) BOOST_AUTO_TEST_CASE(userDefinedFileState) { - dev::test::userDefinedTest("--singletest", dev::test::doStateTests); + dev::test::userDefinedTest(dev::test::doStateTests); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libethereum/transaction.cpp b/test/libethereum/transaction.cpp index 058d03322..017e51ded 100644 --- a/test/libethereum/transaction.cpp +++ b/test/libethereum/transaction.cpp @@ -195,7 +195,7 @@ BOOST_AUTO_TEST_CASE(ttCreateTest) BOOST_AUTO_TEST_CASE(userDefinedFile) { - dev::test::userDefinedTest("--singletest", dev::test::doTransactionTests); + dev::test::userDefinedTest(dev::test::doTransactionTests); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libevm/vm.cpp b/test/libevm/vm.cpp index 8b5a7c5d3..2d67d7670 100644 --- a/test/libevm/vm.cpp +++ b/test/libevm/vm.cpp @@ -548,7 +548,7 @@ BOOST_AUTO_TEST_CASE(vmRandom) BOOST_AUTO_TEST_CASE(userDefinedFile) { - dev::test::userDefinedTest("--singletest", dev::test::doVMTests); + dev::test::userDefinedTest(dev::test::doVMTests); } BOOST_AUTO_TEST_SUITE_END() From 483403cc91bedc25c4ba9c5465941d35d2748bd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 13 May 2015 12:39:55 +0200 Subject: [PATCH 010/290] Lower DIV to a function call in the LLVM pass after optimization. --- evmjit/libevmjit/Arith256.cpp | 114 +++++++++++++++++++++++++++++++++ evmjit/libevmjit/Arith256.h | 2 + evmjit/libevmjit/Compiler.cpp | 4 +- evmjit/libevmjit/Optimizer.cpp | 10 +++ 4 files changed, 128 insertions(+), 2 deletions(-) diff --git a/evmjit/libevmjit/Arith256.cpp b/evmjit/libevmjit/Arith256.cpp index 107eb5b05..caef06bec 100644 --- a/evmjit/libevmjit/Arith256.cpp +++ b/evmjit/libevmjit/Arith256.cpp @@ -86,6 +86,120 @@ llvm::Function* Arith256::getMulFunc(llvm::Module& _module) return func; } +llvm::Function* Arith256::getUDivRem256Func(llvm::Module& _module) +{ + static const auto funcName = "evm.udivrem.i256"; + if (auto func = _module.getFunction(funcName)) + return func; + + auto type = Type::Word; + + // Based of "Improved shift divisor algorithm" from "Software Integer Division" by Microsoft Research + // The following algorithm also handles divisor of value 0 returning 0 for both quotient and reminder + + llvm::Type* argTypes[] = {type, type}; + auto retType = llvm::VectorType::get(type, 2); + auto func = llvm::Function::Create(llvm::FunctionType::get(retType, argTypes, false), llvm::Function::PrivateLinkage, funcName, &_module); + func->setDoesNotThrow(); + func->setDoesNotAccessMemory(); + + auto zero = llvm::ConstantInt::get(type, 0); + auto one = llvm::ConstantInt::get(type, 1); + + auto x = &func->getArgumentList().front(); + x->setName("x"); + auto yArg = x->getNextNode(); + yArg->setName("y"); + + auto entryBB = llvm::BasicBlock::Create(_module.getContext(), "Entry", func); + auto mainBB = llvm::BasicBlock::Create(_module.getContext(), "Main", func); + auto loopBB = llvm::BasicBlock::Create(_module.getContext(), "Loop", func); + auto continueBB = llvm::BasicBlock::Create(_module.getContext(), "Continue", func); + auto returnBB = llvm::BasicBlock::Create(_module.getContext(), "Return", func); + + auto builder = llvm::IRBuilder<>{entryBB}; + auto yNonZero = builder.CreateICmpNE(yArg, zero); + auto yLEx = builder.CreateICmpULE(yArg, x); + auto r0 = builder.CreateSelect(yNonZero, x, zero, "r0"); + builder.CreateCondBr(builder.CreateAnd(yLEx, yNonZero), mainBB, returnBB); + + builder.SetInsertPoint(mainBB); + auto ctlzIntr = llvm::Intrinsic::getDeclaration(&_module, llvm::Intrinsic::ctlz, type); + // both y and r are non-zero + auto yLz = builder.CreateCall2(ctlzIntr, yArg, builder.getInt1(true), "y.lz"); + auto rLz = builder.CreateCall2(ctlzIntr, r0, builder.getInt1(true), "r.lz"); + auto i0 = builder.CreateNUWSub(yLz, rLz, "i0"); + auto y0 = builder.CreateShl(yArg, i0); + builder.CreateBr(loopBB); + + builder.SetInsertPoint(loopBB); + auto yPhi = builder.CreatePHI(type, 2, "y.phi"); + auto rPhi = builder.CreatePHI(type, 2, "r.phi"); + auto iPhi = builder.CreatePHI(type, 2, "i.phi"); + auto qPhi = builder.CreatePHI(type, 2, "q.phi"); + auto rUpdate = builder.CreateNUWSub(rPhi, yPhi); + auto qUpdate = builder.CreateOr(qPhi, one); // q += 1, q lowest bit is 0 + auto rGEy = builder.CreateICmpUGE(rPhi, yPhi); + auto r1 = builder.CreateSelect(rGEy, rUpdate, rPhi, "r1"); + auto q1 = builder.CreateSelect(rGEy, qUpdate, qPhi, "q"); + auto iZero = builder.CreateICmpEQ(iPhi, zero); + builder.CreateCondBr(iZero, returnBB, continueBB); + + builder.SetInsertPoint(continueBB); + auto i2 = builder.CreateNUWSub(iPhi, one); + auto q2 = builder.CreateShl(q1, one); + auto y2 = builder.CreateLShr(yPhi, one); + builder.CreateBr(loopBB); + + yPhi->addIncoming(y0, mainBB); + yPhi->addIncoming(y2, continueBB); + rPhi->addIncoming(r0, mainBB); + rPhi->addIncoming(r1, continueBB); + iPhi->addIncoming(i0, mainBB); + iPhi->addIncoming(i2, continueBB); + qPhi->addIncoming(zero, mainBB); + qPhi->addIncoming(q2, continueBB); + + builder.SetInsertPoint(returnBB); + auto qRet = builder.CreatePHI(type, 2, "q.ret"); + qRet->addIncoming(zero, entryBB); + qRet->addIncoming(q1, loopBB); + auto rRet = builder.CreatePHI(type, 2, "r.ret"); + rRet->addIncoming(r0, entryBB); + rRet->addIncoming(r1, loopBB); + auto ret = builder.CreateInsertElement(llvm::UndefValue::get(retType), qRet, uint64_t(0), "ret0"); + ret = builder.CreateInsertElement(ret, rRet, 1, "ret"); + builder.CreateRet(ret); + + return func; +} + +llvm::Function* Arith256::getUDiv256Func(llvm::Module& _module) +{ + static const auto funcName = "evm.udiv.i256"; + if (auto func = _module.getFunction(funcName)) + return func; + + auto udivremFunc = getUDivRem256Func(_module); + + auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Word, {Type::Word, Type::Word}, false), llvm::Function::PrivateLinkage, funcName, &_module); + func->setDoesNotThrow(); + func->setDoesNotAccessMemory(); + + auto x = &func->getArgumentList().front(); + x->setName("x"); + auto y = x->getNextNode(); + y->setName("y"); + + auto bb = llvm::BasicBlock::Create(_module.getContext(), {}, func); + auto builder = llvm::IRBuilder<>{bb}; + auto udivrem = builder.CreateCall(udivremFunc, {x, y}); + auto udiv = builder.CreateExtractElement(udivrem, uint64_t(0)); + builder.CreateRet(udiv); + + return func; +} + llvm::Function* Arith256::getMul512Func() { auto& func = m_mul512; diff --git a/evmjit/libevmjit/Arith256.h b/evmjit/libevmjit/Arith256.h index a5762429d..3ee016073 100644 --- a/evmjit/libevmjit/Arith256.h +++ b/evmjit/libevmjit/Arith256.h @@ -23,6 +23,8 @@ public: void debug(llvm::Value* _value, char _c); static llvm::Function* getMulFunc(llvm::Module& _module); + static llvm::Function* getUDiv256Func(llvm::Module& _module); + static llvm::Function* getUDivRem256Func(llvm::Module& _module); private: llvm::Function* getMul512Func(); diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 038d9ef3f..2e4976c78 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -279,8 +279,8 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res = _arith.div(lhs, rhs); - stack.push(res.first); + auto res = m_builder.CreateUDiv(lhs, rhs); + stack.push(res); break; } diff --git a/evmjit/libevmjit/Optimizer.cpp b/evmjit/libevmjit/Optimizer.cpp index 23550a7ea..7bd7f252c 100644 --- a/evmjit/libevmjit/Optimizer.cpp +++ b/evmjit/libevmjit/Optimizer.cpp @@ -65,6 +65,15 @@ bool LowerEVMPass::runOnBasicBlock(llvm::BasicBlock& _bb) modified = true; } } + else if (inst.getOpcode() == llvm::Instruction::UDiv) + { + if (inst.getType() == Type::Word) + { + auto call = llvm::CallInst::Create(Arith256::getUDiv256Func(*module), {inst.getOperand(0), inst.getOperand(1)}, "", &inst); + inst.replaceAllUsesWith(call); + modified = true; + } + } } return modified; } @@ -81,6 +90,7 @@ bool prepare(llvm::Module& _module) auto pm = llvm::legacy::PassManager{}; pm.add(llvm::createDeadCodeEliminationPass()); pm.add(new LowerEVMPass{}); + pm.add(llvm::createDeadInstEliminationPass()); // Remove leftovers return pm.run(_module); } From 03ea86c8555a143b94e1cfd178fc49891dee14d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 13 May 2015 13:10:22 +0200 Subject: [PATCH 011/290] Eliminate dead instructions replaced in AP arithmetic lowering. --- evmjit/libevmjit/Optimizer.cpp | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/evmjit/libevmjit/Optimizer.cpp b/evmjit/libevmjit/Optimizer.cpp index 7bd7f252c..982f1cefe 100644 --- a/evmjit/libevmjit/Optimizer.cpp +++ b/evmjit/libevmjit/Optimizer.cpp @@ -54,25 +54,30 @@ bool LowerEVMPass::runOnBasicBlock(llvm::BasicBlock& _bb) { auto modified = false; auto module = _bb.getParent()->getParent(); - for (auto&& inst : _bb) + for (auto it = _bb.begin(); it != _bb.end(); ) { - if (inst.getOpcode() == llvm::Instruction::Mul) + auto& inst = *it++; + llvm::Function* func = nullptr; + if (inst.getType() == Type::Word) { - if (inst.getType() == Type::Word) + switch (inst.getOpcode()) { - auto call = llvm::CallInst::Create(Arith256::getMulFunc(*module), {inst.getOperand(0), inst.getOperand(1)}, "", &inst); - inst.replaceAllUsesWith(call); - modified = true; + case llvm::Instruction::Mul: + func = Arith256::getMulFunc(*module); + break; + + case llvm::Instruction::UDiv: + func = Arith256::getUDiv256Func(*module); + break; } } - else if (inst.getOpcode() == llvm::Instruction::UDiv) + + if (func) { - if (inst.getType() == Type::Word) - { - auto call = llvm::CallInst::Create(Arith256::getUDiv256Func(*module), {inst.getOperand(0), inst.getOperand(1)}, "", &inst); - inst.replaceAllUsesWith(call); - modified = true; - } + auto call = llvm::CallInst::Create(func, {inst.getOperand(0), inst.getOperand(1)}, "", &inst); + inst.replaceAllUsesWith(call); + inst.eraseFromParent(); + modified = true; } } return modified; @@ -90,7 +95,6 @@ bool prepare(llvm::Module& _module) auto pm = llvm::legacy::PassManager{}; pm.add(llvm::createDeadCodeEliminationPass()); pm.add(new LowerEVMPass{}); - pm.add(llvm::createDeadInstEliminationPass()); // Remove leftovers return pm.run(_module); } From 7de220228b99208f4f98ead4fa9c8c31e584bcea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 13 May 2015 14:07:49 +0200 Subject: [PATCH 012/290] Lower MOD, SDIV & SMOD to a function call in the LLVM pass after optimization. --- evmjit/libevmjit/Arith256.cpp | 180 +++++++++++++++++++++++---------- evmjit/libevmjit/Arith256.h | 6 +- evmjit/libevmjit/Compiler.cpp | 12 +-- evmjit/libevmjit/Optimizer.cpp | 12 +++ 4 files changed, 147 insertions(+), 63 deletions(-) diff --git a/evmjit/libevmjit/Arith256.cpp b/evmjit/libevmjit/Arith256.cpp index caef06bec..48e3307df 100644 --- a/evmjit/libevmjit/Arith256.cpp +++ b/evmjit/libevmjit/Arith256.cpp @@ -200,6 +200,131 @@ llvm::Function* Arith256::getUDiv256Func(llvm::Module& _module) return func; } +llvm::Function* Arith256::getURem256Func(llvm::Module& _module) +{ + static const auto funcName = "evm.urem.i256"; + if (auto func = _module.getFunction(funcName)) + return func; + + auto udivremFunc = getUDivRem256Func(_module); + + auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Word, {Type::Word, Type::Word}, false), llvm::Function::PrivateLinkage, funcName, &_module); + func->setDoesNotThrow(); + func->setDoesNotAccessMemory(); + + auto x = &func->getArgumentList().front(); + x->setName("x"); + auto y = x->getNextNode(); + y->setName("y"); + + auto bb = llvm::BasicBlock::Create(_module.getContext(), {}, func); + auto builder = llvm::IRBuilder<>{bb}; + auto udivrem = builder.CreateCall(udivremFunc, {x, y}); + auto r = builder.CreateExtractElement(udivrem, uint64_t(1)); + builder.CreateRet(r); + + return func; +} + +llvm::Function* Arith256::getSDivRem256Func(llvm::Module& _module) +{ + static const auto funcName = "evm.sdivrem.i256"; + if (auto func = _module.getFunction(funcName)) + return func; + + auto udivremFunc = getUDivRem256Func(_module); + + auto retType = llvm::VectorType::get(Type::Word, 2); + auto func = llvm::Function::Create(llvm::FunctionType::get(retType, {Type::Word, Type::Word}, false), llvm::Function::PrivateLinkage, funcName, &_module); + func->setDoesNotThrow(); + func->setDoesNotAccessMemory(); + + auto x = &func->getArgumentList().front(); + x->setName("x"); + auto y = x->getNextNode(); + y->setName("y"); + + auto bb = llvm::BasicBlock::Create(_module.getContext(), "", func); + auto builder = llvm::IRBuilder<>{bb}; + auto xIsNeg = builder.CreateICmpSLT(x, Constant::get(0)); + auto xNeg = builder.CreateSub(Constant::get(0), x); + auto xAbs = builder.CreateSelect(xIsNeg, xNeg, x); + + auto yIsNeg = builder.CreateICmpSLT(y, Constant::get(0)); + auto yNeg = builder.CreateSub(Constant::get(0), y); + auto yAbs = builder.CreateSelect(yIsNeg, yNeg, y); + + auto res = builder.CreateCall(udivremFunc, {xAbs, yAbs}); + auto qAbs = builder.CreateExtractElement(res, uint64_t(0)); + auto rAbs = builder.CreateExtractElement(res, 1); + + // the reminder has the same sign as dividend + auto rNeg = builder.CreateSub(Constant::get(0), rAbs); + auto r = builder.CreateSelect(xIsNeg, rNeg, rAbs); + + auto qNeg = builder.CreateSub(Constant::get(0), qAbs); + auto xyOpposite = builder.CreateXor(xIsNeg, yIsNeg); + auto q = builder.CreateSelect(xyOpposite, qNeg, qAbs); + + auto ret = builder.CreateInsertElement(llvm::UndefValue::get(retType), q, uint64_t(0)); + ret = builder.CreateInsertElement(ret, r, 1); + builder.CreateRet(ret); + + return func; +} + +llvm::Function* Arith256::getSDiv256Func(llvm::Module& _module) +{ + static const auto funcName = "evm.sdiv.i256"; + if (auto func = _module.getFunction(funcName)) + return func; + + auto sdivremFunc = getSDivRem256Func(_module); + + auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Word, {Type::Word, Type::Word}, false), llvm::Function::PrivateLinkage, funcName, &_module); + func->setDoesNotThrow(); + func->setDoesNotAccessMemory(); + + auto x = &func->getArgumentList().front(); + x->setName("x"); + auto y = x->getNextNode(); + y->setName("y"); + + auto bb = llvm::BasicBlock::Create(_module.getContext(), {}, func); + auto builder = llvm::IRBuilder<>{bb}; + auto sdivrem = builder.CreateCall(sdivremFunc, {x, y}); + auto q = builder.CreateExtractElement(sdivrem, uint64_t(0)); + builder.CreateRet(q); + + return func; +} + +llvm::Function* Arith256::getSRem256Func(llvm::Module& _module) +{ + static const auto funcName = "evm.srem.i256"; + if (auto func = _module.getFunction(funcName)) + return func; + + auto sdivremFunc = getSDivRem256Func(_module); + + auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Word, {Type::Word, Type::Word}, false), llvm::Function::PrivateLinkage, funcName, &_module); + func->setDoesNotThrow(); + func->setDoesNotAccessMemory(); + + auto x = &func->getArgumentList().front(); + x->setName("x"); + auto y = x->getNextNode(); + y->setName("y"); + + auto bb = llvm::BasicBlock::Create(_module.getContext(), {}, func); + auto builder = llvm::IRBuilder<>{bb}; + auto sdivrem = builder.CreateCall(sdivremFunc, {x, y}); + auto r = builder.CreateExtractElement(sdivrem, uint64_t(1)); + builder.CreateRet(r); + + return func; +} + llvm::Function* Arith256::getMul512Func() { auto& func = m_mul512; @@ -462,61 +587,6 @@ llvm::Function* Arith256::getMulModFunc() return m_mulmod; } -std::pair Arith256::div(llvm::Value* _arg1, llvm::Value* _arg2) -{ - if (auto c1 = llvm::dyn_cast(_arg1)) - { - if (auto c2 = llvm::dyn_cast(_arg2)) - { - if (!c2->getValue()) - return std::make_pair(Constant::get(0), Constant::get(0)); - auto div = Constant::get(c1->getValue().udiv(c2->getValue())); - auto mod = Constant::get(c1->getValue().urem(c2->getValue())); - return std::make_pair(div, mod); - } - } - - auto r = createCall(getDivFunc(Type::Word), {_arg1, _arg2}); - auto div = m_builder.CreateExtractElement(r, uint64_t(0), "div"); - auto mod = m_builder.CreateExtractElement(r, 1, "mod"); - return std::make_pair(div, mod); -} - -std::pair Arith256::sdiv(llvm::Value* _x, llvm::Value* _y) -{ - if (auto c1 = llvm::dyn_cast(_x)) - { - if (auto c2 = llvm::dyn_cast(_y)) - { - if (!c2->getValue()) - return std::make_pair(Constant::get(0), Constant::get(0)); - auto div = Constant::get(c1->getValue().sdiv(c2->getValue())); - auto mod = Constant::get(c1->getValue().srem(c2->getValue())); - return std::make_pair(div, mod); - } - } - - auto xIsNeg = m_builder.CreateICmpSLT(_x, Constant::get(0)); - auto xNeg = m_builder.CreateSub(Constant::get(0), _x); - auto xAbs = m_builder.CreateSelect(xIsNeg, xNeg, _x); - - auto yIsNeg = m_builder.CreateICmpSLT(_y, Constant::get(0)); - auto yNeg = m_builder.CreateSub(Constant::get(0), _y); - auto yAbs = m_builder.CreateSelect(yIsNeg, yNeg, _y); - - auto res = div(xAbs, yAbs); - - // the reminder has the same sign as dividend - auto rNeg = m_builder.CreateSub(Constant::get(0), res.second); - res.second = m_builder.CreateSelect(xIsNeg, rNeg, res.second); - - auto qNeg = m_builder.CreateSub(Constant::get(0), res.first); - auto xyOpposite = m_builder.CreateXor(xIsNeg, yIsNeg); - res.first = m_builder.CreateSelect(xyOpposite, qNeg, res.first); - - return res; -} - llvm::Value* Arith256::exp(llvm::Value* _arg1, llvm::Value* _arg2) { // while (e != 0) { diff --git a/evmjit/libevmjit/Arith256.h b/evmjit/libevmjit/Arith256.h index 3ee016073..aeea830db 100644 --- a/evmjit/libevmjit/Arith256.h +++ b/evmjit/libevmjit/Arith256.h @@ -14,8 +14,6 @@ class Arith256 : public CompilerHelper public: Arith256(llvm::IRBuilder<>& _builder); - std::pair div(llvm::Value* _arg1, llvm::Value* _arg2); - std::pair sdiv(llvm::Value* _arg1, llvm::Value* _arg2); llvm::Value* exp(llvm::Value* _arg1, llvm::Value* _arg2); llvm::Value* mulmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3); llvm::Value* addmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3); @@ -24,7 +22,11 @@ public: static llvm::Function* getMulFunc(llvm::Module& _module); static llvm::Function* getUDiv256Func(llvm::Module& _module); + static llvm::Function* getURem256Func(llvm::Module& _module); static llvm::Function* getUDivRem256Func(llvm::Module& _module); + static llvm::Function* getSDiv256Func(llvm::Module& _module); + static llvm::Function* getSRem256Func(llvm::Module& _module); + static llvm::Function* getSDivRem256Func(llvm::Module& _module); private: llvm::Function* getMul512Func(); diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 2e4976c78..7ae3e067b 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -288,8 +288,8 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res = _arith.sdiv(lhs, rhs); - stack.push(res.first); + auto res = m_builder.CreateSDiv(lhs, rhs); + stack.push(res); break; } @@ -297,8 +297,8 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res = _arith.div(lhs, rhs); - stack.push(res.second); + auto res = m_builder.CreateURem(lhs, rhs); + stack.push(res); break; } @@ -306,8 +306,8 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti { auto lhs = stack.pop(); auto rhs = stack.pop(); - auto res = _arith.sdiv(lhs, rhs); - stack.push(res.second); + auto res = m_builder.CreateSRem(lhs, rhs); + stack.push(res); break; } diff --git a/evmjit/libevmjit/Optimizer.cpp b/evmjit/libevmjit/Optimizer.cpp index 982f1cefe..8eaab9a99 100644 --- a/evmjit/libevmjit/Optimizer.cpp +++ b/evmjit/libevmjit/Optimizer.cpp @@ -69,6 +69,18 @@ bool LowerEVMPass::runOnBasicBlock(llvm::BasicBlock& _bb) case llvm::Instruction::UDiv: func = Arith256::getUDiv256Func(*module); break; + + case llvm::Instruction::URem: + func = Arith256::getURem256Func(*module); + break; + + case llvm::Instruction::SDiv: + func = Arith256::getSDiv256Func(*module); + break; + + case llvm::Instruction::SRem: + func = Arith256::getSRem256Func(*module); + break; } } From f041e68cfe69e932f82b3eda50de92bb523339ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 13 May 2015 17:21:13 +0200 Subject: [PATCH 013/290] Add edge DIV/MOD cases. Migrate to new udivrem function. --- evmjit/libevmjit/Arith256.cpp | 176 +++++++++++----------------------- evmjit/libevmjit/Arith256.h | 5 +- evmjit/libevmjit/Compiler.cpp | 43 +++++---- 3 files changed, 86 insertions(+), 138 deletions(-) diff --git a/evmjit/libevmjit/Arith256.cpp b/evmjit/libevmjit/Arith256.cpp index 48e3307df..64ed7e649 100644 --- a/evmjit/libevmjit/Arith256.cpp +++ b/evmjit/libevmjit/Arith256.cpp @@ -86,25 +86,20 @@ llvm::Function* Arith256::getMulFunc(llvm::Module& _module) return func; } -llvm::Function* Arith256::getUDivRem256Func(llvm::Module& _module) +namespace +{ +llvm::Function* createUDivRemFunc(llvm::Type* _type, llvm::Module& _module, char const* _funcName) { - static const auto funcName = "evm.udivrem.i256"; - if (auto func = _module.getFunction(funcName)) - return func; - - auto type = Type::Word; - // Based of "Improved shift divisor algorithm" from "Software Integer Division" by Microsoft Research // The following algorithm also handles divisor of value 0 returning 0 for both quotient and reminder - llvm::Type* argTypes[] = {type, type}; - auto retType = llvm::VectorType::get(type, 2); - auto func = llvm::Function::Create(llvm::FunctionType::get(retType, argTypes, false), llvm::Function::PrivateLinkage, funcName, &_module); + auto retType = llvm::VectorType::get(_type, 2); + auto func = llvm::Function::Create(llvm::FunctionType::get(retType, {_type, _type}, false), llvm::Function::PrivateLinkage, _funcName, &_module); func->setDoesNotThrow(); func->setDoesNotAccessMemory(); - auto zero = llvm::ConstantInt::get(type, 0); - auto one = llvm::ConstantInt::get(type, 1); + auto zero = llvm::ConstantInt::get(_type, 0); + auto one = llvm::ConstantInt::get(_type, 1); auto x = &func->getArgumentList().front(); x->setName("x"); @@ -124,7 +119,7 @@ llvm::Function* Arith256::getUDivRem256Func(llvm::Module& _module) builder.CreateCondBr(builder.CreateAnd(yLEx, yNonZero), mainBB, returnBB); builder.SetInsertPoint(mainBB); - auto ctlzIntr = llvm::Intrinsic::getDeclaration(&_module, llvm::Intrinsic::ctlz, type); + auto ctlzIntr = llvm::Intrinsic::getDeclaration(&_module, llvm::Intrinsic::ctlz, _type); // both y and r are non-zero auto yLz = builder.CreateCall2(ctlzIntr, yArg, builder.getInt1(true), "y.lz"); auto rLz = builder.CreateCall2(ctlzIntr, r0, builder.getInt1(true), "r.lz"); @@ -133,10 +128,10 @@ llvm::Function* Arith256::getUDivRem256Func(llvm::Module& _module) builder.CreateBr(loopBB); builder.SetInsertPoint(loopBB); - auto yPhi = builder.CreatePHI(type, 2, "y.phi"); - auto rPhi = builder.CreatePHI(type, 2, "r.phi"); - auto iPhi = builder.CreatePHI(type, 2, "i.phi"); - auto qPhi = builder.CreatePHI(type, 2, "q.phi"); + auto yPhi = builder.CreatePHI(_type, 2, "y.phi"); + auto rPhi = builder.CreatePHI(_type, 2, "r.phi"); + auto iPhi = builder.CreatePHI(_type, 2, "i.phi"); + auto qPhi = builder.CreatePHI(_type, 2, "q.phi"); auto rUpdate = builder.CreateNUWSub(rPhi, yPhi); auto qUpdate = builder.CreateOr(qPhi, one); // q += 1, q lowest bit is 0 auto rGEy = builder.CreateICmpUGE(rPhi, yPhi); @@ -161,10 +156,10 @@ llvm::Function* Arith256::getUDivRem256Func(llvm::Module& _module) qPhi->addIncoming(q2, continueBB); builder.SetInsertPoint(returnBB); - auto qRet = builder.CreatePHI(type, 2, "q.ret"); + auto qRet = builder.CreatePHI(_type, 2, "q.ret"); qRet->addIncoming(zero, entryBB); qRet->addIncoming(q1, loopBB); - auto rRet = builder.CreatePHI(type, 2, "r.ret"); + auto rRet = builder.CreatePHI(_type, 2, "r.ret"); rRet->addIncoming(r0, entryBB); rRet->addIncoming(r1, loopBB); auto ret = builder.CreateInsertElement(llvm::UndefValue::get(retType), qRet, uint64_t(0), "ret0"); @@ -173,6 +168,25 @@ llvm::Function* Arith256::getUDivRem256Func(llvm::Module& _module) return func; } +} + +llvm::Function* Arith256::getUDivRem256Func(llvm::Module& _module) +{ + static const auto funcName = "evm.udivrem.i256"; + if (auto func = _module.getFunction(funcName)) + return func; + + return createUDivRemFunc(Type::Word, _module, funcName); +} + +llvm::Function* Arith256::getUDivRem512Func(llvm::Module& _module) +{ + static const auto funcName = "evm.udivrem.i512"; + if (auto func = _module.getFunction(funcName)) + return func; + + return createUDivRemFunc(llvm::IntegerType::get(_module.getContext(), 512), _module, funcName); +} llvm::Function* Arith256::getUDiv256Func(llvm::Module& _module) { @@ -200,15 +214,13 @@ llvm::Function* Arith256::getUDiv256Func(llvm::Module& _module) return func; } -llvm::Function* Arith256::getURem256Func(llvm::Module& _module) +namespace { - static const auto funcName = "evm.urem.i256"; - if (auto func = _module.getFunction(funcName)) - return func; - - auto udivremFunc = getUDivRem256Func(_module); +llvm::Function* createURemFunc(llvm::Type* _type, llvm::Module& _module, char const* _funcName) +{ + auto udivremFunc = _type == Type::Word ? Arith256::getUDivRem256Func(_module) : Arith256::getUDivRem512Func(_module); - auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Word, {Type::Word, Type::Word}, false), llvm::Function::PrivateLinkage, funcName, &_module); + auto func = llvm::Function::Create(llvm::FunctionType::get(_type, {_type, _type}, false), llvm::Function::PrivateLinkage, _funcName, &_module); func->setDoesNotThrow(); func->setDoesNotAccessMemory(); @@ -225,6 +237,23 @@ llvm::Function* Arith256::getURem256Func(llvm::Module& _module) return func; } +} + +llvm::Function* Arith256::getURem256Func(llvm::Module& _module) +{ + static const auto funcName = "evm.urem.i256"; + if (auto func = _module.getFunction(funcName)) + return func; + return createURemFunc(Type::Word, _module, funcName); +} + +llvm::Function* Arith256::getURem512Func(llvm::Module& _module) +{ + static const auto funcName = "evm.urem.i512"; + if (auto func = _module.getFunction(funcName)) + return func; + return createURemFunc(llvm::IntegerType::get(_module.getContext(), 512), _module, funcName); +} llvm::Function* Arith256::getSDivRem256Func(llvm::Module& _module) { @@ -366,95 +395,6 @@ llvm::Function* Arith256::getMul512Func() return func; } -llvm::Function* Arith256::getDivFunc(llvm::Type* _type) -{ - auto& func = _type == Type::Word ? m_div : m_div512; - - if (!func) - { - // Based of "Improved shift divisor algorithm" from "Software Integer Division" by Microsoft Research - // The following algorithm also handles divisor of value 0 returning 0 for both quotient and reminder - - llvm::Type* argTypes[] = {_type, _type}; - auto retType = llvm::VectorType::get(_type, 2); - auto funcName = _type == Type::Word ? "div" : "div512"; - func = llvm::Function::Create(llvm::FunctionType::get(retType, argTypes, false), llvm::Function::PrivateLinkage, funcName, getModule()); - func->setDoesNotThrow(); - func->setDoesNotAccessMemory(); - - auto zero = llvm::ConstantInt::get(_type, 0); - auto one = llvm::ConstantInt::get(_type, 1); - - auto x = &func->getArgumentList().front(); - x->setName("x"); - auto yArg = x->getNextNode(); - yArg->setName("y"); - - InsertPointGuard guard{m_builder}; - - auto entryBB = llvm::BasicBlock::Create(m_builder.getContext(), "Entry", func); - auto mainBB = llvm::BasicBlock::Create(m_builder.getContext(), "Main", func); - auto loopBB = llvm::BasicBlock::Create(m_builder.getContext(), "Loop", func); - auto continueBB = llvm::BasicBlock::Create(m_builder.getContext(), "Continue", func); - auto returnBB = llvm::BasicBlock::Create(m_builder.getContext(), "Return", func); - - m_builder.SetInsertPoint(entryBB); - auto yNonZero = m_builder.CreateICmpNE(yArg, zero); - auto yLEx = m_builder.CreateICmpULE(yArg, x); - auto r0 = m_builder.CreateSelect(yNonZero, x, zero, "r0"); - m_builder.CreateCondBr(m_builder.CreateAnd(yLEx, yNonZero), mainBB, returnBB); - - m_builder.SetInsertPoint(mainBB); - auto ctlzIntr = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::ctlz, _type); - // both y and r are non-zero - auto yLz = m_builder.CreateCall2(ctlzIntr, yArg, m_builder.getInt1(true), "y.lz"); - auto rLz = m_builder.CreateCall2(ctlzIntr, r0, m_builder.getInt1(true), "r.lz"); - auto i0 = m_builder.CreateNUWSub(yLz, rLz, "i0"); - auto y0 = m_builder.CreateShl(yArg, i0); - m_builder.CreateBr(loopBB); - - m_builder.SetInsertPoint(loopBB); - auto yPhi = m_builder.CreatePHI(_type, 2, "y.phi"); - auto rPhi = m_builder.CreatePHI(_type, 2, "r.phi"); - auto iPhi = m_builder.CreatePHI(_type, 2, "i.phi"); - auto qPhi = m_builder.CreatePHI(_type, 2, "q.phi"); - auto rUpdate = m_builder.CreateNUWSub(rPhi, yPhi); - auto qUpdate = m_builder.CreateOr(qPhi, one); // q += 1, q lowest bit is 0 - auto rGEy = m_builder.CreateICmpUGE(rPhi, yPhi); - auto r1 = m_builder.CreateSelect(rGEy, rUpdate, rPhi, "r1"); - auto q1 = m_builder.CreateSelect(rGEy, qUpdate, qPhi, "q"); - auto iZero = m_builder.CreateICmpEQ(iPhi, zero); - m_builder.CreateCondBr(iZero, returnBB, continueBB); - - m_builder.SetInsertPoint(continueBB); - auto i2 = m_builder.CreateNUWSub(iPhi, one); - auto q2 = m_builder.CreateShl(q1, one); - auto y2 = m_builder.CreateLShr(yPhi, one); - m_builder.CreateBr(loopBB); - - yPhi->addIncoming(y0, mainBB); - yPhi->addIncoming(y2, continueBB); - rPhi->addIncoming(r0, mainBB); - rPhi->addIncoming(r1, continueBB); - iPhi->addIncoming(i0, mainBB); - iPhi->addIncoming(i2, continueBB); - qPhi->addIncoming(zero, mainBB); - qPhi->addIncoming(q2, continueBB); - - m_builder.SetInsertPoint(returnBB); - auto qRet = m_builder.CreatePHI(_type, 2, "q.ret"); - qRet->addIncoming(zero, entryBB); - qRet->addIncoming(q1, loopBB); - auto rRet = m_builder.CreatePHI(_type, 2, "r.ret"); - rRet->addIncoming(r0, entryBB); - rRet->addIncoming(r1, loopBB); - auto ret = m_builder.CreateInsertElement(llvm::UndefValue::get(retType), qRet, uint64_t(0), "ret0"); - ret = m_builder.CreateInsertElement(ret, rRet, 1, "ret"); - m_builder.CreateRet(ret); - } - return func; -} - llvm::Function* Arith256::getExpFunc() { if (!m_exp) @@ -550,8 +490,7 @@ llvm::Function* Arith256::getAddModFunc() auto y512 = m_builder.CreateZExt(y, i512Ty, "y512"); auto m512 = m_builder.CreateZExt(mod, i512Ty, "m512"); auto s = m_builder.CreateAdd(x512, y512, "s"); - auto d = createCall(getDivFunc(i512Ty), {s, m512}); - auto r = m_builder.CreateExtractElement(d, 1, "r"); + auto r = createCall(getURem512Func(*getModule()), {s, m512}); m_builder.CreateRet(m_builder.CreateTrunc(r, Type::Word)); } return m_addmod; @@ -580,8 +519,7 @@ llvm::Function* Arith256::getMulModFunc() m_builder.SetInsertPoint(entryBB); auto p = createCall(getMul512Func(), {x, y}); auto m = m_builder.CreateZExt(mod, i512Ty, "m"); - auto d = createCall(getDivFunc(i512Ty), {p, m}); - auto r = m_builder.CreateExtractElement(d, 1, "r"); + auto r = createCall(getURem512Func(*getModule()), {p, m}); m_builder.CreateRet(m_builder.CreateTrunc(r, Type::Word)); } return m_mulmod; diff --git a/evmjit/libevmjit/Arith256.h b/evmjit/libevmjit/Arith256.h index aeea830db..d6096a4c2 100644 --- a/evmjit/libevmjit/Arith256.h +++ b/evmjit/libevmjit/Arith256.h @@ -23,21 +23,20 @@ public: static llvm::Function* getMulFunc(llvm::Module& _module); static llvm::Function* getUDiv256Func(llvm::Module& _module); static llvm::Function* getURem256Func(llvm::Module& _module); + static llvm::Function* getURem512Func(llvm::Module& _module); static llvm::Function* getUDivRem256Func(llvm::Module& _module); static llvm::Function* getSDiv256Func(llvm::Module& _module); static llvm::Function* getSRem256Func(llvm::Module& _module); static llvm::Function* getSDivRem256Func(llvm::Module& _module); + static llvm::Function* getUDivRem512Func(llvm::Module& _module); private: llvm::Function* getMul512Func(); - llvm::Function* getDivFunc(llvm::Type* _type); llvm::Function* getExpFunc(); llvm::Function* getAddModFunc(); llvm::Function* getMulModFunc(); llvm::Function* m_mul512 = nullptr; - llvm::Function* m_div = nullptr; - llvm::Function* m_div512 = nullptr; llvm::Function* m_exp = nullptr; llvm::Function* m_addmod = nullptr; llvm::Function* m_mulmod = nullptr; diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 7ae3e067b..33d802f90 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -277,37 +277,48 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti case Instruction::DIV: { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateUDiv(lhs, rhs); - stack.push(res); + auto d = stack.pop(); + auto n = stack.pop(); + auto divByZero = m_builder.CreateICmpEQ(n, Constant::get(0)); + auto r = m_builder.CreateUDiv(d, n); + r = m_builder.CreateSelect(divByZero, Constant::get(0), r); + stack.push(r); break; } case Instruction::SDIV: { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateSDiv(lhs, rhs); - stack.push(res); + auto d = stack.pop(); + auto n = stack.pop(); + auto divByZero = m_builder.CreateICmpEQ(n, Constant::get(0)); + auto divByMinusOne = m_builder.CreateICmpEQ(n, Constant::get(-1)); + auto r = m_builder.CreateSDiv(d, n); + r = m_builder.CreateSelect(divByZero, Constant::get(0), r); + auto dNeg = m_builder.CreateSub(Constant::get(0), d); + r = m_builder.CreateSelect(divByMinusOne, dNeg, r); + stack.push(r); break; } case Instruction::MOD: { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateURem(lhs, rhs); - stack.push(res); + auto d = stack.pop(); + auto n = stack.pop(); + auto divByZero = m_builder.CreateICmpEQ(n, Constant::get(0)); + auto r = m_builder.CreateURem(d, n); + r = m_builder.CreateSelect(divByZero, Constant::get(0), r); + stack.push(r); break; } case Instruction::SMOD: { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto res = m_builder.CreateSRem(lhs, rhs); - stack.push(res); + auto d = stack.pop(); + auto n = stack.pop(); + auto divByZero = m_builder.CreateICmpEQ(n, Constant::get(0)); + auto r = m_builder.CreateSRem(d, n); + r = m_builder.CreateSelect(divByZero, Constant::get(0), r); + stack.push(r); break; } From 9a025df4e769254cd5a6c7587cf21cfffffe8847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 13 May 2015 17:22:35 +0200 Subject: [PATCH 014/290] Add support for --singletest filter in VM tests. Add & correct arithmetic VM tests. --- .../VMTestsFiller/vmArithmeticTestFiller.json | 133 +++++++++++++++++- test/libevm/vm.cpp | 7 +- 2 files changed, 132 insertions(+), 8 deletions(-) diff --git a/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json b/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json index c06a429e0..f8a824f57 100644 --- a/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json +++ b/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json @@ -728,6 +728,41 @@ "gas" : "100000" } }, + + "divByZero_2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "storage" : { + "0x" : "0x00" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (+ (/ 13 0) 7)}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, "div1": { "env" : { @@ -974,6 +1009,34 @@ } }, + "sdivByZero2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (+ (SDIV (- 0 115792089237316195423570985008687907853269984665640564039457584007900129639935) 0) 1) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + "sdiv0": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", @@ -1639,6 +1702,34 @@ } }, + "modByZero": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (- (% 3 0) 1) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + "smod0": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", @@ -1873,7 +1964,7 @@ "value" : "1000000000000000000", "data" : "", "gasPrice" : "100000000000000", - "gas" : "10000" + "gas" : "100000" } }, @@ -1912,6 +2003,34 @@ } }, + "smod8_byZero": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (- (SMOD (- 0 200) 0) 13)}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + "addmod0": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", @@ -2006,7 +2125,7 @@ "value" : "1000000000000000000", "data" : "", "gasPrice" : "100000000000000", - "gas" : "10000" + "gas" : "1000000" } }, @@ -2104,7 +2223,7 @@ "value" : "1000000000000000000", "data" : "", "gasPrice" : "100000000000000", - "gas" : "10000" + "gas" : "1000000" } }, @@ -2132,7 +2251,7 @@ "value" : "1000000000000000000", "data" : "", "gasPrice" : "100000000000000", - "gas" : "10000" + "gas" : "1000000" } }, @@ -2546,7 +2665,7 @@ "value" : "1000000000000000000", "data" : "", "gasPrice" : "100000000000000", - "gas" : "10000" + "gas" : "1000000" } }, @@ -2574,7 +2693,7 @@ "value" : "1000000000000000000", "data" : "", "gasPrice" : "100000000000000", - "gas" : "10000" + "gas" : "1000000" } }, @@ -2602,7 +2721,7 @@ "value" : "1000000000000000000", "data" : "", "gasPrice" : "100000000000000", - "gas" : "10000" + "gas" : "1000000" } }, diff --git a/test/libevm/vm.cpp b/test/libevm/vm.cpp index 090258244..10670bfe3 100644 --- a/test/libevm/vm.cpp +++ b/test/libevm/vm.cpp @@ -300,9 +300,14 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) { for (auto& i: v.get_obj()) { - std::cout << " " << i.first << "\n"; mObject& o = i.second.get_obj(); + if (test::Options::get().singleTest && test::Options::get().singleTestName != i.first) + { + o.clear(); + continue; + } + std::cout << " " << i.first << "\n"; BOOST_REQUIRE(o.count("env") > 0); BOOST_REQUIRE(o.count("pre") > 0); BOOST_REQUIRE(o.count("exec") > 0); From 3b8e2996a5db4ad5704f22fe20478337dc40376a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 13 May 2015 18:55:14 +0200 Subject: [PATCH 015/290] Lower ADDMOD & MULMOD (limited) to a function call in the LLVM pass after optimization. --- evmjit/libevmjit/Arith256.cpp | 183 ++++++++------------------------- evmjit/libevmjit/Arith256.h | 9 +- evmjit/libevmjit/Compiler.cpp | 55 ++++++---- evmjit/libevmjit/Optimizer.cpp | 10 ++ 4 files changed, 87 insertions(+), 170 deletions(-) diff --git a/evmjit/libevmjit/Arith256.cpp b/evmjit/libevmjit/Arith256.cpp index 64ed7e649..472c699a8 100644 --- a/evmjit/libevmjit/Arith256.cpp +++ b/evmjit/libevmjit/Arith256.cpp @@ -86,6 +86,47 @@ llvm::Function* Arith256::getMulFunc(llvm::Module& _module) return func; } +llvm::Function* Arith256::getMul512Func(llvm::Module& _module) +{ + static const auto funcName = "evm.mul.i512"; + if (auto func = _module.getFunction(funcName)) + return func; + + auto i512Ty = llvm::IntegerType::get(_module.getContext(), 512); + auto func = llvm::Function::Create(llvm::FunctionType::get(i512Ty, {Type::Word, Type::Word}, false), llvm::Function::PrivateLinkage, funcName, &_module); + func->setDoesNotThrow(); + func->setDoesNotAccessMemory(); + + auto x = &func->getArgumentList().front(); + x->setName("x"); + auto y = x->getNextNode(); + y->setName("y"); + + auto bb = llvm::BasicBlock::Create(_module.getContext(), {}, func); + auto builder = llvm::IRBuilder<>{bb}; + + auto i128 = builder.getIntNTy(128); + auto i256 = Type::Word; + auto x_lo = builder.CreateZExt(builder.CreateTrunc(x, i128, "x.lo"), i256); + auto y_lo = builder.CreateZExt(builder.CreateTrunc(y, i128, "y.lo"), i256); + auto x_hi = builder.CreateZExt(builder.CreateTrunc(builder.CreateLShr(x, Constant::get(128)), i128, "x.hi"), i256); + auto y_hi = builder.CreateZExt(builder.CreateTrunc(builder.CreateLShr(y, Constant::get(128)), i128, "y.hi"), i256); + + auto mul256Func = getMulFunc(_module); + auto t1 = builder.CreateCall(mul256Func, {x_lo, y_lo}); + auto t2 = builder.CreateCall(mul256Func, {x_lo, y_hi}); + auto t3 = builder.CreateCall(mul256Func, {x_hi, y_lo}); + auto t4 = builder.CreateCall(mul256Func, {x_hi, y_hi}); + + auto p = builder.CreateZExt(t1, i512Ty); + p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t2, i512Ty), builder.getIntN(512, 128))); + p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t3, i512Ty), builder.getIntN(512, 128))); + p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t4, i512Ty), builder.getIntN(512, 256))); + builder.CreateRet(p); + + return func; +} + namespace { llvm::Function* createUDivRemFunc(llvm::Type* _type, llvm::Module& _module, char const* _funcName) @@ -354,47 +395,6 @@ llvm::Function* Arith256::getSRem256Func(llvm::Module& _module) return func; } -llvm::Function* Arith256::getMul512Func() -{ - auto& func = m_mul512; - if (!func) - { - auto i512 = m_builder.getIntNTy(512); - llvm::Type* argTypes[] = {Type::Word, Type::Word}; - func = llvm::Function::Create(llvm::FunctionType::get(i512, argTypes, false), llvm::Function::PrivateLinkage, "mul512", getModule()); - func->setDoesNotThrow(); - func->setDoesNotAccessMemory(); - - auto x = &func->getArgumentList().front(); - x->setName("x"); - auto y = x->getNextNode(); - y->setName("y"); - - InsertPointGuard guard{m_builder}; - auto bb = llvm::BasicBlock::Create(m_builder.getContext(), {}, func); - m_builder.SetInsertPoint(bb); - auto i128 = m_builder.getIntNTy(128); - auto i256 = Type::Word; - auto x_lo = m_builder.CreateZExt(m_builder.CreateTrunc(x, i128, "x.lo"), i256); - auto y_lo = m_builder.CreateZExt(m_builder.CreateTrunc(y, i128, "y.lo"), i256); - auto x_hi = m_builder.CreateZExt(m_builder.CreateTrunc(m_builder.CreateLShr(x, Constant::get(128)), i128, "x.hi"), i256); - auto y_hi = m_builder.CreateZExt(m_builder.CreateTrunc(m_builder.CreateLShr(y, Constant::get(128)), i128, "y.hi"), i256); - - auto mul256Func = getMulFunc(*getModule()); - auto t1 = createCall(mul256Func, {x_lo, y_lo}); - auto t2 = createCall(mul256Func, {x_lo, y_hi}); - auto t3 = createCall(mul256Func, {x_hi, y_lo}); - auto t4 = createCall(mul256Func, {x_hi, y_hi}); - - auto p = m_builder.CreateZExt(t1, i512); - p = m_builder.CreateAdd(p, m_builder.CreateShl(m_builder.CreateZExt(t2, i512), m_builder.getIntN(512, 128))); - p = m_builder.CreateAdd(p, m_builder.CreateShl(m_builder.CreateZExt(t3, i512), m_builder.getIntN(512, 128))); - p = m_builder.CreateAdd(p, m_builder.CreateShl(m_builder.CreateZExt(t4, i512), m_builder.getIntN(512, 256))); - m_builder.CreateRet(p); - } - return func; -} - llvm::Function* Arith256::getExpFunc() { if (!m_exp) @@ -465,66 +465,6 @@ llvm::Function* Arith256::getExpFunc() return m_exp; } -llvm::Function* Arith256::getAddModFunc() -{ - if (!m_addmod) - { - auto i512Ty = m_builder.getIntNTy(512); - llvm::Type* argTypes[] = {Type::Word, Type::Word, Type::Word}; - m_addmod = llvm::Function::Create(llvm::FunctionType::get(Type::Word, argTypes, false), llvm::Function::PrivateLinkage, "addmod", getModule()); - m_addmod->setDoesNotThrow(); - m_addmod->setDoesNotAccessMemory(); - - auto x = &m_addmod->getArgumentList().front(); - x->setName("x"); - auto y = x->getNextNode(); - y->setName("y"); - auto mod = y->getNextNode(); - mod->setName("m"); - - InsertPointGuard guard{m_builder}; - - auto entryBB = llvm::BasicBlock::Create(m_builder.getContext(), {}, m_addmod); - m_builder.SetInsertPoint(entryBB); - auto x512 = m_builder.CreateZExt(x, i512Ty, "x512"); - auto y512 = m_builder.CreateZExt(y, i512Ty, "y512"); - auto m512 = m_builder.CreateZExt(mod, i512Ty, "m512"); - auto s = m_builder.CreateAdd(x512, y512, "s"); - auto r = createCall(getURem512Func(*getModule()), {s, m512}); - m_builder.CreateRet(m_builder.CreateTrunc(r, Type::Word)); - } - return m_addmod; -} - -llvm::Function* Arith256::getMulModFunc() -{ - if (!m_mulmod) - { - llvm::Type* argTypes[] = {Type::Word, Type::Word, Type::Word}; - m_mulmod = llvm::Function::Create(llvm::FunctionType::get(Type::Word, argTypes, false), llvm::Function::PrivateLinkage, "mulmod", getModule()); - m_mulmod->setDoesNotThrow(); - m_mulmod->setDoesNotAccessMemory(); - - auto i512Ty = m_builder.getIntNTy(512); - auto x = &m_mulmod->getArgumentList().front(); - x->setName("x"); - auto y = x->getNextNode(); - y->setName("y"); - auto mod = y->getNextNode(); - mod->setName("mod"); - - InsertPointGuard guard{m_builder}; - - auto entryBB = llvm::BasicBlock::Create(m_builder.getContext(), {}, m_mulmod); - m_builder.SetInsertPoint(entryBB); - auto p = createCall(getMul512Func(), {x, y}); - auto m = m_builder.CreateZExt(mod, i512Ty, "m"); - auto r = createCall(getURem512Func(*getModule()), {p, m}); - m_builder.CreateRet(m_builder.CreateTrunc(r, Type::Word)); - } - return m_mulmod; -} - llvm::Value* Arith256::exp(llvm::Value* _arg1, llvm::Value* _arg2) { // while (e != 0) { @@ -555,47 +495,6 @@ llvm::Value* Arith256::exp(llvm::Value* _arg1, llvm::Value* _arg2) return createCall(getExpFunc(), {_arg1, _arg2}); } -llvm::Value* Arith256::addmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3) -{ - if (auto c1 = llvm::dyn_cast(_arg1)) - { - if (auto c2 = llvm::dyn_cast(_arg2)) - { - if (auto c3 = llvm::dyn_cast(_arg3)) - { - if (!c3->getValue()) - return Constant::get(0); - auto s = c1->getValue().zext(256+64) + c2->getValue().zext(256+64); - auto r = s.urem(c3->getValue().zext(256+64)).trunc(256); - return Constant::get(r); - } - } - } - - return createCall(getAddModFunc(), {_arg1, _arg2, _arg3}); -} - -llvm::Value* Arith256::mulmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3) -{ - if (auto c1 = llvm::dyn_cast(_arg1)) - { - if (auto c2 = llvm::dyn_cast(_arg2)) - { - if (auto c3 = llvm::dyn_cast(_arg3)) - { - if (!c3->getValue()) - return Constant::get(0); - auto p = c1->getValue().zext(512) * c2->getValue().zext(512); - auto r = p.urem(c3->getValue().zext(512)).trunc(256); - return Constant::get(r); - } - } - } - - return createCall(getMulModFunc(), {_arg1, _arg2, _arg3}); -} - - } } } diff --git a/evmjit/libevmjit/Arith256.h b/evmjit/libevmjit/Arith256.h index d6096a4c2..81535a792 100644 --- a/evmjit/libevmjit/Arith256.h +++ b/evmjit/libevmjit/Arith256.h @@ -15,12 +15,11 @@ public: Arith256(llvm::IRBuilder<>& _builder); llvm::Value* exp(llvm::Value* _arg1, llvm::Value* _arg2); - llvm::Value* mulmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3); - llvm::Value* addmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3); void debug(llvm::Value* _value, char _c); static llvm::Function* getMulFunc(llvm::Module& _module); + static llvm::Function* getMul512Func(llvm::Module& _module); static llvm::Function* getUDiv256Func(llvm::Module& _module); static llvm::Function* getURem256Func(llvm::Module& _module); static llvm::Function* getURem512Func(llvm::Module& _module); @@ -31,15 +30,9 @@ public: static llvm::Function* getUDivRem512Func(llvm::Module& _module); private: - llvm::Function* getMul512Func(); llvm::Function* getExpFunc(); - llvm::Function* getAddModFunc(); - llvm::Function* getMulModFunc(); - llvm::Function* m_mul512 = nullptr; llvm::Function* m_exp = nullptr; - llvm::Function* m_addmod = nullptr; - llvm::Function* m_mulmod = nullptr; llvm::Function* m_debug = nullptr; }; diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 33d802f90..56f1904a1 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -322,6 +322,41 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti break; } + case Instruction::ADDMOD: + { + auto i512Ty = m_builder.getIntNTy(512); + auto a = stack.pop(); + auto b = stack.pop(); + auto m = stack.pop(); + auto divByZero = m_builder.CreateICmpEQ(m, Constant::get(0)); + a = m_builder.CreateZExt(a, i512Ty); + b = m_builder.CreateZExt(b, i512Ty); + m = m_builder.CreateZExt(m, i512Ty); + auto s = m_builder.CreateNUWAdd(a, b); + s = m_builder.CreateURem(s, m); + s = m_builder.CreateTrunc(s, Type::Word); + s = m_builder.CreateSelect(divByZero, Constant::get(0), s); + stack.push(s); + break; + } + + case Instruction::MULMOD: + { + auto i512Ty = m_builder.getIntNTy(512); + auto a = stack.pop(); + auto b = stack.pop(); + auto m = stack.pop(); + auto divByZero = m_builder.CreateICmpEQ(m, Constant::get(0)); + m = m_builder.CreateZExt(m, i512Ty); + // TODO: Add support for i256 x i256 -> i512 in LowerEVM pass + llvm::Value* p = m_builder.CreateCall(Arith256::getMul512Func(*_basicBlock.llvm()->getParent()->getParent()), {a, b}); + p = m_builder.CreateURem(p, m); + p = m_builder.CreateTrunc(p, Type::Word); + p = m_builder.CreateSelect(divByZero, Constant::get(0), p); + stack.push(p); + break; + } + case Instruction::EXP: { auto base = stack.pop(); @@ -440,26 +475,6 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti break; } - case Instruction::ADDMOD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto mod = stack.pop(); - auto res = _arith.addmod(lhs, rhs, mod); - stack.push(res); - break; - } - - case Instruction::MULMOD: - { - auto lhs = stack.pop(); - auto rhs = stack.pop(); - auto mod = stack.pop(); - auto res = _arith.mulmod(lhs, rhs, mod); - stack.push(res); - break; - } - case Instruction::SIGNEXTEND: { auto idx = stack.pop(); diff --git a/evmjit/libevmjit/Optimizer.cpp b/evmjit/libevmjit/Optimizer.cpp index 8eaab9a99..52bf14efa 100644 --- a/evmjit/libevmjit/Optimizer.cpp +++ b/evmjit/libevmjit/Optimizer.cpp @@ -54,6 +54,7 @@ bool LowerEVMPass::runOnBasicBlock(llvm::BasicBlock& _bb) { auto modified = false; auto module = _bb.getParent()->getParent(); + auto i512Ty = llvm::IntegerType::get(_bb.getContext(), 512); for (auto it = _bb.begin(); it != _bb.end(); ) { auto& inst = *it++; @@ -83,6 +84,15 @@ bool LowerEVMPass::runOnBasicBlock(llvm::BasicBlock& _bb) break; } } + else if (inst.getType() == i512Ty) + { + switch (inst.getOpcode()) + { + case llvm::Instruction::URem: + func = Arith256::getURem512Func(*module); + break; + } + } if (func) { From b0937aafd9fb430473e8635686e2e9ab7763967b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 13 May 2015 18:55:31 +0200 Subject: [PATCH 016/290] Tests: add edge cases for ADDMOD and MULMOD. --- .../VMTestsFiller/vmArithmeticTestFiller.json | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json b/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json index f8a824f57..76771982e 100644 --- a/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json +++ b/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json @@ -2535,6 +2535,34 @@ } }, + "addmodDivByZero3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (- (ADDMOD 0 0 0) 1) } ", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + "mulmod0": { "env" : { @@ -3040,6 +3068,34 @@ } }, + "mulmoddivByZero3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (- 1 (MULMOD 0 0 0)) } ", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + "expXY": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", From 910732c2cb32c410034e291f5bea3c452d61696a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 13 May 2015 19:12:49 +0200 Subject: [PATCH 017/290] Remove div by 0 check in udivrem implementation. --- evmjit/libevmjit/Arith256.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/evmjit/libevmjit/Arith256.cpp b/evmjit/libevmjit/Arith256.cpp index 472c699a8..6c1f8f160 100644 --- a/evmjit/libevmjit/Arith256.cpp +++ b/evmjit/libevmjit/Arith256.cpp @@ -154,10 +154,9 @@ llvm::Function* createUDivRemFunc(llvm::Type* _type, llvm::Module& _module, char auto returnBB = llvm::BasicBlock::Create(_module.getContext(), "Return", func); auto builder = llvm::IRBuilder<>{entryBB}; - auto yNonZero = builder.CreateICmpNE(yArg, zero); auto yLEx = builder.CreateICmpULE(yArg, x); - auto r0 = builder.CreateSelect(yNonZero, x, zero, "r0"); - builder.CreateCondBr(builder.CreateAnd(yLEx, yNonZero), mainBB, returnBB); + auto r0 = x; + builder.CreateCondBr(yLEx, mainBB, returnBB); builder.SetInsertPoint(mainBB); auto ctlzIntr = llvm::Intrinsic::getDeclaration(&_module, llvm::Intrinsic::ctlz, _type); From 7dd279e64eceddd2c13e54263079f38a238447ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 14 May 2015 10:50:37 +0200 Subject: [PATCH 018/290] Remove unused code --- evmjit/libevmjit/Stack.cpp | 90 -------------------------------------- evmjit/libevmjit/Stack.h | 3 -- 2 files changed, 93 deletions(-) diff --git a/evmjit/libevmjit/Stack.cpp b/evmjit/libevmjit/Stack.cpp index 7cf514dea..b47567f17 100644 --- a/evmjit/libevmjit/Stack.cpp +++ b/evmjit/libevmjit/Stack.cpp @@ -23,96 +23,6 @@ Stack::Stack(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager): m_stack(_builder, "stack") {} -llvm::Function* Stack::getPushFunc() -{ - auto& func = m_push; - if (!func) - { - llvm::Type* argTypes[] = {Type::RuntimePtr, Type::Word}; - func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::ExternalLinkage, "stack.push", getModule()); - llvm::Type* extArgTypes[] = {Type::RuntimePtr, Type::WordPtr}; - auto extPushFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, extArgTypes, false), llvm::Function::ExternalLinkage, "stack_push", getModule()); - - auto rt = &func->getArgumentList().front(); - rt->setName("rt"); - auto value = rt->getNextNode(); - value->setName("value"); - - InsertPointGuard guard{m_builder}; - auto entryBB = llvm::BasicBlock::Create(m_builder.getContext(), {}, func); - m_builder.SetInsertPoint(entryBB); - auto a = m_builder.CreateAlloca(Type::Word); - m_builder.CreateStore(value, a); - createCall(extPushFunc, {rt, a}); - m_builder.CreateRetVoid(); - } - return func; -} - -llvm::Function* Stack::getSetFunc() -{ - auto& func = m_set; - if (!func) - { - llvm::Type* argTypes[] = {Type::RuntimePtr, Type::Size, Type::Word}; - func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::ExternalLinkage, "stack.set", getModule()); - llvm::Type* extArgTypes[] = {Type::RuntimePtr, Type::Size, Type::WordPtr}; - auto extSetFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, extArgTypes, false), llvm::Function::ExternalLinkage, "stack_set", getModule()); - - auto rt = &func->getArgumentList().front(); - rt->setName("rt"); - auto index = rt->getNextNode(); - index->setName("index"); - auto value = index->getNextNode(); - value->setName("value"); - - InsertPointGuard guard{m_builder}; - auto entryBB = llvm::BasicBlock::Create(m_builder.getContext(), {}, func); - m_builder.SetInsertPoint(entryBB); - auto a = m_builder.CreateAlloca(Type::Word); - m_builder.CreateStore(value, a); - createCall(extSetFunc, {rt, index, a}); - m_builder.CreateRetVoid(); - } - return func; -} - -llvm::Function* Stack::getPopFunc() -{ - auto& func = m_pop; - if (!func) - { - llvm::Type* argTypes[] = {Type::RuntimePtr, Type::Size, Type::BytePtr}; - func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::ExternalLinkage, "stack.pop", getModule()); - llvm::Type* extArgTypes[] = {Type::RuntimePtr, Type::Size}; - auto extPopFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Bool, extArgTypes, false), llvm::Function::ExternalLinkage, "stack_pop", getModule()); - - auto rt = &func->getArgumentList().front(); - rt->setName("rt"); - auto index = rt->getNextNode(); - index->setName("index"); - auto jmpBuf = index->getNextNode(); - jmpBuf->setName("jmpBuf"); - - InsertPointGuard guard{m_builder}; - auto entryBB = llvm::BasicBlock::Create(m_builder.getContext(), {}, func); - auto underflowBB = llvm::BasicBlock::Create(m_builder.getContext(), "Underflow", func); - auto returnBB = llvm::BasicBlock::Create(m_builder.getContext(), "Return", func); - - m_builder.SetInsertPoint(entryBB); - auto ok = createCall(extPopFunc, {rt, index}); - m_builder.CreateCondBr(ok, returnBB, underflowBB); //TODO: Add branch weight - - m_builder.SetInsertPoint(underflowBB); - m_runtimeManager.abort(jmpBuf); - m_builder.CreateUnreachable(); - - m_builder.SetInsertPoint(returnBB); - m_builder.CreateRetVoid(); - } - return func; -} - llvm::Function* Stack::getGetFunc() { auto& func = m_get; diff --git a/evmjit/libevmjit/Stack.h b/evmjit/libevmjit/Stack.h index 3c526f0d3..6f7ad1c0b 100644 --- a/evmjit/libevmjit/Stack.h +++ b/evmjit/libevmjit/Stack.h @@ -24,10 +24,7 @@ public: void free() { m_stack.free(); } private: - llvm::Function* getPopFunc(); - llvm::Function* getPushFunc(); llvm::Function* getGetFunc(); - llvm::Function* getSetFunc(); RuntimeManager& m_runtimeManager; From f19c7c49816e156a93c8a6a241f2f716bf8083e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 14 May 2015 16:14:21 +0200 Subject: [PATCH 019/290] Add protection against hardware division by 0. --- evmjit/libevmjit/Compiler.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 56f1904a1..75c81f9ed 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -280,6 +280,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti auto d = stack.pop(); auto n = stack.pop(); auto divByZero = m_builder.CreateICmpEQ(n, Constant::get(0)); + n = m_builder.CreateSelect(divByZero, Constant::get(1), n); // protect against hardware signal auto r = m_builder.CreateUDiv(d, n); r = m_builder.CreateSelect(divByZero, Constant::get(0), r); stack.push(r); @@ -292,6 +293,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti auto n = stack.pop(); auto divByZero = m_builder.CreateICmpEQ(n, Constant::get(0)); auto divByMinusOne = m_builder.CreateICmpEQ(n, Constant::get(-1)); + n = m_builder.CreateSelect(divByZero, Constant::get(1), n); // protect against hardware signal auto r = m_builder.CreateSDiv(d, n); r = m_builder.CreateSelect(divByZero, Constant::get(0), r); auto dNeg = m_builder.CreateSub(Constant::get(0), d); @@ -305,6 +307,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti auto d = stack.pop(); auto n = stack.pop(); auto divByZero = m_builder.CreateICmpEQ(n, Constant::get(0)); + n = m_builder.CreateSelect(divByZero, Constant::get(1), n); // protect against hardware signal auto r = m_builder.CreateURem(d, n); r = m_builder.CreateSelect(divByZero, Constant::get(0), r); stack.push(r); @@ -316,6 +319,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti auto d = stack.pop(); auto n = stack.pop(); auto divByZero = m_builder.CreateICmpEQ(n, Constant::get(0)); + n = m_builder.CreateSelect(divByZero, Constant::get(1), n); // protect against hardware signal auto r = m_builder.CreateSRem(d, n); r = m_builder.CreateSelect(divByZero, Constant::get(0), r); stack.push(r); From 002d9a9d69b312433fd50d49ff6a1bb671018bc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 14 May 2015 16:39:16 +0200 Subject: [PATCH 020/290] Handle more edge cases in DIV, etc. --- evmjit/libevmjit/Compiler.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 75c81f9ed..a7006dcde 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -297,7 +297,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti auto r = m_builder.CreateSDiv(d, n); r = m_builder.CreateSelect(divByZero, Constant::get(0), r); auto dNeg = m_builder.CreateSub(Constant::get(0), d); - r = m_builder.CreateSelect(divByMinusOne, dNeg, r); + r = m_builder.CreateSelect(divByMinusOne, dNeg, r); // protect against undef i256.min / -1 stack.push(r); break; } @@ -319,9 +319,11 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti auto d = stack.pop(); auto n = stack.pop(); auto divByZero = m_builder.CreateICmpEQ(n, Constant::get(0)); + auto divByMinusOne = m_builder.CreateICmpEQ(n, Constant::get(-1)); n = m_builder.CreateSelect(divByZero, Constant::get(1), n); // protect against hardware signal auto r = m_builder.CreateSRem(d, n); r = m_builder.CreateSelect(divByZero, Constant::get(0), r); + r = m_builder.CreateSelect(divByMinusOne, Constant::get(0), r); // protect against undef i256.min / -1 stack.push(r); break; } From 7391606d839bc232416381297941a81d2b484519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 14 May 2015 16:39:40 +0200 Subject: [PATCH 021/290] Tests: SMOD edge case test. --- .../VMTestsFiller/vmArithmeticTestFiller.json | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json b/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json index 76771982e..72c90e912 100644 --- a/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json +++ b/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json @@ -2031,6 +2031,76 @@ } }, + "smod_i256min1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "storage" : { + "0x" : "0x8000000000000000000000000000000000000000000000000000000000000000" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (SMOD (- 0 57896044618658097711785492504343953926634992332820282019728792003956564819968) (- 0 1) ) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + + "smod_i256min2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "storage" : { + "0x" : "0x8000000000000000000000000000000000000000000000000000000000000000" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (- (SMOD (- 0 57896044618658097711785492504343953926634992332820282019728792003956564819968) (- 0 1) ) 1) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + "addmod0": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", From 9b66cea1c83bf09fc33aa00924e69ab175134cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 14 May 2015 16:57:26 +0200 Subject: [PATCH 022/290] Enable function inlining optimization. --- evmjit/libevmjit/Optimizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evmjit/libevmjit/Optimizer.cpp b/evmjit/libevmjit/Optimizer.cpp index 52bf14efa..d5bf7f05c 100644 --- a/evmjit/libevmjit/Optimizer.cpp +++ b/evmjit/libevmjit/Optimizer.cpp @@ -21,7 +21,7 @@ namespace jit bool optimize(llvm::Module& _module) { auto pm = llvm::legacy::PassManager{}; - //pm.add(llvm::createFunctionInliningPass(2, 2)); // Problem with APInt value bigger than 64bit + pm.add(llvm::createFunctionInliningPass(2, 2)); pm.add(llvm::createCFGSimplificationPass()); pm.add(llvm::createInstructionCombiningPass()); pm.add(llvm::createAggressiveDCEPass()); From b96d6ff0881e9d5f5a940f6f868183cc99819482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 15 May 2015 14:06:42 +0200 Subject: [PATCH 023/290] Extract execution context from ExecutionEngine::run. --- evmjit/libevmjit-cpp/JitVM.cpp | 5 +- evmjit/libevmjit-cpp/JitVM.h | 2 +- evmjit/libevmjit/ExecutionEngine.cpp | 86 ++++++++++++++++------------ evmjit/libevmjit/ExecutionEngine.h | 24 +++++--- evmjit/libevmjit/interface.cpp | 14 ++--- 5 files changed, 76 insertions(+), 55 deletions(-) diff --git a/evmjit/libevmjit-cpp/JitVM.cpp b/evmjit/libevmjit-cpp/JitVM.cpp index 7acbec5c1..85109ebbc 100644 --- a/evmjit/libevmjit-cpp/JitVM.cpp +++ b/evmjit/libevmjit-cpp/JitVM.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include "Utils.h" @@ -56,7 +55,7 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _step) m_data.codeHash = eth2llvm(sha3(_ext.code)); auto env = reinterpret_cast(&_ext); - auto exitCode = m_engine.run(&m_data, env); + auto exitCode = jit::ExecutionEngine::run(m_context, &m_data, env); switch (exitCode) { case ReturnCode::Suicide: @@ -79,7 +78,7 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _step) } m_gas = m_data.gas; // TODO: Remove m_gas field - return {std::get<0>(m_engine.returnData), std::get<1>(m_engine.returnData)}; + return {std::get<0>(m_context.returnData), std::get<1>(m_context.returnData)}; } } diff --git a/evmjit/libevmjit-cpp/JitVM.h b/evmjit/libevmjit-cpp/JitVM.h index 58caa3648..4bd4a7bbf 100644 --- a/evmjit/libevmjit-cpp/JitVM.h +++ b/evmjit/libevmjit-cpp/JitVM.h @@ -17,7 +17,7 @@ private: explicit JitVM(u256 _gas = 0) : VMFace(_gas) {} jit::RuntimeData m_data; - jit::ExecutionEngine m_engine; + jit::ExecutionContext m_context; std::unique_ptr m_fallbackVM; ///< VM used in case of input data rejected by JIT }; diff --git a/evmjit/libevmjit/ExecutionEngine.cpp b/evmjit/libevmjit/ExecutionEngine.cpp index 0377ac402..741a7d764 100644 --- a/evmjit/libevmjit/ExecutionEngine.cpp +++ b/evmjit/libevmjit/ExecutionEngine.cpp @@ -90,65 +90,77 @@ void parseOptions() cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler"); } +// FIXME: It is temporary, becaue ExecutionEngine.h is currently our public header +// and including llvm::ExecutionEngine there is not a good idea. +llvm::ExecutionEngine* g_ee = nullptr; + } +ExecutionEngine& ExecutionEngine::get() +{ + static ExecutionEngine instance; + return instance; +} -ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env) +ExecutionEngine::ExecutionEngine() { - static std::once_flag flag; - std::call_once(flag, parseOptions); + /// ExecutionEngine is created only once - std::unique_ptr listener{new ExecStats}; - listener->stateChanged(ExecState::Started); + parseOptions(); + + if (g_cache == CacheMode::clear) + Cache::clear(); bool preloadCache = g_cache == CacheMode::preload; if (preloadCache) g_cache = CacheMode::on; - // TODO: Do not pseudo-init the cache every time - auto objectCache = (g_cache != CacheMode::off && g_cache != CacheMode::clear) ? Cache::getObjectCache(g_cache, listener.get()) : nullptr; + llvm::InitializeNativeTarget(); + llvm::InitializeNativeTargetAsmPrinter(); - static std::unique_ptr ee; - if (!ee) - { - if (g_cache == CacheMode::clear) - Cache::clear(); + auto module = std::unique_ptr(new llvm::Module({}, llvm::getGlobalContext())); + + // FIXME: LLVM 3.7: test on Windows + auto triple = llvm::Triple(llvm::sys::getProcessTriple()); + if (triple.getOS() == llvm::Triple::OSType::Win32) + triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF); // MCJIT does not support COFF format + module->setTargetTriple(triple.str()); - llvm::InitializeNativeTarget(); - llvm::InitializeNativeTargetAsmPrinter(); + llvm::EngineBuilder builder(std::move(module)); + builder.setEngineKind(llvm::EngineKind::JIT); + builder.setOptLevel(g_optimize ? llvm::CodeGenOpt::Default : llvm::CodeGenOpt::None); - auto module = std::unique_ptr(new llvm::Module({}, llvm::getGlobalContext())); + g_ee = (builder.create()); - // FIXME: LLVM 3.7: test on Windows - auto triple = llvm::Triple(llvm::sys::getProcessTriple()); - if (triple.getOS() == llvm::Triple::OSType::Win32) - triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF); // MCJIT does not support COFF format - module->setTargetTriple(triple.str()); + // TODO: Update cache listener + auto objectCache = (g_cache != CacheMode::off && g_cache != CacheMode::clear) ? Cache::getObjectCache(g_cache, nullptr) : nullptr; + g_ee->setObjectCache(objectCache); - llvm::EngineBuilder builder(std::move(module)); - builder.setEngineKind(llvm::EngineKind::JIT); - builder.setOptLevel(g_optimize ? llvm::CodeGenOpt::Default : llvm::CodeGenOpt::None); + // FIXME: Disabled during API changes + //if (preloadCache) + // Cache::preload(*ee, funcCache); +} + + +ReturnCode ExecutionEngine::run(ExecutionContext& _context, RuntimeData* _data, Env* _env) +{ + ExecutionEngine::get(); // FIXME + + std::unique_ptr listener{new ExecStats}; + listener->stateChanged(ExecState::Started); - ee.reset(builder.create()); - if (!CHECK(ee)) - return ReturnCode::LLVMConfigError; - ee->setObjectCache(objectCache); - // FIXME: Disabled during API changes - //if (preloadCache) - // Cache::preload(*ee, funcCache); - } static StatsCollector statsCollector; auto mainFuncName = codeHash(_data->codeHash); - m_runtime.init(_data, _env); + _context.m_runtime.init(_data, _env); // TODO: Remove cast auto entryFuncPtr = (EntryFuncPtr) JIT::getCode(_data->codeHash); if (!entryFuncPtr) { - auto module = objectCache ? Cache::getObject(mainFuncName) : nullptr; + auto module = Cache::getObject(mainFuncName); if (!module) { listener->stateChanged(ExecState::Compilation); @@ -166,20 +178,20 @@ ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env) if (g_dump) module->dump(); - ee->addModule(std::move(module)); + g_ee->addModule(std::move(module)); listener->stateChanged(ExecState::CodeGen); - entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName); + entryFuncPtr = (EntryFuncPtr)g_ee->getFunctionAddress(mainFuncName); if (!CHECK(entryFuncPtr)) return ReturnCode::LLVMLinkError; JIT::mapCode(_data->codeHash, (void*)entryFuncPtr); // FIXME: Remove cast } listener->stateChanged(ExecState::Execution); - auto returnCode = entryFuncPtr(&m_runtime); + auto returnCode = entryFuncPtr(&_context.m_runtime); listener->stateChanged(ExecState::Return); if (returnCode == ReturnCode::Return) - returnData = m_runtime.getReturnData(); // Save reference to return data + _context.returnData = _context.m_runtime.getReturnData(); // Save reference to return data listener->stateChanged(ExecState::Finished); diff --git a/evmjit/libevmjit/ExecutionEngine.h b/evmjit/libevmjit/ExecutionEngine.h index 26da6977c..c380b6cb5 100644 --- a/evmjit/libevmjit/ExecutionEngine.h +++ b/evmjit/libevmjit/ExecutionEngine.h @@ -38,22 +38,32 @@ public: virtual void stateChanged(ExecState) {} }; -class ExecutionEngine +class ExecutionContext { public: - ExecutionEngine() = default; - ExecutionEngine(ExecutionEngine const&) = delete; - ExecutionEngine& operator=(ExecutionEngine) = delete; - - EXPORT ReturnCode run(RuntimeData* _data, Env* _env); + ExecutionContext() = default; + ExecutionContext(ExecutionContext const&) = delete; + ExecutionContext& operator=(ExecutionContext const&) = delete; /// Reference to returned data (RETURN opcode used) bytes_ref returnData; -private: Runtime m_runtime; }; +class ExecutionEngine +{ +public: + ExecutionEngine(ExecutionEngine const&) = delete; + ExecutionEngine& operator=(ExecutionEngine const&) = delete; + + EXPORT static ReturnCode run(ExecutionContext& _context, RuntimeData* _data, Env* _env); + +private: + ExecutionEngine(); + static ExecutionEngine& get(); +}; + } } } diff --git a/evmjit/libevmjit/interface.cpp b/evmjit/libevmjit/interface.cpp index 01f743a2e..bc9d98474 100644 --- a/evmjit/libevmjit/interface.cpp +++ b/evmjit/libevmjit/interface.cpp @@ -7,23 +7,23 @@ using namespace dev::eth::jit; EXPORT void* evmjit_create() noexcept { - // TODO: Make sure ExecutionEngine constructor does not throw - return new(std::nothrow) ExecutionEngine; + // TODO: Make sure ExecutionEngine constructor does not throw + make JIT/ExecutionEngine interface all nothrow + return new(std::nothrow) ExecutionContext; } -EXPORT void evmjit_destroy(ExecutionEngine* _engine) noexcept +EXPORT void evmjit_destroy(ExecutionContext* _context) noexcept { - delete _engine; + delete _context; } -EXPORT int evmjit_run(ExecutionEngine* _engine, RuntimeData* _data, Env* _env) noexcept +EXPORT int evmjit_run(ExecutionContext* _context, RuntimeData* _data, Env* _env) noexcept { - if (!_engine || !_data) + if (!_context || !_data) return static_cast(ReturnCode::UnexpectedException); try { - auto returnCode = _engine->run(_data, _env); + auto returnCode = ExecutionEngine::run(*_context, _data, _env); return static_cast(returnCode); } catch(...) From 3cb8f3a4b24b292bf0432a4130acb0c7f110f195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 15 May 2015 15:22:37 +0200 Subject: [PATCH 024/290] Merge ExecutionContext and Runtime classes --- evmjit/libevmjit-cpp/JitVM.cpp | 4 +- evmjit/libevmjit-cpp/JitVM.h | 1 + evmjit/libevmjit/Array.cpp | 1 - evmjit/libevmjit/CMakeLists.txt | 2 +- evmjit/libevmjit/Common.h | 4 +- .../{Runtime.cpp => ExecutionContext.cpp} | 18 ++------ evmjit/libevmjit/ExecutionContext.h | 41 +++++++++++++++++++ evmjit/libevmjit/ExecutionEngine.cpp | 27 ++++++------ evmjit/libevmjit/ExecutionEngine.h | 22 ++++------ evmjit/libevmjit/Memory.cpp | 1 - evmjit/libevmjit/Runtime.h | 30 -------------- evmjit/libevmjit/Stack.cpp | 1 - evmjit/libevmjit/interface.cpp | 15 +++---- 13 files changed, 80 insertions(+), 87 deletions(-) rename evmjit/libevmjit/{Runtime.cpp => ExecutionContext.cpp} (70%) create mode 100644 evmjit/libevmjit/ExecutionContext.h delete mode 100644 evmjit/libevmjit/Runtime.h diff --git a/evmjit/libevmjit-cpp/JitVM.cpp b/evmjit/libevmjit-cpp/JitVM.cpp index 85109ebbc..e44628c67 100644 --- a/evmjit/libevmjit-cpp/JitVM.cpp +++ b/evmjit/libevmjit-cpp/JitVM.cpp @@ -54,8 +54,8 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _step) m_data.codeSize = _ext.code.size(); m_data.codeHash = eth2llvm(sha3(_ext.code)); - auto env = reinterpret_cast(&_ext); - auto exitCode = jit::ExecutionEngine::run(m_context, &m_data, env); + m_context.init(m_data, reinterpret_cast(&_ext)); + auto exitCode = jit::ExecutionEngine::run(m_context); switch (exitCode) { case ReturnCode::Suicide: diff --git a/evmjit/libevmjit-cpp/JitVM.h b/evmjit/libevmjit-cpp/JitVM.h index 4bd4a7bbf..aad379a75 100644 --- a/evmjit/libevmjit-cpp/JitVM.h +++ b/evmjit/libevmjit-cpp/JitVM.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include namespace dev diff --git a/evmjit/libevmjit/Array.cpp b/evmjit/libevmjit/Array.cpp index b3d3cc0bb..a76776c69 100644 --- a/evmjit/libevmjit/Array.cpp +++ b/evmjit/libevmjit/Array.cpp @@ -6,7 +6,6 @@ #include "preprocessor/llvm_includes_end.h" #include "RuntimeManager.h" -#include "Runtime.h" #include "Utils.h" #include // DEBUG only diff --git a/evmjit/libevmjit/CMakeLists.txt b/evmjit/libevmjit/CMakeLists.txt index 4b15d52ac..324ad6717 100644 --- a/evmjit/libevmjit/CMakeLists.txt +++ b/evmjit/libevmjit/CMakeLists.txt @@ -11,6 +11,7 @@ set(SOURCES ${EVMJIT_INCLUDE_DIR}/evmjit/DataTypes.h Endianness.cpp Endianness.h ExecStats.cpp ExecStats.h + ExecutionContext.cpp ExecutionContext.h ExecutionEngine.cpp ExecutionEngine.h Ext.cpp Ext.h GasMeter.cpp GasMeter.h @@ -19,7 +20,6 @@ set(SOURCES JIT.cpp ${EVMJIT_INCLUDE_DIR}/evmjit/JIT.h Memory.cpp Memory.h Optimizer.cpp Optimizer.h - Runtime.cpp Runtime.h RuntimeData.h RuntimeManager.cpp RuntimeManager.h Stack.cpp Stack.h diff --git a/evmjit/libevmjit/Common.h b/evmjit/libevmjit/Common.h index b519614fe..e99308174 100644 --- a/evmjit/libevmjit/Common.h +++ b/evmjit/libevmjit/Common.h @@ -4,8 +4,8 @@ #include #ifdef _MSC_VER -#define EXPORT __declspec(dllexport) -#define _ALLOW_KEYWORD_MACROS +#define EXPORT __declspec(dllexport) +#define _ALLOW_KEYWORD_MACROS #define noexcept throw() #else #define EXPORT diff --git a/evmjit/libevmjit/Runtime.cpp b/evmjit/libevmjit/ExecutionContext.cpp similarity index 70% rename from evmjit/libevmjit/Runtime.cpp rename to evmjit/libevmjit/ExecutionContext.cpp index 7e9a7d52e..fab6fad87 100644 --- a/evmjit/libevmjit/Runtime.cpp +++ b/evmjit/libevmjit/ExecutionContext.cpp @@ -1,29 +1,20 @@ -#include "Runtime.h" - +#include "ExecutionContext.h" #include namespace dev { -namespace eth -{ -namespace jit -{ - -void Runtime::init(RuntimeData* _data, Env* _env) +namespace evmjit { - m_data = _data; - m_env = _env; -} extern "C" void ext_free(void* _data) noexcept; -Runtime::~Runtime() +ExecutionContext::~ExecutionContext() { if (m_memData) ext_free(m_memData); // Use helper free to check memory leaks } -bytes_ref Runtime::getReturnData() const +bytes_ref ExecutionContext::getReturnData() const { auto data = m_data->callData; auto size = static_cast(m_data->callDataSize); @@ -40,4 +31,3 @@ bytes_ref Runtime::getReturnData() const } } -} diff --git a/evmjit/libevmjit/ExecutionContext.h b/evmjit/libevmjit/ExecutionContext.h new file mode 100644 index 000000000..6d40e2819 --- /dev/null +++ b/evmjit/libevmjit/ExecutionContext.h @@ -0,0 +1,41 @@ +#pragma once + +#include "RuntimeData.h" + +namespace dev +{ +namespace evmjit +{ + using namespace eth::jit; // FIXME + +class ExecutionContext +{ +public: + ExecutionContext() = default; + ExecutionContext(RuntimeData& _data, Env* _env) { init(_data, _env); } + ExecutionContext(ExecutionContext const&) = delete; + ExecutionContext& operator=(ExecutionContext const&) = delete; + EXPORT ~ExecutionContext(); + + void init(RuntimeData& _data, Env* _env) { m_data = &_data; m_env = _env; } + + byte const* code() const { return m_data->code; } + uint64_t codeSize() const { return m_data->codeSize; } + h256 const& codeHash() const { return m_data->codeHash; } + + bytes_ref getReturnData() const; + +private: + RuntimeData* m_data = nullptr; ///< Pointer to data. Expected by compiled contract. + Env* m_env = nullptr; ///< Pointer to environment proxy. Expected by compiled contract. + byte* m_memData = nullptr; + uint64_t m_memSize = 0; + uint64_t m_memCap = 0; + +public: + /// Reference to returned data (RETURN opcode used) + bytes_ref returnData; +}; + +} +} diff --git a/evmjit/libevmjit/ExecutionEngine.cpp b/evmjit/libevmjit/ExecutionEngine.cpp index 741a7d764..a96ac700c 100644 --- a/evmjit/libevmjit/ExecutionEngine.cpp +++ b/evmjit/libevmjit/ExecutionEngine.cpp @@ -19,8 +19,8 @@ #include #include "preprocessor/llvm_includes_end.h" +#include "ExecutionContext.h" #include "evmjit/JIT.h" -#include "Runtime.h" #include "Compiler.h" #include "Optimizer.h" #include "Cache.h" @@ -38,9 +38,9 @@ using evmjit::JIT; namespace { -using EntryFuncPtr = ReturnCode(*)(Runtime*); +using EntryFuncPtr = ReturnCode(*)(ExecutionContext*); -std::string codeHash(i256 const& _hash) +std::string hash2str(i256 const& _hash) { static const auto size = sizeof(_hash); static const auto hexChars = "0123456789abcdef"; @@ -142,30 +142,31 @@ ExecutionEngine::ExecutionEngine() } -ReturnCode ExecutionEngine::run(ExecutionContext& _context, RuntimeData* _data, Env* _env) +ReturnCode ExecutionEngine::run(ExecutionContext& _context) { ExecutionEngine::get(); // FIXME std::unique_ptr listener{new ExecStats}; listener->stateChanged(ExecState::Started); - + auto code = _context.code(); + auto codeSize = _context.codeSize(); + auto codeHash = _context.codeHash(); static StatsCollector statsCollector; - auto mainFuncName = codeHash(_data->codeHash); - _context.m_runtime.init(_data, _env); + auto mainFuncName = hash2str(codeHash); // TODO: Remove cast - auto entryFuncPtr = (EntryFuncPtr) JIT::getCode(_data->codeHash); + auto entryFuncPtr = (EntryFuncPtr) JIT::getCode(codeHash); if (!entryFuncPtr) { auto module = Cache::getObject(mainFuncName); if (!module) { listener->stateChanged(ExecState::Compilation); - assert(_data->code || !_data->codeSize); //TODO: Is it good idea to execute empty code? - module = Compiler{{}}.compile(_data->code, _data->code + _data->codeSize, mainFuncName); + assert(code || !codeSize); //TODO: Is it good idea to execute empty code? + module = Compiler{{}}.compile(code, code + codeSize, mainFuncName); if (g_optimize) { @@ -183,15 +184,15 @@ ReturnCode ExecutionEngine::run(ExecutionContext& _context, RuntimeData* _data, entryFuncPtr = (EntryFuncPtr)g_ee->getFunctionAddress(mainFuncName); if (!CHECK(entryFuncPtr)) return ReturnCode::LLVMLinkError; - JIT::mapCode(_data->codeHash, (void*)entryFuncPtr); // FIXME: Remove cast + JIT::mapCode(codeHash, (void*)entryFuncPtr); // FIXME: Remove cast } listener->stateChanged(ExecState::Execution); - auto returnCode = entryFuncPtr(&_context.m_runtime); + auto returnCode = entryFuncPtr(&_context); listener->stateChanged(ExecState::Return); if (returnCode == ReturnCode::Return) - _context.returnData = _context.m_runtime.getReturnData(); // Save reference to return data + _context.returnData = _context.getReturnData(); // Save reference to return data listener->stateChanged(ExecState::Finished); diff --git a/evmjit/libevmjit/ExecutionEngine.h b/evmjit/libevmjit/ExecutionEngine.h index c380b6cb5..5c689403c 100644 --- a/evmjit/libevmjit/ExecutionEngine.h +++ b/evmjit/libevmjit/ExecutionEngine.h @@ -1,15 +1,20 @@ #pragma once #include +#include "Common.h" -#include "Runtime.h" namespace dev { +namespace evmjit +{ + class ExecutionContext; +} namespace eth { namespace jit { + using namespace evmjit; // FIXME enum class ExecState { @@ -38,26 +43,13 @@ public: virtual void stateChanged(ExecState) {} }; -class ExecutionContext -{ -public: - ExecutionContext() = default; - ExecutionContext(ExecutionContext const&) = delete; - ExecutionContext& operator=(ExecutionContext const&) = delete; - - /// Reference to returned data (RETURN opcode used) - bytes_ref returnData; - - Runtime m_runtime; -}; - class ExecutionEngine { public: ExecutionEngine(ExecutionEngine const&) = delete; ExecutionEngine& operator=(ExecutionEngine const&) = delete; - EXPORT static ReturnCode run(ExecutionContext& _context, RuntimeData* _data, Env* _env); + EXPORT static ReturnCode run(ExecutionContext& _context); private: ExecutionEngine(); diff --git a/evmjit/libevmjit/Memory.cpp b/evmjit/libevmjit/Memory.cpp index 6d5b72024..fdf5a6b98 100644 --- a/evmjit/libevmjit/Memory.cpp +++ b/evmjit/libevmjit/Memory.cpp @@ -5,7 +5,6 @@ #include "preprocessor/llvm_includes_end.h" #include "Type.h" -#include "Runtime.h" #include "GasMeter.h" #include "Endianness.h" #include "RuntimeManager.h" diff --git a/evmjit/libevmjit/Runtime.h b/evmjit/libevmjit/Runtime.h deleted file mode 100644 index 895128a59..000000000 --- a/evmjit/libevmjit/Runtime.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "RuntimeData.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ - -class Runtime -{ -public: - void init(RuntimeData* _data, Env* _env); - EXPORT ~Runtime(); - - bytes_ref getReturnData() const; - -private: - RuntimeData* m_data = nullptr; ///< Pointer to data. Expected by compiled contract. - Env* m_env = nullptr; ///< Pointer to environment proxy. Expected by compiled contract. - byte* m_memData = nullptr; - uint64_t m_memSize = 0; - uint64_t m_memCap = 0; -}; - -} -} -} diff --git a/evmjit/libevmjit/Stack.cpp b/evmjit/libevmjit/Stack.cpp index b47567f17..b7b8f25b1 100644 --- a/evmjit/libevmjit/Stack.cpp +++ b/evmjit/libevmjit/Stack.cpp @@ -5,7 +5,6 @@ #include "preprocessor/llvm_includes_end.h" #include "RuntimeManager.h" -#include "Runtime.h" #include "Utils.h" #include // DEBUG only diff --git a/evmjit/libevmjit/interface.cpp b/evmjit/libevmjit/interface.cpp index bc9d98474..18b36cd7f 100644 --- a/evmjit/libevmjit/interface.cpp +++ b/evmjit/libevmjit/interface.cpp @@ -1,14 +1,18 @@ #include "ExecutionEngine.h" +#include "ExecutionContext.h" extern "C" { using namespace dev::eth::jit; -EXPORT void* evmjit_create() noexcept +EXPORT void* evmjit_create(RuntimeData* _data, Env* _env) noexcept { + if (!_data) + return nullptr; + // TODO: Make sure ExecutionEngine constructor does not throw + make JIT/ExecutionEngine interface all nothrow - return new(std::nothrow) ExecutionContext; + return new(std::nothrow) ExecutionContext{*_data, _env}; } EXPORT void evmjit_destroy(ExecutionContext* _context) noexcept @@ -16,14 +20,11 @@ EXPORT void evmjit_destroy(ExecutionContext* _context) noexcept delete _context; } -EXPORT int evmjit_run(ExecutionContext* _context, RuntimeData* _data, Env* _env) noexcept +EXPORT int evmjit_run(ExecutionContext* _context) noexcept { - if (!_context || !_data) - return static_cast(ReturnCode::UnexpectedException); - try { - auto returnCode = ExecutionEngine::run(*_context, _data, _env); + auto returnCode = ExecutionEngine::run(*_context); return static_cast(returnCode); } catch(...) From d43991723f8fcfab85b00227ca4133f9b233555e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 15 May 2015 17:05:11 +0200 Subject: [PATCH 025/290] Fix cache mode handling. --- evmjit/libevmjit/Cache.cpp | 17 ++++++++++++++--- evmjit/libevmjit/Cache.h | 2 +- evmjit/libevmjit/ExecutionEngine.cpp | 6 +----- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/evmjit/libevmjit/Cache.cpp b/evmjit/libevmjit/Cache.cpp index aa316d51d..464912104 100644 --- a/evmjit/libevmjit/Cache.cpp +++ b/evmjit/libevmjit/Cache.cpp @@ -40,12 +40,23 @@ namespace } } -ObjectCache* Cache::getObjectCache(CacheMode _mode, ExecutionEngineListener* _listener) +ObjectCache* Cache::init(CacheMode _mode, ExecutionEngineListener* _listener) { - static ObjectCache objectCache; g_mode = _mode; g_listener = _listener; - return &objectCache; + + if (g_mode == CacheMode::clear) + { + Cache::clear(); + g_mode = CacheMode::off; + } + + if (g_mode != CacheMode::off) + { + static ObjectCache objectCache; + return &objectCache; + } + return nullptr; } void Cache::clear() diff --git a/evmjit/libevmjit/Cache.h b/evmjit/libevmjit/Cache.h index 6b8457f4b..ef4a0bac7 100644 --- a/evmjit/libevmjit/Cache.h +++ b/evmjit/libevmjit/Cache.h @@ -45,7 +45,7 @@ public: class Cache { public: - static ObjectCache* getObjectCache(CacheMode _mode, ExecutionEngineListener* _listener); + static ObjectCache* init(CacheMode _mode, ExecutionEngineListener* _listener); static std::unique_ptr getObject(std::string const& id); /// Clears cache storage diff --git a/evmjit/libevmjit/ExecutionEngine.cpp b/evmjit/libevmjit/ExecutionEngine.cpp index a96ac700c..736946079 100644 --- a/evmjit/libevmjit/ExecutionEngine.cpp +++ b/evmjit/libevmjit/ExecutionEngine.cpp @@ -108,9 +108,6 @@ ExecutionEngine::ExecutionEngine() parseOptions(); - if (g_cache == CacheMode::clear) - Cache::clear(); - bool preloadCache = g_cache == CacheMode::preload; if (preloadCache) g_cache = CacheMode::on; @@ -133,8 +130,7 @@ ExecutionEngine::ExecutionEngine() g_ee = (builder.create()); // TODO: Update cache listener - auto objectCache = (g_cache != CacheMode::off && g_cache != CacheMode::clear) ? Cache::getObjectCache(g_cache, nullptr) : nullptr; - g_ee->setObjectCache(objectCache); + g_ee->setObjectCache(Cache::init(g_cache, nullptr)); // FIXME: Disabled during API changes //if (preloadCache) From 75e4e34647b067ff7c44409d0aa76fc6829d04fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 15 May 2015 17:31:08 +0200 Subject: [PATCH 026/290] Better style of ExecutionEngine initialization. Some eth::jit -> evmjit namespace transfers. --- evmjit/include/evmjit/JIT.h | 10 +------- evmjit/libevmjit-cpp/JitVM.cpp | 18 +++++++------- evmjit/libevmjit-cpp/JitVM.h | 2 +- evmjit/libevmjit/Cache.cpp | 6 ++--- evmjit/libevmjit/Cache.h | 5 +--- evmjit/libevmjit/ExecStats.cpp | 5 +--- evmjit/libevmjit/ExecStats.h | 6 ++--- evmjit/libevmjit/ExecutionEngine.cpp | 35 +++++++++------------------- evmjit/libevmjit/ExecutionEngine.h | 20 +++------------- evmjit/libevmjit/interface.cpp | 2 +- 10 files changed, 31 insertions(+), 78 deletions(-) diff --git a/evmjit/include/evmjit/JIT.h b/evmjit/include/evmjit/JIT.h index 446dd9e56..ba7a0dbc0 100644 --- a/evmjit/include/evmjit/JIT.h +++ b/evmjit/include/evmjit/JIT.h @@ -4,14 +4,6 @@ namespace dev { -namespace eth -{ -namespace jit -{ - class ExecutionEngine; -} -} - namespace evmjit { @@ -26,7 +18,7 @@ public: static bool isCodeReady(h256 _codeHash); private: - friend class dev::eth::jit::ExecutionEngine; + friend class ExecutionEngine; static void* getCode(h256 _codeHash); static void mapCode(h256 _codeHash, void* _funcAddr); diff --git a/evmjit/libevmjit-cpp/JitVM.cpp b/evmjit/libevmjit-cpp/JitVM.cpp index e44628c67..a4eed5793 100644 --- a/evmjit/libevmjit-cpp/JitVM.cpp +++ b/evmjit/libevmjit-cpp/JitVM.cpp @@ -19,8 +19,6 @@ extern "C" void env_sload(); // fake declaration for linker symbol stripping wor bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _step) { - using namespace jit; - auto rejected = false; // TODO: Rejecting transactions with gas limit > 2^63 can be used by attacker to take JIT out of scope rejected |= m_gas > std::numeric_limits::max(); // Do not accept requests with gas > 2^63 (int64 max) @@ -54,23 +52,23 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _step) m_data.codeSize = _ext.code.size(); m_data.codeHash = eth2llvm(sha3(_ext.code)); - m_context.init(m_data, reinterpret_cast(&_ext)); - auto exitCode = jit::ExecutionEngine::run(m_context); + m_context.init(m_data, reinterpret_cast(&_ext)); + auto exitCode = evmjit::ExecutionEngine::run(m_context); switch (exitCode) { - case ReturnCode::Suicide: + case evmjit::ReturnCode::Suicide: _ext.suicide(right160(llvm2eth(m_data.address))); break; - case ReturnCode::BadJumpDestination: + case evmjit::ReturnCode::BadJumpDestination: BOOST_THROW_EXCEPTION(BadJumpDestination()); - case ReturnCode::OutOfGas: + case evmjit::ReturnCode::OutOfGas: BOOST_THROW_EXCEPTION(OutOfGas()); - case ReturnCode::StackUnderflow: + case evmjit::ReturnCode::StackUnderflow: // FIXME: Remove support for detail errors BOOST_THROW_EXCEPTION(StackUnderflow()); - case ReturnCode::BadInstruction: + case evmjit::ReturnCode::BadInstruction: BOOST_THROW_EXCEPTION(BadInstruction()); - case ReturnCode::LinkerWorkaround: // never happens + case evmjit::ReturnCode::LinkerWorkaround: // never happens env_sload(); // but forces linker to include env_* JIT callback functions break; default: diff --git a/evmjit/libevmjit-cpp/JitVM.h b/evmjit/libevmjit-cpp/JitVM.h index aad379a75..a6f6f1d52 100644 --- a/evmjit/libevmjit-cpp/JitVM.h +++ b/evmjit/libevmjit-cpp/JitVM.h @@ -18,7 +18,7 @@ private: explicit JitVM(u256 _gas = 0) : VMFace(_gas) {} jit::RuntimeData m_data; - jit::ExecutionContext m_context; + evmjit::ExecutionContext m_context; std::unique_ptr m_fallbackVM; ///< VM used in case of input data rejected by JIT }; diff --git a/evmjit/libevmjit/Cache.cpp b/evmjit/libevmjit/Cache.cpp index 464912104..21be82d11 100644 --- a/evmjit/libevmjit/Cache.cpp +++ b/evmjit/libevmjit/Cache.cpp @@ -16,10 +16,9 @@ namespace dev { -namespace eth -{ -namespace jit +namespace evmjit { + using namespace eth::jit; namespace { @@ -177,4 +176,3 @@ std::unique_ptr ObjectCache::getObject(llvm::Module const* _ } } -} diff --git a/evmjit/libevmjit/Cache.h b/evmjit/libevmjit/Cache.h index ef4a0bac7..61635b8a1 100644 --- a/evmjit/libevmjit/Cache.h +++ b/evmjit/libevmjit/Cache.h @@ -12,9 +12,7 @@ namespace llvm namespace dev { -namespace eth -{ -namespace jit +namespace evmjit { class ExecutionEngineListener; @@ -57,4 +55,3 @@ public: } } -} diff --git a/evmjit/libevmjit/ExecStats.cpp b/evmjit/libevmjit/ExecStats.cpp index ff8c05307..c7f6ef0cd 100644 --- a/evmjit/libevmjit/ExecStats.cpp +++ b/evmjit/libevmjit/ExecStats.cpp @@ -8,9 +8,7 @@ namespace dev { -namespace eth -{ -namespace jit +namespace evmjit { void ExecStats::stateChanged(ExecState _state) @@ -95,4 +93,3 @@ StatsCollector::~StatsCollector() } } -} diff --git a/evmjit/libevmjit/ExecStats.h b/evmjit/libevmjit/ExecStats.h index 0451ccb05..3ea77733b 100644 --- a/evmjit/libevmjit/ExecStats.h +++ b/evmjit/libevmjit/ExecStats.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -8,9 +9,7 @@ namespace dev { -namespace eth -{ -namespace jit +namespace evmjit { class ExecStats : public ExecutionEngineListener @@ -42,4 +41,3 @@ public: } } -} diff --git a/evmjit/libevmjit/ExecutionEngine.cpp b/evmjit/libevmjit/ExecutionEngine.cpp index 736946079..e424d9d3a 100644 --- a/evmjit/libevmjit/ExecutionEngine.cpp +++ b/evmjit/libevmjit/ExecutionEngine.cpp @@ -30,11 +30,8 @@ namespace dev { -namespace eth +namespace evmjit { -namespace jit -{ -using evmjit::JIT; namespace { @@ -56,7 +53,7 @@ std::string hash2str(i256 const& _hash) return str; } -void printVersion() +void printVersion() // FIXME: Fix LLVM version parsing { std::cout << "Ethereum EVM JIT Compiler (http://github.com/ethereum/evmjit):\n" << " EVMJIT version " << EVMJIT_VERSION << "\n" @@ -90,19 +87,7 @@ void parseOptions() cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler"); } -// FIXME: It is temporary, becaue ExecutionEngine.h is currently our public header -// and including llvm::ExecutionEngine there is not a good idea. -llvm::ExecutionEngine* g_ee = nullptr; - -} - -ExecutionEngine& ExecutionEngine::get() -{ - static ExecutionEngine instance; - return instance; -} - -ExecutionEngine::ExecutionEngine() +std::unique_ptr init() { /// ExecutionEngine is created only once @@ -127,20 +112,23 @@ ExecutionEngine::ExecutionEngine() builder.setEngineKind(llvm::EngineKind::JIT); builder.setOptLevel(g_optimize ? llvm::CodeGenOpt::Default : llvm::CodeGenOpt::None); - g_ee = (builder.create()); + auto ee = std::unique_ptr{builder.create()}; // TODO: Update cache listener - g_ee->setObjectCache(Cache::init(g_cache, nullptr)); + ee->setObjectCache(Cache::init(g_cache, nullptr)); // FIXME: Disabled during API changes //if (preloadCache) // Cache::preload(*ee, funcCache); + + return ee; } +} ReturnCode ExecutionEngine::run(ExecutionContext& _context) { - ExecutionEngine::get(); // FIXME + static auto s_ee = init(); std::unique_ptr listener{new ExecStats}; listener->stateChanged(ExecState::Started); @@ -175,9 +163,9 @@ ReturnCode ExecutionEngine::run(ExecutionContext& _context) if (g_dump) module->dump(); - g_ee->addModule(std::move(module)); + s_ee->addModule(std::move(module)); listener->stateChanged(ExecState::CodeGen); - entryFuncPtr = (EntryFuncPtr)g_ee->getFunctionAddress(mainFuncName); + entryFuncPtr = (EntryFuncPtr)s_ee->getFunctionAddress(mainFuncName); if (!CHECK(entryFuncPtr)) return ReturnCode::LLVMLinkError; JIT::mapCode(codeHash, (void*)entryFuncPtr); // FIXME: Remove cast @@ -200,4 +188,3 @@ ReturnCode ExecutionEngine::run(ExecutionContext& _context) } } -} diff --git a/evmjit/libevmjit/ExecutionEngine.h b/evmjit/libevmjit/ExecutionEngine.h index 5c689403c..d14e50702 100644 --- a/evmjit/libevmjit/ExecutionEngine.h +++ b/evmjit/libevmjit/ExecutionEngine.h @@ -1,20 +1,14 @@ #pragma once -#include #include "Common.h" - namespace dev { namespace evmjit { - class ExecutionContext; -} -namespace eth -{ -namespace jit -{ - using namespace evmjit; // FIXME +class ExecutionContext; + +using namespace eth::jit; enum class ExecState { @@ -46,16 +40,8 @@ public: class ExecutionEngine { public: - ExecutionEngine(ExecutionEngine const&) = delete; - ExecutionEngine& operator=(ExecutionEngine const&) = delete; - EXPORT static ReturnCode run(ExecutionContext& _context); - -private: - ExecutionEngine(); - static ExecutionEngine& get(); }; } } -} diff --git a/evmjit/libevmjit/interface.cpp b/evmjit/libevmjit/interface.cpp index 18b36cd7f..3b4145cb7 100644 --- a/evmjit/libevmjit/interface.cpp +++ b/evmjit/libevmjit/interface.cpp @@ -3,8 +3,8 @@ extern "C" { - using namespace dev::eth::jit; +using namespace dev::evmjit; EXPORT void* evmjit_create(RuntimeData* _data, Env* _env) noexcept { From 8e4881bcd072b613c61cc52f00566950368a08ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 18 May 2015 09:48:44 +0200 Subject: [PATCH 027/290] Code migration. --- evmjit/include/evmjit/DataTypes.h | 12 +++++ evmjit/include/evmjit/JIT.h | 6 --- evmjit/libevmjit-cpp/JitVM.h | 2 +- evmjit/libevmjit/Arith256.cpp | 1 + evmjit/libevmjit/BasicBlock.h | 4 +- evmjit/libevmjit/CMakeLists.txt | 3 +- evmjit/libevmjit/Cache.cpp | 1 - evmjit/libevmjit/Common.h | 37 +------------- evmjit/libevmjit/ExecutionContext.h | 73 +++++++++++++++++++++++++++- evmjit/libevmjit/ExecutionEngine.cpp | 41 ++++++++++++++-- evmjit/libevmjit/ExecutionEngine.h | 5 +- evmjit/libevmjit/GasMeter.h | 1 + evmjit/libevmjit/Instruction.cpp | 5 +- evmjit/libevmjit/Instruction.h | 7 +-- evmjit/libevmjit/JIT.cpp | 46 ------------------ evmjit/libevmjit/RuntimeData.h | 63 ------------------------ evmjit/libevmjit/RuntimeManager.h | 3 +- evmjit/libevmjit/Type.h | 3 +- evmjit/libevmjit/interface.cpp | 1 - 19 files changed, 138 insertions(+), 176 deletions(-) delete mode 100644 evmjit/libevmjit/JIT.cpp delete mode 100644 evmjit/libevmjit/RuntimeData.h diff --git a/evmjit/include/evmjit/DataTypes.h b/evmjit/include/evmjit/DataTypes.h index 179d9a372..6f06a81d6 100644 --- a/evmjit/include/evmjit/DataTypes.h +++ b/evmjit/include/evmjit/DataTypes.h @@ -3,11 +3,23 @@ #include #include +#ifdef _MSC_VER +#define EXPORT __declspec(dllexport) +#define _ALLOW_KEYWORD_MACROS +#define noexcept throw() +#else +#define EXPORT +#endif + namespace dev { namespace evmjit { +using byte = uint8_t; +using bytes_ref = std::tuple; +using code_iterator = byte const*; + struct h256 { uint64_t words[4]; diff --git a/evmjit/include/evmjit/JIT.h b/evmjit/include/evmjit/JIT.h index ba7a0dbc0..5972bfa88 100644 --- a/evmjit/include/evmjit/JIT.h +++ b/evmjit/include/evmjit/JIT.h @@ -16,12 +16,6 @@ public: /// In this case the code can be executed without overhead. /// \param _codeHash The Keccak hash of the EVM code. static bool isCodeReady(h256 _codeHash); - -private: - friend class ExecutionEngine; - - static void* getCode(h256 _codeHash); - static void mapCode(h256 _codeHash, void* _funcAddr); }; } diff --git a/evmjit/libevmjit-cpp/JitVM.h b/evmjit/libevmjit-cpp/JitVM.h index a6f6f1d52..4fccca7df 100644 --- a/evmjit/libevmjit-cpp/JitVM.h +++ b/evmjit/libevmjit-cpp/JitVM.h @@ -17,7 +17,7 @@ private: friend class VMFactory; explicit JitVM(u256 _gas = 0) : VMFace(_gas) {} - jit::RuntimeData m_data; + evmjit::RuntimeData m_data; evmjit::ExecutionContext m_context; std::unique_ptr m_fallbackVM; ///< VM used in case of input data rejected by JIT }; diff --git a/evmjit/libevmjit/Arith256.cpp b/evmjit/libevmjit/Arith256.cpp index 6c1f8f160..9d6494730 100644 --- a/evmjit/libevmjit/Arith256.cpp +++ b/evmjit/libevmjit/Arith256.cpp @@ -8,6 +8,7 @@ #include #include "preprocessor/llvm_includes_end.h" +#include "evmjit/DataTypes.h" #include "Type.h" #include "Endianness.h" #include "Utils.h" diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index 5e19235a7..9960a0d1c 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -2,7 +2,8 @@ #include -#include "Common.h" + +#include "evmjit/DataTypes.h" #include "Stack.h" namespace dev @@ -13,6 +14,7 @@ namespace jit { using instr_idx = uint64_t; +using namespace evmjit; class BasicBlock { diff --git a/evmjit/libevmjit/CMakeLists.txt b/evmjit/libevmjit/CMakeLists.txt index 324ad6717..67e5f5800 100644 --- a/evmjit/libevmjit/CMakeLists.txt +++ b/evmjit/libevmjit/CMakeLists.txt @@ -17,10 +17,9 @@ set(SOURCES GasMeter.cpp GasMeter.h Instruction.cpp Instruction.h interface.cpp interface.h - JIT.cpp ${EVMJIT_INCLUDE_DIR}/evmjit/JIT.h + ${EVMJIT_INCLUDE_DIR}/evmjit/JIT.h Memory.cpp Memory.h Optimizer.cpp Optimizer.h - RuntimeData.h RuntimeManager.cpp RuntimeManager.h Stack.cpp Stack.h Type.cpp Type.h diff --git a/evmjit/libevmjit/Cache.cpp b/evmjit/libevmjit/Cache.cpp index 21be82d11..e64cb5430 100644 --- a/evmjit/libevmjit/Cache.cpp +++ b/evmjit/libevmjit/Cache.cpp @@ -18,7 +18,6 @@ namespace dev { namespace evmjit { - using namespace eth::jit; namespace { diff --git a/evmjit/libevmjit/Common.h b/evmjit/libevmjit/Common.h index e99308174..5067f4fb1 100644 --- a/evmjit/libevmjit/Common.h +++ b/evmjit/libevmjit/Common.h @@ -3,48 +3,13 @@ #include #include -#ifdef _MSC_VER -#define EXPORT __declspec(dllexport) -#define _ALLOW_KEYWORD_MACROS -#define noexcept throw() -#else -#define EXPORT -#endif - namespace dev { namespace eth { -namespace jit -{ - -using byte = uint8_t; -using bytes_ref = std::tuple; -using code_iterator = byte const*; - -enum class ReturnCode -{ - // Success codes - Stop = 0, - Return = 1, - Suicide = 2, - - // Standard error codes - OutOfGas = -1, - StackUnderflow = -2, - BadJumpDestination = -3, - BadInstruction = -4, - Rejected = -5, ///< Input data (code, gas, block info, etc.) does not meet JIT requirement and execution request has been rejected - - // Internal error codes - LLVMConfigError = -101, - LLVMCompileError = -102, - LLVMLinkError = -103, +namespace jit{ - UnexpectedException = -111, - LinkerWorkaround = -299, -}; #define UNTESTED assert(false) diff --git a/evmjit/libevmjit/ExecutionContext.h b/evmjit/libevmjit/ExecutionContext.h index 6d40e2819..fd7e8f11a 100644 --- a/evmjit/libevmjit/ExecutionContext.h +++ b/evmjit/libevmjit/ExecutionContext.h @@ -1,12 +1,81 @@ #pragma once -#include "RuntimeData.h" +#include "evmjit/DataTypes.h" namespace dev { namespace evmjit { - using namespace eth::jit; // FIXME + +struct RuntimeData +{ + enum Index + { + Gas, + GasPrice, + CallData, + CallDataSize, + Address, + Caller, + Origin, + CallValue, + CoinBase, + Difficulty, + GasLimit, + Number, + Timestamp, + Code, + CodeSize, + + SuicideDestAddress = Address, ///< Suicide balance destination address + ReturnData = CallData, ///< Return data pointer (set only in case of RETURN) + ReturnDataSize = CallDataSize, ///< Return data size (set only in case of RETURN) + }; + + int64_t gas = 0; + int64_t gasPrice = 0; + byte const* callData = nullptr; + uint64_t callDataSize = 0; + i256 address; + i256 caller; + i256 origin; + i256 callValue; + i256 coinBase; + i256 difficulty; + i256 gasLimit; + uint64_t number = 0; + int64_t timestamp = 0; + byte const* code = nullptr; + uint64_t codeSize = 0; + h256 codeHash; +}; + +/// VM Environment (ExtVM) opaque type +struct Env; + +enum class ReturnCode +{ + // Success codes + Stop = 0, + Return = 1, + Suicide = 2, + + // Standard error codes + OutOfGas = -1, + StackUnderflow = -2, + BadJumpDestination = -3, + BadInstruction = -4, + Rejected = -5, ///< Input data (code, gas, block info, etc.) does not meet JIT requirement and execution request has been rejected + + // Internal error codes + LLVMConfigError = -101, + LLVMCompileError = -102, + LLVMLinkError = -103, + + UnexpectedException = -111, + + LinkerWorkaround = -299, +}; class ExecutionContext { diff --git a/evmjit/libevmjit/ExecutionEngine.cpp b/evmjit/libevmjit/ExecutionEngine.cpp index e424d9d3a..79ae1315c 100644 --- a/evmjit/libevmjit/ExecutionEngine.cpp +++ b/evmjit/libevmjit/ExecutionEngine.cpp @@ -32,6 +32,7 @@ namespace dev { namespace evmjit { +using namespace eth::jit; namespace { @@ -53,7 +54,7 @@ std::string hash2str(i256 const& _hash) return str; } -void printVersion() // FIXME: Fix LLVM version parsing +void printVersion() { std::cout << "Ethereum EVM JIT Compiler (http://github.com/ethereum/evmjit):\n" << " EVMJIT version " << EVMJIT_VERSION << "\n" @@ -124,6 +125,40 @@ std::unique_ptr init() return ee; } +class JITImpl +{ +public: + std::unordered_map codeMap; + + static JITImpl& instance() + { + static JITImpl s_instance; + return s_instance; + } + + static void* getCode(h256 _codeHash); + static void mapCode(h256 _codeHash, void* _funcAddr); +}; + +void* JITImpl::getCode(h256 _codeHash) +{ + auto& codeMap = JITImpl::instance().codeMap; + auto it = codeMap.find(_codeHash); + if (it != codeMap.end()) + return it->second; + return nullptr; +} + +void JITImpl::mapCode(h256 _codeHash, void* _funcAddr) +{ + JITImpl::instance().codeMap.insert(std::make_pair(_codeHash, _funcAddr)); +} + +} // anonymous namespace + +bool JIT::isCodeReady(h256 _codeHash) +{ + return JITImpl::instance().codeMap.count(_codeHash) != 0; } ReturnCode ExecutionEngine::run(ExecutionContext& _context) @@ -142,7 +177,7 @@ ReturnCode ExecutionEngine::run(ExecutionContext& _context) auto mainFuncName = hash2str(codeHash); // TODO: Remove cast - auto entryFuncPtr = (EntryFuncPtr) JIT::getCode(codeHash); + auto entryFuncPtr = (EntryFuncPtr) JITImpl::getCode(codeHash); if (!entryFuncPtr) { auto module = Cache::getObject(mainFuncName); @@ -168,7 +203,7 @@ ReturnCode ExecutionEngine::run(ExecutionContext& _context) entryFuncPtr = (EntryFuncPtr)s_ee->getFunctionAddress(mainFuncName); if (!CHECK(entryFuncPtr)) return ReturnCode::LLVMLinkError; - JIT::mapCode(codeHash, (void*)entryFuncPtr); // FIXME: Remove cast + JITImpl::mapCode(codeHash, (void*)entryFuncPtr); // FIXME: Remove cast } listener->stateChanged(ExecState::Execution); diff --git a/evmjit/libevmjit/ExecutionEngine.h b/evmjit/libevmjit/ExecutionEngine.h index d14e50702..04c3218b0 100644 --- a/evmjit/libevmjit/ExecutionEngine.h +++ b/evmjit/libevmjit/ExecutionEngine.h @@ -1,14 +1,13 @@ #pragma once -#include "Common.h" +#include "evmjit/DataTypes.h" namespace dev { namespace evmjit { class ExecutionContext; - -using namespace eth::jit; +enum class ReturnCode; enum class ExecState { diff --git a/evmjit/libevmjit/GasMeter.h b/evmjit/libevmjit/GasMeter.h index aecc07315..93a6cc24c 100644 --- a/evmjit/libevmjit/GasMeter.h +++ b/evmjit/libevmjit/GasMeter.h @@ -10,6 +10,7 @@ namespace eth namespace jit { class RuntimeManager; +using namespace evmjit; class GasMeter : public CompilerHelper // TODO: Use RuntimeHelper { diff --git a/evmjit/libevmjit/Instruction.cpp b/evmjit/libevmjit/Instruction.cpp index f70b020f8..c2e267cdb 100644 --- a/evmjit/libevmjit/Instruction.cpp +++ b/evmjit/libevmjit/Instruction.cpp @@ -6,9 +6,7 @@ namespace dev { -namespace eth -{ -namespace jit +namespace evmjit { llvm::APInt readPushData(code_iterator& _curr, code_iterator _end) @@ -39,4 +37,3 @@ void skipPushData(code_iterator& _curr, code_iterator _end) } } -} diff --git a/evmjit/libevmjit/Instruction.h b/evmjit/libevmjit/Instruction.h index 6785213d6..2da3c4c65 100644 --- a/evmjit/libevmjit/Instruction.h +++ b/evmjit/libevmjit/Instruction.h @@ -1,6 +1,6 @@ #pragma once -#include "Common.h" +#include "evmjit/DataTypes.h" namespace llvm { @@ -9,9 +9,7 @@ namespace llvm namespace dev { -namespace eth -{ -namespace jit +namespace evmjit { /// Virtual machine bytecode instruction. @@ -236,4 +234,3 @@ void skipPushData(code_iterator& _curr, code_iterator _end); } } -} diff --git a/evmjit/libevmjit/JIT.cpp b/evmjit/libevmjit/JIT.cpp deleted file mode 100644 index 9774c7396..000000000 --- a/evmjit/libevmjit/JIT.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "evmjit/JIT.h" - -#include - -namespace dev -{ -namespace evmjit -{ -namespace -{ - -class JITImpl: JIT -{ -public: - std::unordered_map codeMap; - - static JITImpl& instance() - { - static JITImpl s_instance; - return s_instance; - } -}; - -} // anonymous namespace - -bool JIT::isCodeReady(h256 _codeHash) -{ - return JITImpl::instance().codeMap.count(_codeHash) != 0; -} - -void* JIT::getCode(h256 _codeHash) -{ - auto& codeMap = JITImpl::instance().codeMap; - auto it = codeMap.find(_codeHash); - if (it != codeMap.end()) - return it->second; - return nullptr; -} - -void JIT::mapCode(h256 _codeHash, void* _funcAddr) -{ - JITImpl::instance().codeMap.insert(std::make_pair(_codeHash, _funcAddr)); -} - -} -} diff --git a/evmjit/libevmjit/RuntimeData.h b/evmjit/libevmjit/RuntimeData.h deleted file mode 100644 index 6a5cd0d14..000000000 --- a/evmjit/libevmjit/RuntimeData.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include "evmjit/DataTypes.h" -#include "Common.h" - -namespace dev -{ -namespace eth -{ -namespace jit -{ -using evmjit::i256; -using evmjit::h256; - -struct RuntimeData -{ - enum Index - { - Gas, - GasPrice, - CallData, - CallDataSize, - Address, - Caller, - Origin, - CallValue, - CoinBase, - Difficulty, - GasLimit, - Number, - Timestamp, - Code, - CodeSize, - - SuicideDestAddress = Address, ///< Suicide balance destination address - ReturnData = CallData, ///< Return data pointer (set only in case of RETURN) - ReturnDataSize = CallDataSize, ///< Return data size (set only in case of RETURN) - }; - - int64_t gas = 0; - int64_t gasPrice = 0; - byte const* callData = nullptr; - uint64_t callDataSize = 0; - i256 address; - i256 caller; - i256 origin; - i256 callValue; - i256 coinBase; - i256 difficulty; - i256 gasLimit; - uint64_t number = 0; - int64_t timestamp = 0; - byte const* code = nullptr; - uint64_t codeSize = 0; - h256 codeHash; -}; - -/// VM Environment (ExtVM) opaque type -struct Env; - -} -} -} diff --git a/evmjit/libevmjit/RuntimeManager.h b/evmjit/libevmjit/RuntimeManager.h index 4c36c4ef3..088611093 100644 --- a/evmjit/libevmjit/RuntimeManager.h +++ b/evmjit/libevmjit/RuntimeManager.h @@ -1,8 +1,8 @@ #pragma once +#include "ExecutionContext.h" #include "CompilerHelper.h" #include "Type.h" -#include "RuntimeData.h" #include "Instruction.h" namespace dev @@ -11,6 +11,7 @@ namespace eth { namespace jit { +using namespace evmjit; class Stack; class RuntimeManager: public CompilerHelper diff --git a/evmjit/libevmjit/Type.h b/evmjit/libevmjit/Type.h index ba9181f6b..b1b6d1ad4 100644 --- a/evmjit/libevmjit/Type.h +++ b/evmjit/libevmjit/Type.h @@ -6,7 +6,7 @@ #include #include "preprocessor/llvm_includes_end.h" // FIXME: LLVM 3.7: check if needed -#include "Common.h" +#include "ExecutionContext.h" // FIXME: crappy dependence namespace dev { @@ -14,6 +14,7 @@ namespace eth { namespace jit { +using namespace evmjit; struct Type { diff --git a/evmjit/libevmjit/interface.cpp b/evmjit/libevmjit/interface.cpp index 3b4145cb7..4aef5995f 100644 --- a/evmjit/libevmjit/interface.cpp +++ b/evmjit/libevmjit/interface.cpp @@ -3,7 +3,6 @@ extern "C" { -using namespace dev::eth::jit; using namespace dev::evmjit; EXPORT void* evmjit_create(RuntimeData* _data, Env* _env) noexcept From bcc0cfd0555ed04b42d08d525ab96b749d81a586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 18 May 2015 10:25:35 +0200 Subject: [PATCH 028/290] Code migration. --- evmjit/include/evmjit/JIT.h | 4 ++ evmjit/libevmjit-cpp/JitVM.cpp | 3 +- evmjit/libevmjit-cpp/JitVM.h | 1 - evmjit/libevmjit/CMakeLists.txt | 3 +- evmjit/libevmjit/Cache.cpp | 6 +-- evmjit/libevmjit/Cache.h | 4 +- evmjit/libevmjit/ExecStats.h | 31 +++++++++++-- evmjit/libevmjit/ExecutionEngine.h | 46 ------------------- .../{ExecutionEngine.cpp => JIT.cpp} | 14 +----- evmjit/libevmjit/interface.cpp | 4 +- 10 files changed, 44 insertions(+), 72 deletions(-) delete mode 100644 evmjit/libevmjit/ExecutionEngine.h rename evmjit/libevmjit/{ExecutionEngine.cpp => JIT.cpp} (94%) diff --git a/evmjit/include/evmjit/JIT.h b/evmjit/include/evmjit/JIT.h index 5972bfa88..f4bb9d159 100644 --- a/evmjit/include/evmjit/JIT.h +++ b/evmjit/include/evmjit/JIT.h @@ -6,6 +6,8 @@ namespace dev { namespace evmjit { +enum class ReturnCode; +class ExecutionContext; class JIT { @@ -16,6 +18,8 @@ public: /// In this case the code can be executed without overhead. /// \param _codeHash The Keccak hash of the EVM code. static bool isCodeReady(h256 _codeHash); + + EXPORT static ReturnCode exec(ExecutionContext& _context); }; } diff --git a/evmjit/libevmjit-cpp/JitVM.cpp b/evmjit/libevmjit-cpp/JitVM.cpp index a4eed5793..d40aa2b1c 100644 --- a/evmjit/libevmjit-cpp/JitVM.cpp +++ b/evmjit/libevmjit-cpp/JitVM.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "Utils.h" @@ -53,7 +54,7 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _step) m_data.codeHash = eth2llvm(sha3(_ext.code)); m_context.init(m_data, reinterpret_cast(&_ext)); - auto exitCode = evmjit::ExecutionEngine::run(m_context); + auto exitCode = evmjit::JIT::exec(m_context); switch (exitCode) { case evmjit::ReturnCode::Suicide: diff --git a/evmjit/libevmjit-cpp/JitVM.h b/evmjit/libevmjit-cpp/JitVM.h index 4fccca7df..5bba7b5f0 100644 --- a/evmjit/libevmjit-cpp/JitVM.h +++ b/evmjit/libevmjit-cpp/JitVM.h @@ -2,7 +2,6 @@ #include #include -#include namespace dev { diff --git a/evmjit/libevmjit/CMakeLists.txt b/evmjit/libevmjit/CMakeLists.txt index 67e5f5800..525030285 100644 --- a/evmjit/libevmjit/CMakeLists.txt +++ b/evmjit/libevmjit/CMakeLists.txt @@ -12,12 +12,11 @@ set(SOURCES Endianness.cpp Endianness.h ExecStats.cpp ExecStats.h ExecutionContext.cpp ExecutionContext.h - ExecutionEngine.cpp ExecutionEngine.h Ext.cpp Ext.h GasMeter.cpp GasMeter.h Instruction.cpp Instruction.h interface.cpp interface.h - ${EVMJIT_INCLUDE_DIR}/evmjit/JIT.h + JIT.cpp ${EVMJIT_INCLUDE_DIR}/evmjit/JIT.h Memory.cpp Memory.h Optimizer.cpp Optimizer.h RuntimeManager.cpp RuntimeManager.h diff --git a/evmjit/libevmjit/Cache.cpp b/evmjit/libevmjit/Cache.cpp index e64cb5430..0e19b6276 100644 --- a/evmjit/libevmjit/Cache.cpp +++ b/evmjit/libevmjit/Cache.cpp @@ -10,7 +10,7 @@ #include #include "preprocessor/llvm_includes_end.h" -#include "ExecutionEngine.h" +#include "ExecStats.h" #include "Utils.h" #include "BuildInfo.gen.h" @@ -23,7 +23,7 @@ namespace { CacheMode g_mode; std::unique_ptr g_lastObject; - ExecutionEngineListener* g_listener; + JITListener* g_listener; static const size_t c_versionStampLength = 32; llvm::StringRef getLibVersionStamp() @@ -38,7 +38,7 @@ namespace } } -ObjectCache* Cache::init(CacheMode _mode, ExecutionEngineListener* _listener) +ObjectCache* Cache::init(CacheMode _mode, JITListener* _listener) { g_mode = _mode; g_listener = _listener; diff --git a/evmjit/libevmjit/Cache.h b/evmjit/libevmjit/Cache.h index 61635b8a1..2f152c9f8 100644 --- a/evmjit/libevmjit/Cache.h +++ b/evmjit/libevmjit/Cache.h @@ -14,7 +14,7 @@ namespace dev { namespace evmjit { -class ExecutionEngineListener; +class JITListener; enum class CacheMode { @@ -43,7 +43,7 @@ public: class Cache { public: - static ObjectCache* init(CacheMode _mode, ExecutionEngineListener* _listener); + static ObjectCache* init(CacheMode _mode, JITListener* _listener); static std::unique_ptr getObject(std::string const& id); /// Clears cache storage diff --git a/evmjit/libevmjit/ExecStats.h b/evmjit/libevmjit/ExecStats.h index 3ea77733b..4a5ae00e1 100644 --- a/evmjit/libevmjit/ExecStats.h +++ b/evmjit/libevmjit/ExecStats.h @@ -5,14 +5,39 @@ #include #include -#include "ExecutionEngine.h" - namespace dev { namespace evmjit { -class ExecStats : public ExecutionEngineListener +enum class ExecState +{ + Started, + CacheLoad, + CacheWrite, + Compilation, + Optimization, + CodeGen, + Execution, + Return, + Finished +}; + +class JITListener +{ +public: + JITListener() = default; + JITListener(JITListener const&) = delete; + JITListener& operator=(JITListener) = delete; + virtual ~JITListener() {} + + virtual void executionStarted() {} + virtual void executionEnded() {} + + virtual void stateChanged(ExecState) {} +}; + +class ExecStats : public JITListener { public: using clock = std::chrono::high_resolution_clock; diff --git a/evmjit/libevmjit/ExecutionEngine.h b/evmjit/libevmjit/ExecutionEngine.h deleted file mode 100644 index 04c3218b0..000000000 --- a/evmjit/libevmjit/ExecutionEngine.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include "evmjit/DataTypes.h" - -namespace dev -{ -namespace evmjit -{ -class ExecutionContext; -enum class ReturnCode; - -enum class ExecState -{ - Started, - CacheLoad, - CacheWrite, - Compilation, - Optimization, - CodeGen, - Execution, - Return, - Finished -}; - -class ExecutionEngineListener -{ -public: - ExecutionEngineListener() = default; - ExecutionEngineListener(ExecutionEngineListener const&) = delete; - ExecutionEngineListener& operator=(ExecutionEngineListener) = delete; - virtual ~ExecutionEngineListener() {} - - virtual void executionStarted() {} - virtual void executionEnded() {} - - virtual void stateChanged(ExecState) {} -}; - -class ExecutionEngine -{ -public: - EXPORT static ReturnCode run(ExecutionContext& _context); -}; - -} -} diff --git a/evmjit/libevmjit/ExecutionEngine.cpp b/evmjit/libevmjit/JIT.cpp similarity index 94% rename from evmjit/libevmjit/ExecutionEngine.cpp rename to evmjit/libevmjit/JIT.cpp index 79ae1315c..6fc44e5eb 100644 --- a/evmjit/libevmjit/ExecutionEngine.cpp +++ b/evmjit/libevmjit/JIT.cpp @@ -1,17 +1,8 @@ -#include "ExecutionEngine.h" - -#include -#include -#include -#include -#include -#include +#include "evmjit/JIT.h" #include "preprocessor/llvm_includes_start.h" #include #include -#include -#include #include #include #include @@ -20,7 +11,6 @@ #include "preprocessor/llvm_includes_end.h" #include "ExecutionContext.h" -#include "evmjit/JIT.h" #include "Compiler.h" #include "Optimizer.h" #include "Cache.h" @@ -161,7 +151,7 @@ bool JIT::isCodeReady(h256 _codeHash) return JITImpl::instance().codeMap.count(_codeHash) != 0; } -ReturnCode ExecutionEngine::run(ExecutionContext& _context) +ReturnCode JIT::exec(ExecutionContext& _context) { static auto s_ee = init(); diff --git a/evmjit/libevmjit/interface.cpp b/evmjit/libevmjit/interface.cpp index 4aef5995f..34491e772 100644 --- a/evmjit/libevmjit/interface.cpp +++ b/evmjit/libevmjit/interface.cpp @@ -1,4 +1,4 @@ -#include "ExecutionEngine.h" +#include "evmjit/JIT.h" #include "ExecutionContext.h" extern "C" @@ -23,7 +23,7 @@ EXPORT int evmjit_run(ExecutionContext* _context) noexcept { try { - auto returnCode = ExecutionEngine::run(*_context); + auto returnCode = JIT::exec(*_context); return static_cast(returnCode); } catch(...) From b8a66c7f3e34c8bcdaa757a213bb75bdcc63c711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 18 May 2015 11:35:05 +0200 Subject: [PATCH 029/290] JIT implementation cleanups. --- evmjit/include/evmjit/JIT.h | 2 +- evmjit/libevmjit/JIT.cpp | 80 ++++++++++++++++++------------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/evmjit/include/evmjit/JIT.h b/evmjit/include/evmjit/JIT.h index f4bb9d159..58c19b426 100644 --- a/evmjit/include/evmjit/JIT.h +++ b/evmjit/include/evmjit/JIT.h @@ -17,7 +17,7 @@ public: /// Returns `true` if the EVM code has been compiled and loaded into memory. /// In this case the code can be executed without overhead. /// \param _codeHash The Keccak hash of the EVM code. - static bool isCodeReady(h256 _codeHash); + static bool isCodeReady(h256 const& _codeHash); EXPORT static ReturnCode exec(ExecutionContext& _context); }; diff --git a/evmjit/libevmjit/JIT.cpp b/evmjit/libevmjit/JIT.cpp index 6fc44e5eb..c4ce24ee2 100644 --- a/evmjit/libevmjit/JIT.cpp +++ b/evmjit/libevmjit/JIT.cpp @@ -26,7 +26,7 @@ using namespace eth::jit; namespace { -using EntryFuncPtr = ReturnCode(*)(ExecutionContext*); +using ExecFunc = ReturnCode(*)(ExecutionContext*); std::string hash2str(i256 const& _hash) { @@ -78,10 +78,28 @@ void parseOptions() cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler"); } -std::unique_ptr init() +class JITImpl { - /// ExecutionEngine is created only once + std::unique_ptr m_engine; + std::unordered_map m_codeMap; +public: + static JITImpl& instance() + { + static JITImpl s_instance; + return s_instance; + } + + JITImpl(); + + llvm::ExecutionEngine& engine() { return *m_engine; } + + ExecFunc getExecFunc(h256 const& _codeHash) const; + void mapExecFunc(h256 _codeHash, ExecFunc _funcAddr); +}; + +JITImpl::JITImpl() +{ parseOptions(); bool preloadCache = g_cache == CacheMode::preload; @@ -103,57 +121,39 @@ std::unique_ptr init() builder.setEngineKind(llvm::EngineKind::JIT); builder.setOptLevel(g_optimize ? llvm::CodeGenOpt::Default : llvm::CodeGenOpt::None); - auto ee = std::unique_ptr{builder.create()}; + m_engine.reset(builder.create()); // TODO: Update cache listener - ee->setObjectCache(Cache::init(g_cache, nullptr)); + m_engine->setObjectCache(Cache::init(g_cache, nullptr)); // FIXME: Disabled during API changes //if (preloadCache) - // Cache::preload(*ee, funcCache); - - return ee; + // Cache::preload(*m_engine, funcCache); } -class JITImpl -{ -public: - std::unordered_map codeMap; - - static JITImpl& instance() - { - static JITImpl s_instance; - return s_instance; - } - - static void* getCode(h256 _codeHash); - static void mapCode(h256 _codeHash, void* _funcAddr); -}; - -void* JITImpl::getCode(h256 _codeHash) +ExecFunc JITImpl::getExecFunc(h256 const& _codeHash) const { - auto& codeMap = JITImpl::instance().codeMap; - auto it = codeMap.find(_codeHash); - if (it != codeMap.end()) + auto it = m_codeMap.find(_codeHash); + if (it != m_codeMap.end()) return it->second; return nullptr; } -void JITImpl::mapCode(h256 _codeHash, void* _funcAddr) +void JITImpl::mapExecFunc(h256 _codeHash, ExecFunc _funcAddr) { - JITImpl::instance().codeMap.insert(std::make_pair(_codeHash, _funcAddr)); + m_codeMap.emplace(std::move(_codeHash), _funcAddr); } } // anonymous namespace -bool JIT::isCodeReady(h256 _codeHash) +bool JIT::isCodeReady(h256 const& _codeHash) { - return JITImpl::instance().codeMap.count(_codeHash) != 0; + return JITImpl::instance().getExecFunc(_codeHash) != nullptr; } ReturnCode JIT::exec(ExecutionContext& _context) { - static auto s_ee = init(); + auto& jit = JITImpl::instance(); std::unique_ptr listener{new ExecStats}; listener->stateChanged(ExecState::Started); @@ -167,8 +167,8 @@ ReturnCode JIT::exec(ExecutionContext& _context) auto mainFuncName = hash2str(codeHash); // TODO: Remove cast - auto entryFuncPtr = (EntryFuncPtr) JITImpl::getCode(codeHash); - if (!entryFuncPtr) + auto execFunc = jit.getExecFunc(codeHash); + if (!execFunc) { auto module = Cache::getObject(mainFuncName); if (!module) @@ -188,20 +188,20 @@ ReturnCode JIT::exec(ExecutionContext& _context) if (g_dump) module->dump(); - s_ee->addModule(std::move(module)); + jit.engine().addModule(std::move(module)); listener->stateChanged(ExecState::CodeGen); - entryFuncPtr = (EntryFuncPtr)s_ee->getFunctionAddress(mainFuncName); - if (!CHECK(entryFuncPtr)) + execFunc = (ExecFunc)jit.engine().getFunctionAddress(mainFuncName); + if (!CHECK(execFunc)) return ReturnCode::LLVMLinkError; - JITImpl::mapCode(codeHash, (void*)entryFuncPtr); // FIXME: Remove cast + jit.mapExecFunc(codeHash, execFunc); } listener->stateChanged(ExecState::Execution); - auto returnCode = entryFuncPtr(&_context); + auto returnCode = execFunc(&_context); listener->stateChanged(ExecState::Return); if (returnCode == ReturnCode::Return) - _context.returnData = _context.getReturnData(); // Save reference to return data + _context.returnData = _context.getReturnData(); // Save reference to return data listener->stateChanged(ExecState::Finished); From 5046dd4bb0e5ad2611ede4f7a1ed8d8cfb815ff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 18 May 2015 13:59:16 +0200 Subject: [PATCH 030/290] EVM JIT C++ interface in one header. --- evmjit/include/evmjit/DataTypes.h | 68 ----------- evmjit/include/evmjit/JIT.h | 160 +++++++++++++++++++++++++- evmjit/libevmjit-cpp/Env.cpp | 1 - evmjit/libevmjit-cpp/JitVM.cpp | 1 - evmjit/libevmjit-cpp/JitVM.h | 2 +- evmjit/libevmjit-cpp/Utils.h | 2 +- evmjit/libevmjit/Arith256.cpp | 1 - evmjit/libevmjit/BasicBlock.h | 6 +- evmjit/libevmjit/CMakeLists.txt | 6 +- evmjit/libevmjit/Common.h | 8 +- evmjit/libevmjit/Compiler.h | 1 - evmjit/libevmjit/ExecutionContext.cpp | 33 ------ evmjit/libevmjit/ExecutionContext.h | 110 ------------------ evmjit/libevmjit/Instruction.h | 2 +- evmjit/libevmjit/JIT.cpp | 25 +++- evmjit/libevmjit/RuntimeManager.h | 1 - evmjit/libevmjit/Type.h | 2 +- evmjit/libevmjit/interface.cpp | 1 - 18 files changed, 192 insertions(+), 238 deletions(-) delete mode 100644 evmjit/include/evmjit/DataTypes.h delete mode 100644 evmjit/libevmjit/ExecutionContext.cpp delete mode 100644 evmjit/libevmjit/ExecutionContext.h diff --git a/evmjit/include/evmjit/DataTypes.h b/evmjit/include/evmjit/DataTypes.h deleted file mode 100644 index 6f06a81d6..000000000 --- a/evmjit/include/evmjit/DataTypes.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#include -#include - -#ifdef _MSC_VER -#define EXPORT __declspec(dllexport) -#define _ALLOW_KEYWORD_MACROS -#define noexcept throw() -#else -#define EXPORT -#endif - -namespace dev -{ -namespace evmjit -{ - -using byte = uint8_t; -using bytes_ref = std::tuple; -using code_iterator = byte const*; - -struct h256 -{ - uint64_t words[4]; -}; - -inline bool operator==(h256 _h1, h256 _h2) -{ - return _h1.words[0] == _h2.words[0] && - _h1.words[1] == _h2.words[1] && - _h1.words[2] == _h2.words[2] && - _h1.words[3] == _h2.words[3]; -} - -/// Representation of 256-bit value binary compatible with LLVM i256 -struct i256 -{ - uint64_t a = 0; - uint64_t b = 0; - uint64_t c = 0; - uint64_t d = 0; - - i256() = default; - i256(h256 _h) - { - a = _h.words[0]; - b = _h.words[1]; - c = _h.words[2]; - d = _h.words[3]; - } -}; - -} -} - -namespace std -{ -template<> struct hash -{ - size_t operator()(dev::evmjit::h256 const& _h) const - { - /// This implementation expects the argument to be a full 256-bit Keccak hash. - /// It does nothing more than returning a slice of the input hash. - return static_cast(_h.words[0]); - }; -}; -} diff --git a/evmjit/include/evmjit/JIT.h b/evmjit/include/evmjit/JIT.h index 58c19b426..cbf0e6e78 100644 --- a/evmjit/include/evmjit/JIT.h +++ b/evmjit/include/evmjit/JIT.h @@ -1,13 +1,153 @@ #pragma once -#include "evmjit/DataTypes.h" +#include +#include + +#ifdef _MSC_VER +#define EXPORT __declspec(dllexport) +#define _ALLOW_KEYWORD_MACROS +#define noexcept throw() +#else +#define EXPORT +#endif namespace dev { namespace evmjit { -enum class ReturnCode; -class ExecutionContext; + +using byte = uint8_t; +using bytes_ref = std::tuple; + +struct h256 +{ + uint64_t words[4]; +}; + +inline bool operator==(h256 _h1, h256 _h2) +{ + return _h1.words[0] == _h2.words[0] && + _h1.words[1] == _h2.words[1] && + _h1.words[2] == _h2.words[2] && + _h1.words[3] == _h2.words[3]; +} + +/// Representation of 256-bit value binary compatible with LLVM i256 +struct i256 +{ + uint64_t a = 0; + uint64_t b = 0; + uint64_t c = 0; + uint64_t d = 0; + + i256() = default; + i256(h256 _h) + { + a = _h.words[0]; + b = _h.words[1]; + c = _h.words[2]; + d = _h.words[3]; + } +}; + +struct RuntimeData +{ + enum Index + { + Gas, + GasPrice, + CallData, + CallDataSize, + Address, + Caller, + Origin, + CallValue, + CoinBase, + Difficulty, + GasLimit, + Number, + Timestamp, + Code, + CodeSize, + + SuicideDestAddress = Address, ///< Suicide balance destination address + ReturnData = CallData, ///< Return data pointer (set only in case of RETURN) + ReturnDataSize = CallDataSize, ///< Return data size (set only in case of RETURN) + }; + + int64_t gas = 0; + int64_t gasPrice = 0; + byte const* callData = nullptr; + uint64_t callDataSize = 0; + i256 address; + i256 caller; + i256 origin; + i256 callValue; + i256 coinBase; + i256 difficulty; + i256 gasLimit; + uint64_t number = 0; + int64_t timestamp = 0; + byte const* code = nullptr; + uint64_t codeSize = 0; + h256 codeHash; +}; + +/// VM Environment (ExtVM) opaque type +struct Env; + +enum class ReturnCode +{ + // Success codes + Stop = 0, + Return = 1, + Suicide = 2, + + // Standard error codes + OutOfGas = -1, + StackUnderflow = -2, + BadJumpDestination = -3, + BadInstruction = -4, + Rejected = -5, ///< Input data (code, gas, block info, etc.) does not meet JIT requirement and execution request has been rejected + + // Internal error codes + LLVMConfigError = -101, + LLVMCompileError = -102, + LLVMLinkError = -103, + + UnexpectedException = -111, + + LinkerWorkaround = -299, +}; + +class ExecutionContext +{ +public: + ExecutionContext() = default; + ExecutionContext(RuntimeData& _data, Env* _env) { init(_data, _env); } + ExecutionContext(ExecutionContext const&) = delete; + ExecutionContext& operator=(ExecutionContext const&) = delete; + EXPORT ~ExecutionContext(); + + void init(RuntimeData& _data, Env* _env) { m_data = &_data; m_env = _env; } + + byte const* code() const { return m_data->code; } + uint64_t codeSize() const { return m_data->codeSize; } + h256 const& codeHash() const { return m_data->codeHash; } + + bytes_ref getReturnData() const; + +private: + RuntimeData* m_data = nullptr; ///< Pointer to data. Expected by compiled contract. + Env* m_env = nullptr; ///< Pointer to environment proxy. Expected by compiled contract. + byte* m_memData = nullptr; + uint64_t m_memSize = 0; + uint64_t m_memCap = 0; + +public: + /// Reference to returned data (RETURN opcode used) + bytes_ref returnData; +}; class JIT { @@ -24,3 +164,17 @@ public: } } + +namespace std +{ +template<> struct hash +{ + size_t operator()(dev::evmjit::h256 const& _h) const + { + /// This implementation expects the argument to be a full 256-bit Keccak hash. + /// It does nothing more than returning a slice of the input hash. + return static_cast(_h.words[0]); + }; +}; +} + diff --git a/evmjit/libevmjit-cpp/Env.cpp b/evmjit/libevmjit-cpp/Env.cpp index a5a60f48c..366f5704a 100644 --- a/evmjit/libevmjit-cpp/Env.cpp +++ b/evmjit/libevmjit-cpp/Env.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include "Utils.h" diff --git a/evmjit/libevmjit-cpp/JitVM.cpp b/evmjit/libevmjit-cpp/JitVM.cpp index d40aa2b1c..e9559026a 100644 --- a/evmjit/libevmjit-cpp/JitVM.cpp +++ b/evmjit/libevmjit-cpp/JitVM.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include "Utils.h" diff --git a/evmjit/libevmjit-cpp/JitVM.h b/evmjit/libevmjit-cpp/JitVM.h index 5bba7b5f0..fdc87248a 100644 --- a/evmjit/libevmjit-cpp/JitVM.h +++ b/evmjit/libevmjit-cpp/JitVM.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include namespace dev { diff --git a/evmjit/libevmjit-cpp/Utils.h b/evmjit/libevmjit-cpp/Utils.h index f9b9b2ef4..d52861fcc 100644 --- a/evmjit/libevmjit-cpp/Utils.h +++ b/evmjit/libevmjit-cpp/Utils.h @@ -1,6 +1,6 @@ #pragma once -#include +#include namespace dev { diff --git a/evmjit/libevmjit/Arith256.cpp b/evmjit/libevmjit/Arith256.cpp index 9d6494730..6c1f8f160 100644 --- a/evmjit/libevmjit/Arith256.cpp +++ b/evmjit/libevmjit/Arith256.cpp @@ -8,7 +8,6 @@ #include #include "preprocessor/llvm_includes_end.h" -#include "evmjit/DataTypes.h" #include "Type.h" #include "Endianness.h" #include "Utils.h" diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index 9960a0d1c..321499196 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -2,8 +2,7 @@ #include - -#include "evmjit/DataTypes.h" +#include "Common.h" #include "Stack.h" namespace dev @@ -12,9 +11,8 @@ namespace eth { namespace jit { - -using instr_idx = uint64_t; using namespace evmjit; +using instr_idx = uint64_t; class BasicBlock { diff --git a/evmjit/libevmjit/CMakeLists.txt b/evmjit/libevmjit/CMakeLists.txt index 525030285..80108e15b 100644 --- a/evmjit/libevmjit/CMakeLists.txt +++ b/evmjit/libevmjit/CMakeLists.txt @@ -1,22 +1,20 @@ set(TARGET_NAME evmjit) set(SOURCES + JIT.cpp ${EVMJIT_INCLUDE_DIR}/evmjit/JIT.h Arith256.cpp Arith256.h Array.cpp Array.h BasicBlock.cpp BasicBlock.h Cache.cpp Cache.h - Common.h + Common.h Compiler.cpp Compiler.h CompilerHelper.cpp CompilerHelper.h - ${EVMJIT_INCLUDE_DIR}/evmjit/DataTypes.h Endianness.cpp Endianness.h ExecStats.cpp ExecStats.h - ExecutionContext.cpp ExecutionContext.h Ext.cpp Ext.h GasMeter.cpp GasMeter.h Instruction.cpp Instruction.h interface.cpp interface.h - JIT.cpp ${EVMJIT_INCLUDE_DIR}/evmjit/JIT.h Memory.cpp Memory.h Optimizer.cpp Optimizer.h RuntimeManager.cpp RuntimeManager.h diff --git a/evmjit/libevmjit/Common.h b/evmjit/libevmjit/Common.h index 5067f4fb1..4a6d7b4f3 100644 --- a/evmjit/libevmjit/Common.h +++ b/evmjit/libevmjit/Common.h @@ -1,18 +1,16 @@ #pragma once -#include #include namespace dev { -namespace eth +namespace evmjit { -namespace jit{ - +using byte = uint8_t; +using code_iterator = byte const*; #define UNTESTED assert(false) } } -} diff --git a/evmjit/libevmjit/Compiler.h b/evmjit/libevmjit/Compiler.h index 9b9fe7160..0b31ae0f2 100644 --- a/evmjit/libevmjit/Compiler.h +++ b/evmjit/libevmjit/Compiler.h @@ -1,6 +1,5 @@ #pragma once -#include "Common.h" #include "BasicBlock.h" namespace dev diff --git a/evmjit/libevmjit/ExecutionContext.cpp b/evmjit/libevmjit/ExecutionContext.cpp deleted file mode 100644 index fab6fad87..000000000 --- a/evmjit/libevmjit/ExecutionContext.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "ExecutionContext.h" -#include - -namespace dev -{ -namespace evmjit -{ - -extern "C" void ext_free(void* _data) noexcept; - -ExecutionContext::~ExecutionContext() -{ - if (m_memData) - ext_free(m_memData); // Use helper free to check memory leaks -} - -bytes_ref ExecutionContext::getReturnData() const -{ - auto data = m_data->callData; - auto size = static_cast(m_data->callDataSize); - - if (data < m_memData || data >= m_memData + m_memSize || size == 0) - { - assert(size == 0); // data can be an invalid pointer only if size is 0 - m_data->callData = nullptr; - return {}; - } - - return bytes_ref{data, size}; -} - -} -} diff --git a/evmjit/libevmjit/ExecutionContext.h b/evmjit/libevmjit/ExecutionContext.h deleted file mode 100644 index fd7e8f11a..000000000 --- a/evmjit/libevmjit/ExecutionContext.h +++ /dev/null @@ -1,110 +0,0 @@ -#pragma once - -#include "evmjit/DataTypes.h" - -namespace dev -{ -namespace evmjit -{ - -struct RuntimeData -{ - enum Index - { - Gas, - GasPrice, - CallData, - CallDataSize, - Address, - Caller, - Origin, - CallValue, - CoinBase, - Difficulty, - GasLimit, - Number, - Timestamp, - Code, - CodeSize, - - SuicideDestAddress = Address, ///< Suicide balance destination address - ReturnData = CallData, ///< Return data pointer (set only in case of RETURN) - ReturnDataSize = CallDataSize, ///< Return data size (set only in case of RETURN) - }; - - int64_t gas = 0; - int64_t gasPrice = 0; - byte const* callData = nullptr; - uint64_t callDataSize = 0; - i256 address; - i256 caller; - i256 origin; - i256 callValue; - i256 coinBase; - i256 difficulty; - i256 gasLimit; - uint64_t number = 0; - int64_t timestamp = 0; - byte const* code = nullptr; - uint64_t codeSize = 0; - h256 codeHash; -}; - -/// VM Environment (ExtVM) opaque type -struct Env; - -enum class ReturnCode -{ - // Success codes - Stop = 0, - Return = 1, - Suicide = 2, - - // Standard error codes - OutOfGas = -1, - StackUnderflow = -2, - BadJumpDestination = -3, - BadInstruction = -4, - Rejected = -5, ///< Input data (code, gas, block info, etc.) does not meet JIT requirement and execution request has been rejected - - // Internal error codes - LLVMConfigError = -101, - LLVMCompileError = -102, - LLVMLinkError = -103, - - UnexpectedException = -111, - - LinkerWorkaround = -299, -}; - -class ExecutionContext -{ -public: - ExecutionContext() = default; - ExecutionContext(RuntimeData& _data, Env* _env) { init(_data, _env); } - ExecutionContext(ExecutionContext const&) = delete; - ExecutionContext& operator=(ExecutionContext const&) = delete; - EXPORT ~ExecutionContext(); - - void init(RuntimeData& _data, Env* _env) { m_data = &_data; m_env = _env; } - - byte const* code() const { return m_data->code; } - uint64_t codeSize() const { return m_data->codeSize; } - h256 const& codeHash() const { return m_data->codeHash; } - - bytes_ref getReturnData() const; - -private: - RuntimeData* m_data = nullptr; ///< Pointer to data. Expected by compiled contract. - Env* m_env = nullptr; ///< Pointer to environment proxy. Expected by compiled contract. - byte* m_memData = nullptr; - uint64_t m_memSize = 0; - uint64_t m_memCap = 0; - -public: - /// Reference to returned data (RETURN opcode used) - bytes_ref returnData; -}; - -} -} diff --git a/evmjit/libevmjit/Instruction.h b/evmjit/libevmjit/Instruction.h index 2da3c4c65..89add0958 100644 --- a/evmjit/libevmjit/Instruction.h +++ b/evmjit/libevmjit/Instruction.h @@ -1,6 +1,6 @@ #pragma once -#include "evmjit/DataTypes.h" +#include "Common.h" namespace llvm { diff --git a/evmjit/libevmjit/JIT.cpp b/evmjit/libevmjit/JIT.cpp index c4ce24ee2..f8b4d4c00 100644 --- a/evmjit/libevmjit/JIT.cpp +++ b/evmjit/libevmjit/JIT.cpp @@ -10,7 +10,6 @@ #include #include "preprocessor/llvm_includes_end.h" -#include "ExecutionContext.h" #include "Compiler.h" #include "Optimizer.h" #include "Cache.h" @@ -211,5 +210,29 @@ ReturnCode JIT::exec(ExecutionContext& _context) return returnCode; } + +extern "C" void ext_free(void* _data) noexcept; + +ExecutionContext::~ExecutionContext() +{ + if (m_memData) + ext_free(m_memData); // Use helper free to check memory leaks +} + +bytes_ref ExecutionContext::getReturnData() const +{ + auto data = m_data->callData; + auto size = static_cast(m_data->callDataSize); + + if (data < m_memData || data >= m_memData + m_memSize || size == 0) + { + assert(size == 0); // data can be an invalid pointer only if size is 0 + m_data->callData = nullptr; + return {}; + } + + return bytes_ref{data, size}; +} + } } diff --git a/evmjit/libevmjit/RuntimeManager.h b/evmjit/libevmjit/RuntimeManager.h index 088611093..5ce749933 100644 --- a/evmjit/libevmjit/RuntimeManager.h +++ b/evmjit/libevmjit/RuntimeManager.h @@ -1,6 +1,5 @@ #pragma once -#include "ExecutionContext.h" #include "CompilerHelper.h" #include "Type.h" #include "Instruction.h" diff --git a/evmjit/libevmjit/Type.h b/evmjit/libevmjit/Type.h index b1b6d1ad4..b54d101cb 100644 --- a/evmjit/libevmjit/Type.h +++ b/evmjit/libevmjit/Type.h @@ -6,7 +6,7 @@ #include #include "preprocessor/llvm_includes_end.h" // FIXME: LLVM 3.7: check if needed -#include "ExecutionContext.h" // FIXME: crappy dependence +#include "evmjit/JIT.h" // ReturnCode namespace dev { diff --git a/evmjit/libevmjit/interface.cpp b/evmjit/libevmjit/interface.cpp index 34491e772..7136f6798 100644 --- a/evmjit/libevmjit/interface.cpp +++ b/evmjit/libevmjit/interface.cpp @@ -1,5 +1,4 @@ #include "evmjit/JIT.h" -#include "ExecutionContext.h" extern "C" { From 394676a1db0d35708bf45f48ef8dac075bb342e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 18 May 2015 14:35:32 +0200 Subject: [PATCH 031/290] Better eth <-> jit integer conversions. --- evmjit/include/evmjit/JIT.h | 14 +++----------- evmjit/libevmjit-cpp/Env.cpp | 16 ++++++++-------- evmjit/libevmjit-cpp/JitVM.cpp | 18 +++++++++--------- evmjit/libevmjit-cpp/Utils.h | 27 ++++++++++++++------------- libevm/SmartVM.cpp | 2 +- 5 files changed, 35 insertions(+), 42 deletions(-) diff --git a/evmjit/include/evmjit/JIT.h b/evmjit/include/evmjit/JIT.h index cbf0e6e78..c12637a25 100644 --- a/evmjit/include/evmjit/JIT.h +++ b/evmjit/include/evmjit/JIT.h @@ -35,21 +35,13 @@ inline bool operator==(h256 _h1, h256 _h2) /// Representation of 256-bit value binary compatible with LLVM i256 struct i256 { - uint64_t a = 0; - uint64_t b = 0; - uint64_t c = 0; - uint64_t d = 0; + uint64_t words[4] = {0,}; i256() = default; - i256(h256 _h) - { - a = _h.words[0]; - b = _h.words[1]; - c = _h.words[2]; - d = _h.words[3]; - } + i256(h256 _h) { *this = *reinterpret_cast(&_h); } }; +// TODO: Merge with ExecutionContext struct RuntimeData { enum Index diff --git a/evmjit/libevmjit-cpp/Env.cpp b/evmjit/libevmjit-cpp/Env.cpp index 366f5704a..b2382b8ba 100644 --- a/evmjit/libevmjit-cpp/Env.cpp +++ b/evmjit/libevmjit-cpp/Env.cpp @@ -20,15 +20,15 @@ extern "C" EXPORT void env_sload(ExtVMFace* _env, i256* _index, i256* o_value) { - auto index = llvm2eth(*_index); + auto index = jit2eth(*_index); auto value = _env->store(index); // Interface uses native endianness - *o_value = eth2llvm(value); + *o_value = eth2jit(value); } EXPORT void env_sstore(ExtVMFace* _env, i256* _index, i256* _value) { - auto index = llvm2eth(*_index); - auto value = llvm2eth(*_value); + auto index = jit2eth(*_index); + auto value = jit2eth(*_value); if (value == 0 && _env->store(index) != 0) // If delete _env->sub.refunds += c_sstoreRefundGas; // Increase refund counter @@ -39,17 +39,17 @@ extern "C" EXPORT void env_balance(ExtVMFace* _env, h256* _address, i256* o_value) { auto u = _env->balance(right160(*_address)); - *o_value = eth2llvm(u); + *o_value = eth2jit(u); } EXPORT void env_blockhash(ExtVMFace* _env, i256* _number, h256* o_hash) { - *o_hash = _env->blockhash(llvm2eth(*_number)); + *o_hash = _env->blockhash(jit2eth(*_number)); } EXPORT void env_create(ExtVMFace* _env, int64_t* io_gas, i256* _endowment, byte* _initBeg, uint64_t _initSize, h256* o_address) { - auto endowment = llvm2eth(*_endowment); + auto endowment = jit2eth(*_endowment); if (_env->balance(_env->myAddress) >= endowment && _env->depth < 1024) { u256 gas = *io_gas; @@ -63,7 +63,7 @@ extern "C" EXPORT bool env_call(ExtVMFace* _env, int64_t* io_gas, int64_t _callGas, h256* _receiveAddress, i256* _value, byte* _inBeg, uint64_t _inSize, byte* _outBeg, uint64_t _outSize, h256* _codeAddress) { - auto value = llvm2eth(*_value); + auto value = jit2eth(*_value); auto receiveAddress = right160(*_receiveAddress); auto codeAddress = right160(*_codeAddress); const auto isCall = receiveAddress == codeAddress; // OPT: The same address pointer can be used if not CODECALL diff --git a/evmjit/libevmjit-cpp/JitVM.cpp b/evmjit/libevmjit-cpp/JitVM.cpp index e9559026a..3bdbc37b8 100644 --- a/evmjit/libevmjit-cpp/JitVM.cpp +++ b/evmjit/libevmjit-cpp/JitVM.cpp @@ -39,25 +39,25 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _step) m_data.gasPrice = static_cast(_ext.gasPrice); m_data.callData = _ext.data.data(); m_data.callDataSize = _ext.data.size(); - m_data.address = eth2llvm(fromAddress(_ext.myAddress)); - m_data.caller = eth2llvm(fromAddress(_ext.caller)); - m_data.origin = eth2llvm(fromAddress(_ext.origin)); - m_data.callValue = eth2llvm(_ext.value); - m_data.coinBase = eth2llvm(fromAddress(_ext.currentBlock.coinbaseAddress)); - m_data.difficulty = eth2llvm(_ext.currentBlock.difficulty); - m_data.gasLimit = eth2llvm(_ext.currentBlock.gasLimit); + m_data.address = eth2jit(fromAddress(_ext.myAddress)); + m_data.caller = eth2jit(fromAddress(_ext.caller)); + m_data.origin = eth2jit(fromAddress(_ext.origin)); + m_data.callValue = eth2jit(_ext.value); + m_data.coinBase = eth2jit(fromAddress(_ext.currentBlock.coinbaseAddress)); + m_data.difficulty = eth2jit(_ext.currentBlock.difficulty); + m_data.gasLimit = eth2jit(_ext.currentBlock.gasLimit); m_data.number = static_cast(_ext.currentBlock.number); m_data.timestamp = static_cast(_ext.currentBlock.timestamp); m_data.code = _ext.code.data(); m_data.codeSize = _ext.code.size(); - m_data.codeHash = eth2llvm(sha3(_ext.code)); + m_data.codeHash = eth2jit(sha3(_ext.code)); m_context.init(m_data, reinterpret_cast(&_ext)); auto exitCode = evmjit::JIT::exec(m_context); switch (exitCode) { case evmjit::ReturnCode::Suicide: - _ext.suicide(right160(llvm2eth(m_data.address))); + _ext.suicide(right160(jit2eth(m_data.address))); break; case evmjit::ReturnCode::BadJumpDestination: diff --git a/evmjit/libevmjit-cpp/Utils.h b/evmjit/libevmjit-cpp/Utils.h index d52861fcc..ebb6ad97d 100644 --- a/evmjit/libevmjit-cpp/Utils.h +++ b/evmjit/libevmjit-cpp/Utils.h @@ -7,34 +7,35 @@ namespace dev namespace eth { -inline u256 llvm2eth(evmjit::i256 _i) +/// Converts EVM JIT representation of 256-bit integer to eth type dev::u256. +inline u256 jit2eth(evmjit::i256 _i) { - u256 u = 0; - u |= _i.d; + u256 u = _i.words[3]; u <<= 64; - u |= _i.c; + u |= _i.words[2]; u <<= 64; - u |= _i.b; + u |= _i.words[1]; u <<= 64; - u |= _i.a; + u |= _i.words[0]; return u; } -inline evmjit::i256 eth2llvm(u256 _u) +/// Converts eth type dev::u256 to EVM JIT representation of 256-bit integer. +inline evmjit::i256 eth2jit(u256 _u) { evmjit::i256 i; - u256 mask = 0xFFFFFFFFFFFFFFFF; - i.a = static_cast(_u & mask); + i.words[0] = static_cast(_u); _u >>= 64; - i.b = static_cast(_u & mask); + i.words[1] = static_cast(_u); _u >>= 64; - i.c = static_cast(_u & mask); + i.words[2] = static_cast(_u); _u >>= 64; - i.d = static_cast(_u & mask); + i.words[3] = static_cast(_u); return i; } -inline evmjit::h256 eth2llvm(h256 _u) +/// Converts eth type dev::h256 to EVM JIT representation of 256-bit hash value. +inline evmjit::h256 eth2jit(h256 _u) { /// Just directly copies memory return *(evmjit::h256*)&_u; diff --git a/libevm/SmartVM.cpp b/libevm/SmartVM.cpp index 4f759a745..6a2ff43c6 100644 --- a/libevm/SmartVM.cpp +++ b/libevm/SmartVM.cpp @@ -47,7 +47,7 @@ bytesConstRef SmartVM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _step auto vmKind = VMKind::Interpreter; // default VM // Jitted EVM code already in memory? - if (evmjit::JIT::isCodeReady(eth2llvm(codeHash))) + if (evmjit::JIT::isCodeReady(eth2jit(codeHash))) { cnote << "Jitted"; vmKind = VMKind::JIT; From 83d27ed2e29916da729fad7f8d6c6d16f9be3015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 18 May 2015 14:44:47 +0200 Subject: [PATCH 032/290] Remove evmcc tool. --- evmjit/CMakeLists.txt | 4 - evmjit/evmcc/CMakeLists.txt | 18 ---- evmjit/evmcc/evmcc.cpp | 210 ------------------------------------ 3 files changed, 232 deletions(-) delete mode 100644 evmjit/evmcc/CMakeLists.txt delete mode 100644 evmjit/evmcc/evmcc.cpp diff --git a/evmjit/CMakeLists.txt b/evmjit/CMakeLists.txt index dc7c50017..e1db7da06 100644 --- a/evmjit/CMakeLists.txt +++ b/evmjit/CMakeLists.txt @@ -40,7 +40,3 @@ add_subdirectory(libevmjit) if(EVMJIT_CPP) add_subdirectory(libevmjit-cpp) endif() - -if(EVMJIT_TOOLS) - add_subdirectory(evmcc) -endif() diff --git a/evmjit/evmcc/CMakeLists.txt b/evmjit/evmcc/CMakeLists.txt deleted file mode 100644 index 4ffbf5fb5..000000000 --- a/evmjit/evmcc/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -set(TARGET_NAME evmcc) - -set(SOURCES - evmcc.cpp -) -source_group("" FILES ${SOURCES}) - -add_executable(${TARGET_NAME} ${SOURCES}) -set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "tools") - -include_directories(../..) -include_directories(${LLVM_INCLUDE_DIRS}) -include_directories(${Boost_INCLUDE_DIRS}) - -target_link_libraries(${TARGET_NAME} ethereum) -target_link_libraries(${TARGET_NAME} ${Boost_PROGRAM_OPTIONS_LIBRARIES}) - -install(TARGETS ${TARGET_NAME} DESTINATION bin ) \ No newline at end of file diff --git a/evmjit/evmcc/evmcc.cpp b/evmjit/evmcc/evmcc.cpp deleted file mode 100644 index e86f948f2..000000000 --- a/evmjit/evmcc/evmcc.cpp +++ /dev/null @@ -1,210 +0,0 @@ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -void parseProgramOptions(int _argc, char** _argv, boost::program_options::variables_map& _varMap) -{ - namespace opt = boost::program_options; - - opt::options_description explicitOpts("Allowed options"); - explicitOpts.add_options() - ("help,h", "show usage information") - ("compile,c", "compile the code to LLVM IR") - ("interpret,i", "compile the code to LLVM IR and execute") - ("gas,g", opt::value(), "set initial gas for execution") - ("disassemble,d", "dissassemble the code") - ("dump-cfg", "dump control flow graph to graphviz file") - ("dont-optimize", "turn off optimizations") - ("optimize-stack", "optimize stack use between basic blocks (default: on)") - ("rewrite-switch", "rewrite LLVM switch to branches (default: on)") - ("output-ll", opt::value(), "dump generated LLVM IR to file") - ("output-bc", opt::value(), "dump generated LLVM bitcode to file") - ("show-logs", "output LOG statements to stderr") - ("verbose,V", "enable verbose output"); - - opt::options_description implicitOpts("Input files"); - implicitOpts.add_options() - ("input-file", opt::value(), "input file"); - - opt::options_description allOpts(""); - allOpts.add(explicitOpts).add(implicitOpts); - - opt::positional_options_description inputOpts; - inputOpts.add("input-file", 1); - - const char* errorMsg = nullptr; - try - { - auto parser = opt::command_line_parser(_argc, _argv).options(allOpts).positional(inputOpts); - opt::store(parser.run(), _varMap); - opt::notify(_varMap); - } - catch (boost::program_options::error& err) - { - errorMsg = err.what(); - } - - if (!errorMsg && _varMap.count("input-file") == 0) - errorMsg = "missing input file name"; - - if (_varMap.count("disassemble") == 0 - && _varMap.count("compile") == 0 - && _varMap.count("interpret") == 0) - { - errorMsg = "at least one of -c, -i, -d is required"; - } - - if (errorMsg || _varMap.count("help")) - { - if (errorMsg) - std::cerr << "Error: " << errorMsg << std::endl; - - std::cout << "Usage: " << _argv[0] << " input-file " << std::endl - << explicitOpts << std::endl; - std::exit(errorMsg ? 1 : 0); - } -} - -int main(int argc, char** argv) -{ - llvm::sys::PrintStackTraceOnErrorSignal(); - llvm::PrettyStackTraceProgram X(argc, argv); - - boost::program_options::variables_map options; - parseProgramOptions(argc, argv, options); - - auto inputFile = options["input-file"].as(); - std::ifstream ifs(inputFile); - if (!ifs.is_open()) - { - std::cerr << "cannot open input file " << inputFile << std::endl; - exit(1); - } - - std::string src((std::istreambuf_iterator(ifs)), - (std::istreambuf_iterator())); - - boost::algorithm::trim(src); - - using namespace dev; - - bytes bytecode = fromHex(src); - - if (options.count("disassemble")) - { - std::string assembly = eth::disassemble(bytecode); - std::cout << assembly << std::endl; - } - - if (options.count("compile") || options.count("interpret")) - { - size_t initialGas = 10000; - - if (options.count("gas")) - initialGas = options["gas"].as(); - - auto compilationStartTime = std::chrono::high_resolution_clock::now(); - - eth::jit::Compiler::Options compilerOptions; - compilerOptions.dumpCFG = options.count("dump-cfg") > 0; - bool optimize = options.count("dont-optimize") == 0; - compilerOptions.optimizeStack = optimize || options.count("optimize-stack") > 0; - compilerOptions.rewriteSwitchToBranches = optimize || options.count("rewrite-switch") > 0; - - auto compiler = eth::jit::Compiler(compilerOptions); - auto module = compiler.compile(bytecode, "main"); - - auto compilationEndTime = std::chrono::high_resolution_clock::now(); - - module->dump(); - - if (options.count("output-ll")) - { - auto outputFile = options["output-ll"].as(); - std::ofstream ofs(outputFile); - if (!ofs.is_open()) - { - std::cerr << "cannot open output file " << outputFile << std::endl; - exit(1); - } - llvm::raw_os_ostream ros(ofs); - module->print(ros, nullptr); - ofs.close(); - } - - if (options.count("output-bc")) - { - auto outputFile = options["output-bc"].as(); - std::ofstream ofs(outputFile); - if (!ofs.is_open()) - { - std::cerr << "cannot open output file " << outputFile << std::endl; - exit(1); - } - llvm::raw_os_ostream ros(ofs); - llvm::WriteBitcodeToFile(module.get(), ros); - ros.flush(); - ofs.close(); - } - - if (options.count("verbose")) - { - std::cerr << "*** Compilation time: " - << std::chrono::duration_cast(compilationEndTime - compilationStartTime).count() - << std::endl; - } - - if (options.count("interpret")) - { - using namespace eth::jit; - - ExecutionEngine engine; - eth::jit::u256 gas = initialGas; - - // Create random runtime data - RuntimeData data; - data.set(RuntimeData::Gas, gas); - data.set(RuntimeData::Address, (u160)Address(1122334455667788)); - data.set(RuntimeData::Caller, (u160)Address(0xfacefacefaceface)); - data.set(RuntimeData::Origin, (u160)Address(101010101010101010)); - data.set(RuntimeData::CallValue, 0xabcd); - data.set(RuntimeData::CallDataSize, 3); - data.set(RuntimeData::GasPrice, 1003); - data.set(RuntimeData::CoinBase, (u160)Address(101010101010101015)); - data.set(RuntimeData::TimeStamp, 1005); - data.set(RuntimeData::Number, 1006); - data.set(RuntimeData::Difficulty, 16); - data.set(RuntimeData::GasLimit, 1008); - data.set(RuntimeData::CodeSize, bytecode.size()); - data.callData = (uint8_t*)"abc"; - data.code = bytecode.data(); - - // BROKEN: env_* functions must be implemented & RuntimeData struct created - // TODO: Do not compile module again - auto result = engine.run(bytecode, &data, nullptr); - return static_cast(result); - } - } - - return 0; -} From 073284feb05becd81b7f68ea1eeb3d1c6ff75798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 19 May 2015 14:02:32 +0200 Subject: [PATCH 033/290] MSVC fixes. --- evmjit/include/evmjit/JIT.h | 4 ++-- evmjit/libevmjit/Cache.h | 2 ++ evmjit/libevmjit/JIT.cpp | 2 ++ evmjit/libevmjit/RuntimeManager.h | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/evmjit/include/evmjit/JIT.h b/evmjit/include/evmjit/JIT.h index c12637a25..adca983d9 100644 --- a/evmjit/include/evmjit/JIT.h +++ b/evmjit/include/evmjit/JIT.h @@ -35,7 +35,7 @@ inline bool operator==(h256 _h1, h256 _h2) /// Representation of 256-bit value binary compatible with LLVM i256 struct i256 { - uint64_t words[4] = {0,}; + uint64_t words[4]; i256() = default; i256(h256 _h) { *this = *reinterpret_cast(&_h); } @@ -149,7 +149,7 @@ public: /// Returns `true` if the EVM code has been compiled and loaded into memory. /// In this case the code can be executed without overhead. /// \param _codeHash The Keccak hash of the EVM code. - static bool isCodeReady(h256 const& _codeHash); + EXPORT static bool isCodeReady(h256 const& _codeHash); EXPORT static ReturnCode exec(ExecutionContext& _context); }; diff --git a/evmjit/libevmjit/Cache.h b/evmjit/libevmjit/Cache.h index 2f152c9f8..5de4222fc 100644 --- a/evmjit/libevmjit/Cache.h +++ b/evmjit/libevmjit/Cache.h @@ -3,7 +3,9 @@ #include #include +#include "preprocessor/llvm_includes_start.h" #include +#include "preprocessor/llvm_includes_end.h" namespace llvm { diff --git a/evmjit/libevmjit/JIT.cpp b/evmjit/libevmjit/JIT.cpp index f8b4d4c00..6a9b7f932 100644 --- a/evmjit/libevmjit/JIT.cpp +++ b/evmjit/libevmjit/JIT.cpp @@ -1,5 +1,7 @@ #include "evmjit/JIT.h" +#include + #include "preprocessor/llvm_includes_start.h" #include #include diff --git a/evmjit/libevmjit/RuntimeManager.h b/evmjit/libevmjit/RuntimeManager.h index 5ce749933..98d5b3132 100644 --- a/evmjit/libevmjit/RuntimeManager.h +++ b/evmjit/libevmjit/RuntimeManager.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "CompilerHelper.h" #include "Type.h" #include "Instruction.h" From a53d50e9e5bad5d5d8db31ccf9ffd37fbf9943d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 19 May 2015 14:03:18 +0200 Subject: [PATCH 034/290] Adjustments for llvm::IRBuilder API changes. --- evmjit/libevmjit/Arith256.cpp | 4 ++-- evmjit/libevmjit/Compiler.cpp | 2 +- evmjit/libevmjit/GasMeter.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/evmjit/libevmjit/Arith256.cpp b/evmjit/libevmjit/Arith256.cpp index 6c1f8f160..066596e4c 100644 --- a/evmjit/libevmjit/Arith256.cpp +++ b/evmjit/libevmjit/Arith256.cpp @@ -161,8 +161,8 @@ llvm::Function* createUDivRemFunc(llvm::Type* _type, llvm::Module& _module, char builder.SetInsertPoint(mainBB); auto ctlzIntr = llvm::Intrinsic::getDeclaration(&_module, llvm::Intrinsic::ctlz, _type); // both y and r are non-zero - auto yLz = builder.CreateCall2(ctlzIntr, yArg, builder.getInt1(true), "y.lz"); - auto rLz = builder.CreateCall2(ctlzIntr, r0, builder.getInt1(true), "r.lz"); + auto yLz = builder.CreateCall(ctlzIntr, {yArg, builder.getInt1(true)}, "y.lz"); + auto rLz = builder.CreateCall(ctlzIntr, {r0, builder.getInt1(true)}, "r.lz"); auto i0 = builder.CreateNUWSub(yLz, rLz, "i0"); auto y0 = builder.CreateShl(yArg, i0); builder.CreateBr(loopBB); diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index a7006dcde..3ec2af203 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -148,7 +148,7 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera auto fp = m_builder.CreateCall(frameaddress, m_builder.getInt32(0), "fp"); m_builder.CreateStore(fp, jmpBufWords); auto stacksave = llvm::Intrinsic::getDeclaration(module.get(), llvm::Intrinsic::stacksave); - auto sp = m_builder.CreateCall(stacksave, "sp"); + auto sp = m_builder.CreateCall(stacksave, {}, "sp"); auto jmpBufSp = m_builder.CreateConstInBoundsGEP1_64(jmpBufWords, 2, "jmpBuf.sp"); m_builder.CreateStore(sp, jmpBufSp); auto setjmp = llvm::Intrinsic::getDeclaration(module.get(), llvm::Intrinsic::eh_sjlj_setjmp); diff --git a/evmjit/libevmjit/GasMeter.cpp b/evmjit/libevmjit/GasMeter.cpp index c0a2ed287..4cd053316 100644 --- a/evmjit/libevmjit/GasMeter.cpp +++ b/evmjit/libevmjit/GasMeter.cpp @@ -217,7 +217,7 @@ void GasMeter::countExp(llvm::Value* _exponent) // OPT: Can gas update be done in exp algorithm? auto ctlz = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::ctlz, Type::Word); - auto lz256 = m_builder.CreateCall2(ctlz, _exponent, m_builder.getInt1(false)); + auto lz256 = m_builder.CreateCall(ctlz, {_exponent, m_builder.getInt1(false)}); auto lz = m_builder.CreateTrunc(lz256, Type::Gas, "lz"); auto sigBits = m_builder.CreateSub(m_builder.getInt64(256), lz, "sigBits"); auto sigBytes = m_builder.CreateUDiv(m_builder.CreateAdd(sigBits, m_builder.getInt64(7)), m_builder.getInt64(8)); From 3db8048627c554fc28977c6425dfa8c3eff597d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 21 May 2015 14:28:19 +0200 Subject: [PATCH 035/290] Remove LLVM cmake files workaround. --- evmjit/CMakeLists.txt | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/evmjit/CMakeLists.txt b/evmjit/CMakeLists.txt index e1db7da06..c57188bbb 100644 --- a/evmjit/CMakeLists.txt +++ b/evmjit/CMakeLists.txt @@ -16,22 +16,11 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") endif() # LLVM -if(LLVM_DIR OR APPLE) # local LLVM build - find_package(LLVM REQUIRED CONFIG) - message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") - message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") - add_definitions(${LLVM_DEFINITIONS}) - # TODO: bitwriter is needed only for evmcc - llvm_map_components_to_libnames(LLVM_LIBS core support mcjit x86asmparser x86codegen bitwriter ipo) -else() - # Workaround for Ubuntu broken LLVM package - message(STATUS "Using llvm-3.7-dev package from Ubuntu. If does not work, build LLVM and set -DLLVM_DIR=llvm-build/share/llvm/cmake") - execute_process(COMMAND llvm-config-3.7 --includedir OUTPUT_VARIABLE LLVM_INCLUDE_DIRS) - message(STATUS "LLVM include dirs: ${LLVM_INCLUDE_DIRS}") - set(LLVM_LIBS "-lLLVMBitWriter -lLLVMX86CodeGen -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMCodeGen -lLLVMScalarOpts -lLLVMInstCombine -lLLVMTransformUtils -lLLVMipa -lLLVMAnalysis -lLLVMX86AsmParser -lLLVMX86Desc -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMMCJIT -lLLVMExecutionEngine -lLLVMRuntimeDyld -lLLVMTarget -lLLVMRuntimeDyld -lLLVMObject -lLLVMMCParser -lLLVMBitReader -lLLVMMC -lLLVMMCDisassembler -lLLVMCore -lLLVMSupport -lz -lpthread -lffi -ltinfo -ldl -lm") - add_definitions(-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS) - link_directories(/usr/lib/llvm-3.7/lib) -endif() +find_package(LLVM REQUIRED CONFIG) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") +add_definitions(${LLVM_DEFINITIONS}) +llvm_map_components_to_libnames(LLVM_LIBS core support mcjit x86asmparser x86codegen ipo) get_filename_component(EVMJIT_INCLUDE_DIR include ABSOLUTE) From f183ac4fbbb57617243f6435fe5c1acb815207d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 21 May 2015 17:54:37 +0200 Subject: [PATCH 036/290] Cleanup unused code. --- evmjit/include/evmjit/JIT.h | 2 +- evmjit/libevmjit/Array.cpp | 2 -- evmjit/libevmjit/Ext.h | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/evmjit/include/evmjit/JIT.h b/evmjit/include/evmjit/JIT.h index adca983d9..85c74ba18 100644 --- a/evmjit/include/evmjit/JIT.h +++ b/evmjit/include/evmjit/JIT.h @@ -129,7 +129,7 @@ public: bytes_ref getReturnData() const; -private: +protected: RuntimeData* m_data = nullptr; ///< Pointer to data. Expected by compiled contract. Env* m_env = nullptr; ///< Pointer to environment proxy. Expected by compiled contract. byte* m_memData = nullptr; diff --git a/evmjit/libevmjit/Array.cpp b/evmjit/libevmjit/Array.cpp index a76776c69..e77ceefe4 100644 --- a/evmjit/libevmjit/Array.cpp +++ b/evmjit/libevmjit/Array.cpp @@ -18,7 +18,6 @@ namespace jit { static const auto c_reallocStep = 1; -static const auto c_reallocMultipier = 2; llvm::Value* LazyFunction::call(llvm::IRBuilder<>& _builder, std::initializer_list const& _args, llvm::Twine const& _name) { @@ -57,7 +56,6 @@ llvm::Function* Array::createArrayPushFunc() m_builder.SetInsertPoint(reallocBB); auto newCap = m_builder.CreateNUWAdd(cap, m_builder.getInt64(c_reallocStep), "newCap"); - //newCap = m_builder.CreateNUWMul(newCap, m_builder.getInt64(c_reallocMultipier)); auto reallocSize = m_builder.CreateShl(newCap, 5, "reallocSize"); // size in bytes: newCap * 32 auto bytes = m_builder.CreateBitCast(data, Type::BytePtr, "bytes"); auto newBytes = m_reallocFunc.call(m_builder, {bytes, reallocSize}, "newBytes"); diff --git a/evmjit/libevmjit/Ext.h b/evmjit/libevmjit/Ext.h index 760f77df5..2af074f4a 100644 --- a/evmjit/libevmjit/Ext.h +++ b/evmjit/libevmjit/Ext.h @@ -62,7 +62,6 @@ private: Memory& m_memoryMan; llvm::Value* m_size; - llvm::Value* m_data = nullptr; std::array::value> m_funcs; std::array m_argAllocas; From 17f66be28a4d969b140d9c2edd934679096fa691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 10 Jun 2015 18:01:37 +0200 Subject: [PATCH 037/290] Disable some warnings in LLVM headers for GCC/clang compilers. --- evmjit/libevmjit/preprocessor/llvm_includes_end.h | 4 ++++ evmjit/libevmjit/preprocessor/llvm_includes_start.h | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/evmjit/libevmjit/preprocessor/llvm_includes_end.h b/evmjit/libevmjit/preprocessor/llvm_includes_end.h index 643e03064..2ead6dda3 100644 --- a/evmjit/libevmjit/preprocessor/llvm_includes_end.h +++ b/evmjit/libevmjit/preprocessor/llvm_includes_end.h @@ -1,3 +1,7 @@ #if defined(_MSC_VER) #pragma warning(pop) +#elif defined(__clang__) + #pragma clang diagnostic pop +#else + #pragma GCC diagnostic pop #endif diff --git a/evmjit/libevmjit/preprocessor/llvm_includes_start.h b/evmjit/libevmjit/preprocessor/llvm_includes_start.h index 9499f9835..9077bf43f 100644 --- a/evmjit/libevmjit/preprocessor/llvm_includes_start.h +++ b/evmjit/libevmjit/preprocessor/llvm_includes_start.h @@ -1,4 +1,12 @@ #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable: 4267 4244 4800) +#elif defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunused-parameter" + #pragma clang diagnostic ignored "-Wconversion" +#else + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunused-parameter" + #pragma GCC diagnostic ignored "-Wconversion" #endif From e5bf3e16a3e72996e2f374970b2026958fb0a9ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 10 Jun 2015 18:18:38 +0200 Subject: [PATCH 038/290] Add code hash to VM tester. --- test/libevm/vm.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/libevm/vm.cpp b/test/libevm/vm.cpp index ec66837e1..2e1ef4d92 100644 --- a/test/libevm/vm.cpp +++ b/test/libevm/vm.cpp @@ -324,6 +324,8 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) fev.code = fev.thisTxCode; } + fev.codeHash = sha3(fev.code); + bytes output; bool vmExceptionOccured = false; try From 62af7a08a117f758548e8015c10f96b226234124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 11 Jun 2015 10:59:14 +0200 Subject: [PATCH 039/290] Skip all STOPs in the end in EVM JIT compiler --- evmjit/libevmjit/Compiler.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 3ec2af203..be980f4be 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -49,6 +49,13 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn return _curr + offset; }; + // Skip all STOPs in the end + for (; _codeEnd != _codeBegin; --_codeEnd) + { + if (*(_codeEnd - 1) != static_cast(Instruction::STOP)) + break; + } + auto begin = _codeBegin; // begin of current block bool nextJumpDest = false; for (auto curr = begin, next = begin; curr != _codeEnd; curr = next) @@ -81,6 +88,7 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn if (isEnd) { auto beginIdx = begin - _codeBegin; + std::cerr << "BB #" << beginIdx << ": " << (next - begin) << "B\n"; m_basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginIdx), std::forward_as_tuple(beginIdx, begin, next, m_mainFunc, m_builder, nextJumpDest)); nextJumpDest = false; From f866a3ab088b673d4838d5c9fe867557cb9664a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 11 Jun 2015 16:10:41 +0200 Subject: [PATCH 040/290] Remove debug message. --- evmjit/libevmjit/Compiler.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index be980f4be..55a8b9203 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -88,7 +88,6 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn if (isEnd) { auto beginIdx = begin - _codeBegin; - std::cerr << "BB #" << beginIdx << ": " << (next - begin) << "B\n"; m_basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginIdx), std::forward_as_tuple(beginIdx, begin, next, m_mainFunc, m_builder, nextJumpDest)); nextJumpDest = false; From 3f1944141c9ba6f5b8f816af168b313c2b01f97f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 11 Jun 2015 16:11:27 +0200 Subject: [PATCH 041/290] Release aquired arg allocas in Ext::calldataload. --- evmjit/libevmjit/Ext.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/evmjit/libevmjit/Ext.cpp b/evmjit/libevmjit/Ext.cpp index 9b1e0983b..b8b124ff5 100644 --- a/evmjit/libevmjit/Ext.cpp +++ b/evmjit/libevmjit/Ext.cpp @@ -119,6 +119,7 @@ llvm::Value* Ext::calldataload(llvm::Value* _idx) auto pad = m_builder.CreateGEP(Type::Byte, result, copySize); m_builder.CreateMemSet(pad, m_builder.getInt8(0), padSize, 1); + m_argCounter = 0; // Release args allocas. TODO: This is a bad design return Endianness::toNative(m_builder, m_builder.CreateLoad(ret)); } From 6ff348f383d52405985564d933ccb75e8f30b5b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 11 Jun 2015 17:48:53 +0200 Subject: [PATCH 042/290] Fix unaligned copy. --- evmjit/include/evmjit/JIT.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/evmjit/include/evmjit/JIT.h b/evmjit/include/evmjit/JIT.h index 85c74ba18..0a938fae9 100644 --- a/evmjit/include/evmjit/JIT.h +++ b/evmjit/include/evmjit/JIT.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #ifdef _MSC_VER @@ -38,7 +39,7 @@ struct i256 uint64_t words[4]; i256() = default; - i256(h256 _h) { *this = *reinterpret_cast(&_h); } + i256(h256 _h) { std::memcpy(this, &_h, sizeof(*this)); } }; // TODO: Merge with ExecutionContext From b2345b982b15056525d9802e194a748f91d4f9a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 24 Jun 2015 17:35:20 +0200 Subject: [PATCH 043/290] Cleanup issues reported by clang. --- evmjit/libevmjit/Optimizer.cpp | 3 +-- evmjit/libevmjit/Stack.h | 5 ----- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/evmjit/libevmjit/Optimizer.cpp b/evmjit/libevmjit/Optimizer.cpp index d5bf7f05c..b097a2e3f 100644 --- a/evmjit/libevmjit/Optimizer.cpp +++ b/evmjit/libevmjit/Optimizer.cpp @@ -36,8 +36,6 @@ class LowerEVMPass : public llvm::BasicBlockPass { static char ID; - bool m_mulFuncNeeded = false; - public: LowerEVMPass(): llvm::BasicBlockPass(ID) @@ -45,6 +43,7 @@ public: virtual bool runOnBasicBlock(llvm::BasicBlock& _bb) override; + using llvm::BasicBlockPass::doFinalization; virtual bool doFinalization(llvm::Module& _module) override; }; diff --git a/evmjit/libevmjit/Stack.h b/evmjit/libevmjit/Stack.h index 6f7ad1c0b..ad10dae12 100644 --- a/evmjit/libevmjit/Stack.h +++ b/evmjit/libevmjit/Stack.h @@ -27,12 +27,7 @@ private: llvm::Function* getGetFunc(); RuntimeManager& m_runtimeManager; - - llvm::Function* m_pop = nullptr; - llvm::Function* m_push = nullptr; llvm::Function* m_get = nullptr; - llvm::Function* m_set = nullptr; - Array m_stack; }; From 773c2303d8020d465dae53feaf2e9a5681594d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 24 Jun 2015 17:43:47 +0200 Subject: [PATCH 044/290] Do not compute code hash twice in VM test engine. --- evmjit/libevmjit/Type.h | 2 +- test/libevm/vm.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/evmjit/libevmjit/Type.h b/evmjit/libevmjit/Type.h index b54d101cb..5e5b9dde5 100644 --- a/evmjit/libevmjit/Type.h +++ b/evmjit/libevmjit/Type.h @@ -4,7 +4,7 @@ #include #include #include -#include "preprocessor/llvm_includes_end.h" // FIXME: LLVM 3.7: check if needed +#include "preprocessor/llvm_includes_end.h" #include "evmjit/JIT.h" // ReturnCode diff --git a/test/libevm/vm.cpp b/test/libevm/vm.cpp index b64b19a1e..fdfb180fb 100644 --- a/test/libevm/vm.cpp +++ b/test/libevm/vm.cpp @@ -325,8 +325,6 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) } fev.codeHash = sha3(fev.code); - fev.codeHash = sha3(fev.code); - bytes output; bool vmExceptionOccured = false; try From 6d7350f3edcbeb5b8ac28ddd5bf9fb09739dc781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 26 Jun 2015 14:38:20 +0200 Subject: [PATCH 045/290] Fix for incorrect BYTE instruction results. It is actually a LLVM bug workaround. --- evmjit/libevmjit/Compiler.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 55a8b9203..00fe7f7d0 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -481,7 +481,9 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti auto idxValid = m_builder.CreateICmpULT(idx, Constant::get(32), "idxValid"); auto bytes = m_builder.CreateBitCast(value, llvm::VectorType::get(Type::Byte, 32), "bytes"); - auto byte = m_builder.CreateExtractElement(bytes, idx, "byte"); + // Workaround for LLVM bug. Using index of type i256 can produce incorrect results + auto safeIdx = m_builder.CreateZExt(m_builder.CreateTrunc(idx, m_builder.getIntNTy(5)), Type::Size); + auto byte = m_builder.CreateExtractElement(bytes, safeIdx, "byte"); value = m_builder.CreateZExt(byte, Type::Word); value = m_builder.CreateSelect(idxValid, value, Constant::get(0)); stack.push(value); From 02c28296778072b2b8298d9d7cd62ffb505048e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 29 Jun 2015 16:33:48 +0200 Subject: [PATCH 046/290] Better BYTE fix. --- evmjit/libevmjit/Compiler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 00fe7f7d0..cde86c747 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -481,8 +481,8 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti auto idxValid = m_builder.CreateICmpULT(idx, Constant::get(32), "idxValid"); auto bytes = m_builder.CreateBitCast(value, llvm::VectorType::get(Type::Byte, 32), "bytes"); - // Workaround for LLVM bug. Using index of type i256 can produce incorrect results - auto safeIdx = m_builder.CreateZExt(m_builder.CreateTrunc(idx, m_builder.getIntNTy(5)), Type::Size); + // Workaround for LLVM bug. Using big value of index causes invalid memory access. + auto safeIdx = m_builder.CreateTrunc(idx, m_builder.getIntNTy(5)); auto byte = m_builder.CreateExtractElement(bytes, safeIdx, "byte"); value = m_builder.CreateZExt(byte, Type::Word); value = m_builder.CreateSelect(idxValid, value, Constant::get(0)); From ffc416e97e750d7f8b756b4c63a50a9c0047c1ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Jun 2015 12:18:16 +0200 Subject: [PATCH 047/290] Another LLVM bug workaround. --- evmjit/libevmjit/Compiler.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index cde86c747..e51df0245 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -481,8 +481,10 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti auto idxValid = m_builder.CreateICmpULT(idx, Constant::get(32), "idxValid"); auto bytes = m_builder.CreateBitCast(value, llvm::VectorType::get(Type::Byte, 32), "bytes"); - // Workaround for LLVM bug. Using big value of index causes invalid memory access. + // TODO: Workaround for LLVM bug. Using big value of index causes invalid memory access. auto safeIdx = m_builder.CreateTrunc(idx, m_builder.getIntNTy(5)); + // TODO: Workaround for LLVM bug. DAG Builder used sext on index instead of zext + safeIdx = m_builder.CreateZExt(safeIdx, Type::Size); auto byte = m_builder.CreateExtractElement(bytes, safeIdx, "byte"); value = m_builder.CreateZExt(byte, Type::Word); value = m_builder.CreateSelect(idxValid, value, Constant::get(0)); From cfcd722c51460716fe6ebaa1449d36a906d09fb5 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 29 Jun 2015 11:48:32 +0200 Subject: [PATCH 048/290] pv61 sync re-enable pv60 --- alethzero/MainWin.cpp | 2 +- libethereum/BlockChainSync.cpp | 345 ++++++++++++++++++++++++++++++--- libethereum/BlockChainSync.h | 46 ++++- libethereum/CommonNet.h | 1 + libethereum/EthereumHost.cpp | 23 ++- libethereum/EthereumHost.h | 2 +- libethereum/EthereumPeer.cpp | 17 +- libethereum/EthereumPeer.h | 2 +- libp2p/Session.cpp | 5 +- 9 files changed, 392 insertions(+), 51 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 821022abc..1fa122cea 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1252,7 +1252,7 @@ void Main::refreshBlockCount() auto d = ethereum()->blockChain().details(); BlockQueueStatus b = ethereum()->blockQueueStatus(); SyncStatus sync = ethereum()->syncStatus(); - QString syncStatus = EthereumHost::stateName(sync.state); + QString syncStatus = QString("PV%1 %2").arg(sync.protocolVersion).arg(EthereumHost::stateName(sync.state)); if (sync.state == SyncState::Hashes) syncStatus += QString(": %1/%2%3").arg(sync.hashesReceived).arg(sync.hashesEstimated ? "~" : "").arg(sync.hashesTotal); if (sync.state == SyncState::Blocks || sync.state == SyncState::NewBlocks) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 63ac620ce..85e894e5d 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -38,7 +38,8 @@ using namespace dev; using namespace dev::eth; using namespace p2p; -unsigned const c_chainReorgSize = 30000; +unsigned const c_chainReorgSize = 30000; /// Added to estimated hashes to account for potential chain reorganiation +unsigned const c_hashSubchainSize = 8192; /// PV61 subchain size BlockChainSync::BlockChainSync(EthereumHost& _host): m_host(_host) @@ -114,7 +115,6 @@ void BlockChainSync::requestBlocks(std::shared_ptr _peer) { clog(NetAllDetail) << "Waiting for block queue before downloading blocks"; pauseSync(); - _peer->setIdle(); return; } _peer->requestBlocks(); @@ -137,11 +137,9 @@ void BlockChainSync::logNewBlock(h256 const& _h) void BlockChainSync::onPeerBlocks(std::shared_ptr _peer, RLP const& _r) { RecursiveGuard l(x_sync); - DEV_INVARIANT_CHECK; unsigned itemCount = _r.itemCount(); clog(NetMessageSummary) << "Blocks (" << dec << itemCount << "entries)" << (itemCount ? "" : ": NoMoreBlocks"); - _peer->setIdle(); if (m_state != SyncState::Blocks && m_state != SyncState::NewBlocks && m_state != SyncState::Waiting) clog(NetWarn) << "Unexpected Blocks received!"; if (m_state == SyncState::Waiting) @@ -305,6 +303,7 @@ SyncStatus PV60Sync::status() const RecursiveGuard l(x_sync); SyncStatus res; res.state = m_state; + res.protocolVersion = EthereumHost::c_oldProtocolVersion; if (m_state == SyncState::Hashes) { res.hashesTotal = m_estimatedHashes; @@ -381,26 +380,10 @@ void PV60Sync::transition(std::shared_ptr _peer, SyncState _s, boo RLPStream s; if (_s == SyncState::Hashes) { - if (m_state == SyncState::Idle) - { - if (isSyncing(_peer)) - clog(NetWarn) << "Bad state: not asking for Hashes, yet syncing!"; - - m_syncingLatestHash = _peer->m_latestHash; - m_syncingTotalDifficulty = _peer->m_totalDifficulty; - setState(_peer, _s, true); - _peer->requestHashes(m_syncingLastReceivedHash ? m_syncingLastReceivedHash : m_syncingLatestHash); - DEV_INVARIANT_CHECK; - return; - } - else if (m_state == SyncState::Hashes) + if (m_state == SyncState::Idle || m_state == SyncState::Hashes) { - if (!isSyncing(_peer)) - clog(NetWarn) << "Bad state: asking for Hashes yet not syncing!"; - - setState(_peer, _s, true); - _peer->requestHashes(m_syncingLastReceivedHash); - DEV_INVARIANT_CHECK; + m_estimatedHashes = _peer->m_expectedHashes - c_chainReorgSize; + syncHashes(_peer); return; } } @@ -462,7 +445,6 @@ void PV60Sync::transition(std::shared_ptr _peer, SyncState _s, boo } else if (_s == SyncState::Idle) { - host().foreachPeer([this](std::shared_ptr _p) { _p->setIdle(); return true; }); if (m_state == SyncState::Blocks || m_state == SyncState::NewBlocks) { clog(NetMessageDetail) << "Finishing blocks fetch..."; @@ -473,7 +455,6 @@ void PV60Sync::transition(std::shared_ptr _peer, SyncState _s, boo // NOTE: need to notify of giving up on chain-hashes, too, altering state as necessary. _peer->m_sub.doneFetch(); - _peer->setIdle(); setState(_peer, SyncState::Idle, false); } else if (m_state == SyncState::Hashes) @@ -562,7 +543,6 @@ void PV60Sync::attemptSync(std::shared_ptr _peer) else { clog(NetAllDetail) << "Yes. Their chain is better."; - m_estimatedHashes = _peer->m_expectedHashes - c_chainReorgSize; transition(_peer, SyncState::Hashes); } } @@ -573,7 +553,9 @@ void PV60Sync::noteNeedsSyncing(std::shared_ptr _peer) if (isSyncing()) { clog(NetAllDetail) << "Sync in progress: Just set to help out."; - if (m_state == SyncState::Blocks) + if (m_state == SyncState::Hashes && _peer->m_asking == Asking::Nothing) + requestSubchain(_peer); + else if (m_state == SyncState::Blocks) requestBlocks(_peer); } else @@ -649,20 +631,45 @@ void PV60Sync::noteDoneBlocks(std::shared_ptr _peer, bool _clemenc } resetSync(); downloadMan().reset(); + } _peer->m_sub.doneFetch(); +} + +void PV60Sync::syncHashes(std::shared_ptr _peer) +{ + if (m_state == SyncState::Idle) + { + if (isSyncing(_peer)) + clog(NetWarn) << "Bad state: not asking for Hashes, yet syncing!"; + + m_syncingLatestHash = _peer->m_latestHash; + m_syncingTotalDifficulty = _peer->m_totalDifficulty; + setState(_peer, SyncState::Hashes, true); + _peer->requestHashes(m_syncingLastReceivedHash ? m_syncingLastReceivedHash : m_syncingLatestHash); + } + else if (m_state == SyncState::Hashes) + { + if (!isSyncing(_peer)) + clog(NetWarn) << "Bad state: asking for Hashes yet not syncing!"; + + setState(_peer, SyncState::Hashes, true); + _peer->requestHashes(m_syncingLastReceivedHash); } } void PV60Sync::onPeerHashes(std::shared_ptr _peer, h256s const& _hashes) { RecursiveGuard l(x_sync); - DEV_INVARIANT_CHECK; - _peer->setIdle(); if (!isSyncing(_peer)) { clog(NetMessageSummary) << "Ignoring hashes since not syncing"; return; } + if (_peer->m_syncHash != (m_syncingLastReceivedHash ? m_syncingLastReceivedHash : m_syncingLatestHash)) + { + clog(NetMessageSummary) << "Ignoring unexpected hashes"; + return; + } if (_hashes.size() == 0) { transition(_peer, SyncState::Blocks); @@ -711,7 +718,6 @@ void PV60Sync::onPeerHashes(std::shared_ptr _peer, h256s const& _h void PV60Sync::onPeerNewHashes(std::shared_ptr _peer, h256s const& _hashes) { RecursiveGuard l(x_sync); - DEV_INVARIANT_CHECK; if (isSyncing() && (m_state != SyncState::NewBlocks || isSyncing(_peer))) { clog(NetMessageSummary) << "Ignoring since we're already downloading."; @@ -769,7 +775,6 @@ void PV60Sync::onPeerNewHashes(std::shared_ptr _peer, h256s const& void PV60Sync::abortSync() { // Can't check invariants here since the peers is already removed from the list and the state is not updated yet. - host().foreachPeer([this](std::shared_ptr _p) { _p->setIdle(); return true; }); setState(std::shared_ptr(), SyncState::Idle, false, true); DEV_INVARIANT_CHECK; } @@ -820,3 +825,281 @@ bool PV60Sync::invariants() const return false; return true; } + +PV61Sync::PV61Sync(EthereumHost& _host): + PV60Sync(_host) +{ +} + +void PV61Sync::syncHashes(std::shared_ptr _peer) +{ + if (_peer->m_protocolVersion != host().protocolVersion()) + { + m_readyChainMap.clear(); + m_completeChainMap.clear(); + m_downloadingChainMap.clear(); + m_syncingBlockNumber = 0; + m_chainSyncPeers.clear(); + m_knownHashes.clear(); + PV60Sync::syncHashes(_peer); + return; + } + if (m_state == SyncState::Idle) + { + if (isSyncing(_peer)) + clog(NetWarn) << "Bad state: not asking for Hashes, yet syncing!"; + + if (m_syncingBlockNumber == 0) + m_syncingBlockNumber = host().chain().number() + c_hashSubchainSize; + m_syncingTotalDifficulty = _peer->m_totalDifficulty; + setState(_peer, SyncState::Hashes, true); + _peer->requestHashes(m_syncingBlockNumber, 1); + } + else if (m_state == SyncState::Hashes) + { + if (!isSyncing(_peer)) + clog(NetWarn) << "Bad state: asking for Hashes yet not syncing!"; + + m_syncingBlockNumber += c_hashSubchainSize; + setState(_peer, SyncState::Hashes, true); + _peer->requestHashes(m_syncingBlockNumber, 1); + } +} + +void PV61Sync::requestSubchain(std::shared_ptr _peer) +{ + auto syncPeer = m_chainSyncPeers.find(_peer); + if (syncPeer != m_chainSyncPeers.end()) + { + // Already downoading, request next batch + h256s& d = m_downloadingChainMap.at(syncPeer->second); + _peer->requestHashes(d.back()); + } + else if (needsSyncing(_peer) && !m_readyChainMap.empty()) + { + clog(NetAllDetail) << "Helping with hashchin download"; + h256s& d = m_readyChainMap.begin()->second; + _peer->requestHashes(d.back()); + m_downloadingChainMap[m_readyChainMap.begin()->first] = move(d); + m_chainSyncPeers[_peer] = m_readyChainMap.begin()->first; + m_readyChainMap.erase(m_readyChainMap.begin()); + } +} + +void PV61Sync::requestSubchains() +{ + host().foreachPeer([this](std::shared_ptr _p) + { + if (_p->m_asking == Asking::Nothing) + requestSubchain(_p); + return true; + }); +} + +void PV61Sync::completeSubchain(std::shared_ptr _peer, unsigned _n) +{ + m_completeChainMap[_n] = move(m_downloadingChainMap.at(_n)); + m_downloadingChainMap.erase(_n); + _peer->m_syncHashNumber = 0; + + auto syncer = m_syncer.lock(); + if (!syncer) + { + restartSync(); + return; + } + + if (m_readyChainMap.empty() && m_downloadingChainMap.empty() && syncer->m_asking == Asking::Nothing) + { + //Done chain-get + m_syncingNeededBlocks.clear(); + for (auto h = m_completeChainMap.rbegin(); h != m_completeChainMap.rend(); ++h) + m_syncingNeededBlocks.insert(m_syncingNeededBlocks.end(), h->second.begin(), h->second.end()); + m_completeChainMap.clear(); + m_knownHashes.clear(); + m_syncingBlockNumber = 0; + transition(syncer, SyncState::Blocks); + } + else + requestSubchain(_peer); +} + +void PV61Sync::restartSync() +{ + m_completeChainMap.clear(); + m_readyChainMap.clear(); + m_downloadingChainMap.clear(); + m_chainSyncPeers.clear(); + m_syncingBlockNumber = 0; + m_knownHashes.clear(); + PV60Sync::restartSync(); +} + +void PV61Sync::onPeerHashes(std::shared_ptr _peer, h256s const& _hashes) +{ + RecursiveGuard l(x_sync); + if (m_syncingBlockNumber == 0 || (_peer == m_syncer.lock() && _peer->m_protocolVersion != host().protocolVersion())) + { + // Syncing in pv60 mode + PV60Sync::onPeerHashes(_peer, _hashes); + return; + } + if (_hashes.size() == 0) + { + if (isSyncing(_peer) && _peer->m_syncHashNumber == m_syncingBlockNumber) + { + // End of hash chain, add last chunk to download + m_readyChainMap.insert(make_pair(m_syncingBlockNumber, h256s { _peer->m_latestHash })); + _peer->m_syncHashNumber = 0; + requestSubchain(_peer); + } + else + { + auto syncPeer = m_chainSyncPeers.find(_peer); + if (syncPeer == m_chainSyncPeers.end()) + clog(NetWarn) << "Hashes response from unexpected peer"; + else + { + // Peer does not have request hashes, move back from downloading to ready + unsigned number = syncPeer->second; + m_chainSyncPeers.erase(_peer); + m_readyChainMap[number] = move(m_downloadingChainMap.at(number)); + m_downloadingChainMap.erase(number); + resetNeedsSyncing(_peer); + requestSubchains(); + } + } + return; + } + if (isSyncing(_peer) && _peer->m_syncHashNumber == m_syncingBlockNumber) + { + // Got new subchain marker + assert(_hashes.size() == 1); + m_knownHashes.insert(_hashes[0]); + m_readyChainMap.insert(make_pair(m_syncingBlockNumber, h256s { _hashes[0] })); + if ((m_readyChainMap.size() + m_downloadingChainMap.size() + m_completeChainMap.size()) * c_hashSubchainSize > _peer->m_expectedHashes) + { + _peer->disable("Too many hashes from lead peer"); + restartSync(); + return; + } + transition(_peer, SyncState::Hashes); + requestSubchains(); + } + else + { + auto syncPeer = m_chainSyncPeers.find(_peer); + if (syncPeer == m_chainSyncPeers.end()) + { + clog(NetWarn) << "Hashes response from unexpected peer"; + return; + } + unsigned number = syncPeer->second; + h256s& hashes = m_downloadingChainMap.at(number); + + unsigned knowns = 0; + unsigned unknowns = 0; + for (unsigned i = 0; i < _hashes.size(); ++i) + { + auto h = _hashes[i]; + auto status = host().bq().blockStatus(h); + if (status == QueueStatus::Importing || status == QueueStatus::Ready || host().chain().isKnown(h) || !!m_knownHashes.count(h)) + { + clog(NetMessageSummary) << "Subchain download complete"; + m_chainSyncPeers.erase(_peer); + completeSubchain(_peer, number); + return; + } + else if (status == QueueStatus::Bad) + { + cwarn << "block hash bad!" << h << ". Bailing..."; + restartSync(); + return; + } + else if (status == QueueStatus::Unknown) + { + unknowns++; + hashes.push_back(h); + } + else + knowns++; + } + clog(NetMessageSummary) << knowns << "knowns," << unknowns << "unknowns; now at" << hashes.back(); + if (hashes.size() > c_hashSubchainSize) + { + _peer->disable("Too many subchain hashes"); + restartSync(); + return; + } + requestSubchain(_peer); + } + DEV_INVARIANT_CHECK; +} + +void PV61Sync::onPeerAborting() +{ + RecursiveGuard l(x_sync); + // Can't check invariants here since the peers is already removed from the list and the state is not updated yet. + for (auto s = m_chainSyncPeers.begin(); s != m_chainSyncPeers.end();) + { + if (s->first.expired()) + { + unsigned number = s->second; + m_readyChainMap[number] = move(m_downloadingChainMap.at(number)); + m_downloadingChainMap.erase(number); + m_chainSyncPeers.erase(s++); + } + else + ++s; + } + if (m_syncer.expired()) + abortSync(); + else if (isPV61Syncing()) + requestSubchains(); + DEV_INVARIANT_CHECK; +} + +SyncStatus PV61Sync::status() const +{ + RecursiveGuard l(x_sync); + SyncStatus res = PV60Sync::status(); + if (m_state == SyncState::Hashes && isPV61Syncing()) + { + res.protocolVersion = 61; + res.hashesReceived = 0; + for (auto const& d : m_readyChainMap) + res.hashesReceived += d.second.size(); + for (auto const& d : m_downloadingChainMap) + res.hashesReceived += d.second.size(); + for (auto const& d : m_completeChainMap) + res.hashesReceived += d.second.size(); + } + return res; +} + +bool PV61Sync::isPV61Syncing() const +{ + return m_syncingBlockNumber != 0; +} + +bool PV61Sync::invariants() const +{ + if (m_downloadingChainMap.size() != m_chainSyncPeers.size()) + return false; + if (m_state == SyncState::Idle && isSyncing()) + return false; + if (m_state != SyncState::Idle && !isSyncing()) + return false; + if (m_state == SyncState::Hashes) + { + bool hashes = false; + host().foreachPeer([&](std::shared_ptr _p) { if (_p->m_asking == Asking::Hashes) hashes = true; return !hashes; }); + if (!hashes) + return false; + if (isPV61Syncing() && !m_syncingBlockNumber) + return false; + } + else if (!PV60Sync::invariants()) + return false; + return true; +} diff --git a/libethereum/BlockChainSync.h b/libethereum/BlockChainSync.h index 449dd49d1..01727a0cb 100644 --- a/libethereum/BlockChainSync.h +++ b/libethereum/BlockChainSync.h @@ -132,8 +132,8 @@ private: /** - * @brief Syncrhonization over PV60. Selects a single peer and tries to downloading hashes from it. After hash downaload is complete - * Syncs to peers and keeps up to date + * @brief Syncrhonization over PV60. Selects a single peer and tries to downloading hashes from it. After hash download is complete + * syncs to peers and keeps up to date */ /** @@ -228,7 +228,7 @@ protected: void pauseSync() override; void resetSyncFor(std::shared_ptr _peer, h256 const& _latestHash, u256 const& _td) override; -private: +protected: /// Transition sync state in a particular direction. @param _peer Peer that is responsible for state tranfer void transition(std::shared_ptr _peer, SyncState _s, bool _force = false, bool _needHelp = true); @@ -262,6 +262,12 @@ private: /// Called when peer done downloading blocks void noteDoneBlocks(std::shared_ptr _who, bool _clemency); + /// Start chainhash sync + virtual void syncHashes(std::shared_ptr _peer); + + /// Request subchain, no-op for pv60 + virtual void requestSubchain(std::shared_ptr /*_peer*/) {} + /// Abort syncing void abortSync(); @@ -276,5 +282,39 @@ private: u256 m_syncingTotalDifficulty; ///< Latest block's total difficulty of the peer we aresyncing to, as of the current sync. std::weak_ptr m_syncer; ///< Peer we are currently syncing with }; + +/** + * @brief Syncrhonization over PV61. Selects a single peer and requests every c_hashSubchainSize hash, splitting the hashchain into subchains and downloading each subchain in parallel. + * Syncs to peers and keeps up to date + */ +class PV61Sync: public PV60Sync +{ +public: + PV61Sync(EthereumHost& _host); + +protected: + void restartSync() override; + void requestSubchain(std::shared_ptr _peer) override; + void syncHashes(std::shared_ptr _peer) override; + void onPeerHashes(std::shared_ptr _peer, h256s const& _hashes) override; + void onPeerAborting() override; + SyncStatus status() const override; + bool invariants() const override; + +private: + /// Called when subchain is complete. Check if if hashchain is fully downloaded and proceed to downloading blocks + void completeSubchain(std::shared_ptr _peer, unsigned _n); + /// Find a subchain for peers to downloading + void requestSubchains(); + /// Check if downloading hashes in parallel + bool isPV61Syncing() const; + + std::map m_completeChainMap; ///< Fully downloaded subchains + std::map m_readyChainMap; ///< Subchains ready for download + std::map m_downloadingChainMap; ///< Subchains currently being downloading. In sync with m_chainSyncPeers + std::map, unsigned, std::owner_less>> m_chainSyncPeers; ///< Peers to m_downloadingSubchain number map + h256Hash m_knownHashes; ///< Subchain start markers. Used to track suchain completion + unsigned m_syncingBlockNumber = 0; ///< Current subchain marker +}; } } diff --git a/libethereum/CommonNet.h b/libethereum/CommonNet.h index 35a27ff5e..d03e04d85 100644 --- a/libethereum/CommonNet.h +++ b/libethereum/CommonNet.h @@ -91,6 +91,7 @@ enum class SyncState struct SyncStatus { SyncState state = SyncState::Idle; + unsigned protocolVersion = 0; unsigned hashesTotal = 0; unsigned hashesReceived = 0; bool hashesEstimated = false; diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 9980f4339..5bd16ac12 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -230,10 +230,10 @@ void EthereumHost::maintainBlocks(h256 const& _currentHash) } } -BlockChainSync& EthereumHost::sync() +BlockChainSync* EthereumHost::sync() { if (m_sync) - return *m_sync; // We only chose sync strategy once + return m_sync.get(); // We only chose sync strategy once bool pv61 = false; foreachPeer([&](std::shared_ptr _p) @@ -242,38 +242,43 @@ BlockChainSync& EthereumHost::sync() pv61 = true; return !pv61; }); - m_sync.reset(pv61 ? new PV60Sync(*this) : new PV60Sync(*this)); - return *m_sync; + m_sync.reset(pv61 ? new PV61Sync(*this) : new PV60Sync(*this)); + return m_sync.get(); } void EthereumHost::onPeerStatus(std::shared_ptr _peer) { Guard l(x_sync); - sync().onPeerStatus(_peer); + if (sync()) + sync()->onPeerStatus(_peer); } void EthereumHost::onPeerHashes(std::shared_ptr _peer, h256s const& _hashes) { Guard l(x_sync); - sync().onPeerHashes(_peer, _hashes); + if (sync()) + sync()->onPeerHashes(_peer, _hashes); } void EthereumHost::onPeerBlocks(std::shared_ptr _peer, RLP const& _r) { Guard l(x_sync); - sync().onPeerBlocks(_peer, _r); + if (sync()) + sync()->onPeerBlocks(_peer, _r); } void EthereumHost::onPeerNewHashes(std::shared_ptr _peer, h256s const& _hashes) { Guard l(x_sync); - sync().onPeerNewHashes(_peer, _hashes); + if (sync()) + sync()->onPeerNewHashes(_peer, _hashes); } void EthereumHost::onPeerNewBlock(std::shared_ptr _peer, RLP const& _r) { Guard l(x_sync); - sync().onPeerNewBlock(_peer, _r); + if (sync()) + sync()->onPeerNewBlock(_peer, _r); } void EthereumHost::onPeerTransactions(std::shared_ptr _peer, RLP const& _r) diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index 182c3d4cd..37c495ec5 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -116,7 +116,7 @@ private: virtual void onStarting() override { startWorking(); } virtual void onStopping() override { stopWorking(); } - BlockChainSync& sync(); + BlockChainSync* sync(); BlockChain const& m_chain; TransactionQueue& m_tq; ///< Maintains a list of incoming transactions not yet in a block on the blockchain. diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp index 88878334c..9e7dd6898 100644 --- a/libethereum/EthereumPeer.cpp +++ b/libethereum/EthereumPeer.cpp @@ -141,6 +141,7 @@ void EthereumPeer::requestStatus() void EthereumPeer::requestHashes(u256 _number, unsigned _count) { assert(m_asking == Asking::Nothing); + assert(m_protocolVersion == host()->protocolVersion()); m_syncHashNumber = _number; m_syncHash = h256(); setAsking(Asking::Hashes); @@ -198,7 +199,7 @@ void EthereumPeer::requestBlocks() void EthereumPeer::setAsking(Asking _a) { m_asking = _a; - m_lastAsk = chrono::system_clock::now(); + m_lastAsk = std::chrono::system_clock::to_time_t(chrono::system_clock::now()); auto s = session(); if (s) @@ -211,9 +212,14 @@ void EthereumPeer::setAsking(Asking _a) void EthereumPeer::tick() { auto s = session(); - if (s && (chrono::system_clock::now() - m_lastAsk > chrono::seconds(10) && m_asking != Asking::Nothing)) + time_t now = std::chrono::system_clock::to_time_t(chrono::system_clock::now()); + if (s && (now - m_lastAsk > 10 && m_asking != Asking::Nothing)) + { + clog(NetWarn) << "timeout: " << (now - m_lastAsk) << " " << + (m_asking == Asking::Nothing ? "nothing" : m_asking == Asking::State ? "state" : m_asking == Asking::Hashes ? "hashes" : m_asking == Asking::Blocks ? "blocks" : "?"); // timeout s->disconnect(PingTimeout); + } } bool EthereumPeer::isConversing() const @@ -228,6 +234,7 @@ bool EthereumPeer::isCriticalSyncing() const bool EthereumPeer::interpret(unsigned _id, RLP const& _r) { + m_lastAsk = std::chrono::system_clock::to_time_t(chrono::system_clock::now()); try { switch (_id) @@ -254,7 +261,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r) } clog(NetMessageSummary) << "Status:" << m_protocolVersion << "/" << m_networkId << "/" << m_genesisHash << "/" << m_latestBlockNumber << ", TD:" << m_totalDifficulty << "=" << m_latestHash; - setAsking(Asking::Nothing); + setIdle(); host()->onPeerStatus(dynamic_pointer_cast(dynamic_pointer_cast(shared_from_this()))); break; } @@ -311,6 +318,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r) clog(NetWarn) << "Peer giving us hashes when we didn't ask for them."; break; } + setIdle(); h256s hashes(itemCount); for (unsigned i = 0; i < itemCount; ++i) hashes[i] = _r[i].toHash(); @@ -357,7 +365,10 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r) if (m_asking != Asking::Blocks) clog(NetImpolite) << "Peer giving us blocks when we didn't ask for them."; else + { + setIdle(); host()->onPeerBlocks(dynamic_pointer_cast(shared_from_this()), _r); + } break; } case NewBlockPacket: diff --git a/libethereum/EthereumPeer.h b/libethereum/EthereumPeer.h index d506ffb3f..faf3a0650 100644 --- a/libethereum/EthereumPeer.h +++ b/libethereum/EthereumPeer.h @@ -136,7 +136,7 @@ private: /// What, if anything, we last asked the other peer for. Asking m_asking = Asking::Nothing; /// When we asked for it. Allows a time out. - std::chrono::system_clock::time_point m_lastAsk; + std::atomic m_lastAsk; /// These are determined through either a Status message or from NewBlock. h256 m_latestHash; ///< Peer's latest block's hash that we know about or default null value if no need to sync. diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp index 3d0bd0b6a..b79a225a2 100644 --- a/libp2p/Session.cpp +++ b/libp2p/Session.cpp @@ -367,7 +367,7 @@ void Session::drop(DisconnectReason _reason) if (socket.is_open()) try { - clog(NetConnect) << "Closing " << socket.remote_endpoint() << "(" << reasonOf(_reason) << ")"; + clog(NetWarn) << "Closing " << socket.remote_endpoint() << "(" << reasonOf(_reason) << ")"; boost::system::error_code ec; socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); socket.close(); @@ -386,11 +386,12 @@ void Session::drop(DisconnectReason _reason) void Session::disconnect(DisconnectReason _reason) { clog(NetConnect) << "Disconnecting (our reason:" << reasonOf(_reason) << ")"; + size_t peerCount = m_server->peerCount(); //needs to be outside of lock to avoid deadlocking with other thread that capture x_info/x_sessions in reverse order DEV_GUARDED(x_info) StructuredLogger::p2pDisconnected( m_info.id.abridged(), m_peer->endpoint, // TODO: may not be 100% accurate - m_server->peerCount() + peerCount ); if (m_socket->ref().is_open()) { From cc9865b271a995104703cbabed7e4c4112ecfd1d Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 30 Jun 2015 18:09:46 +0200 Subject: [PATCH 049/290] detailed invariant exceptions --- libethereum/BlockChainSync.cpp | 32 +++++++++++--------------------- libethereum/EthereumPeer.cpp | 4 ++-- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 85e894e5d..7fa4a574d 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -791,38 +791,32 @@ void PV60Sync::onPeerAborting() bool PV60Sync::invariants() const { if (m_state == SyncState::Idle && isSyncing()) - return false; + BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("Idle while peer syncing")); if (m_state != SyncState::Idle && !isSyncing()) - return false; + BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("Active while peer not syncing")); if (m_state == SyncState::Hashes) { bool hashes = false; host().foreachPeer([&](std::shared_ptr _p) { if (_p->m_asking == Asking::Hashes) hashes = true; return !hashes; }); if (!hashes) - return false; + BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("No peers asking for hashes")); if (!m_syncingLatestHash) - return false; + BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("m_syncingLatestHash is not set while downloading hashes")); if (m_syncingNeededBlocks.empty() != (!m_syncingLastReceivedHash)) - return false; + BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("Received hashes but the hashes list is empty (or the other way around)")); } if (m_state == SyncState::Blocks || m_state == SyncState::NewBlocks) { bool blocks = false; host().foreachPeer([&](std::shared_ptr _p) { if (_p->m_asking == Asking::Blocks) blocks = true; return !blocks; }); if (!blocks) - return false; + BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("No peers asking for blocks")); if (downloadMan().isComplete()) - return false; - } - if (m_state == SyncState::Idle) - { - bool busy = false; - host().foreachPeer([&](std::shared_ptr _p) { if (_p->m_asking != Asking::Nothing && _p->m_asking != Asking::State) busy = true; return !busy; }); - if (busy) + BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("Block download complete but the state is still Blocks")); return false; } if (m_state == SyncState::Waiting && !host().bq().isActive()) - return false; + BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("Waiting while block queue is idle")); return true; } @@ -1085,19 +1079,15 @@ bool PV61Sync::isPV61Syncing() const bool PV61Sync::invariants() const { if (m_downloadingChainMap.size() != m_chainSyncPeers.size()) - return false; - if (m_state == SyncState::Idle && isSyncing()) - return false; - if (m_state != SyncState::Idle && !isSyncing()) - return false; + BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("m_downloadingChainMap and m_chainSyncPeers out of sync")); if (m_state == SyncState::Hashes) { bool hashes = false; host().foreachPeer([&](std::shared_ptr _p) { if (_p->m_asking == Asking::Hashes) hashes = true; return !hashes; }); if (!hashes) - return false; + BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("No peers asking for hashes")); if (isPV61Syncing() && !m_syncingBlockNumber) - return false; + BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("Syncing in PV61 with no block number set")); } else if (!PV60Sync::invariants()) return false; diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp index 9e7dd6898..e8565fafc 100644 --- a/libethereum/EthereumPeer.cpp +++ b/libethereum/EthereumPeer.cpp @@ -392,9 +392,9 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r) return false; } } - catch (Exception const& _e) + catch (Exception const&) { - clog(NetWarn) << "Peer causing an Exception:" << _e.what() << _r; + clog(NetWarn) << "Peer causing an Exception:" << boost::current_exception_diagnostic_information() << _r; } catch (std::exception const& _e) { From fc9d28081b52955d0a78955a16795459207be968 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 30 Jun 2015 18:23:18 +0200 Subject: [PATCH 050/290] removed extra status field for pv61 --- libethereum/EthereumPeer.cpp | 23 +++-------------------- libethereum/EthereumPeer.h | 2 -- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp index e8565fafc..1ad4aec7b 100644 --- a/libethereum/EthereumPeer.cpp +++ b/libethereum/EthereumPeer.cpp @@ -127,14 +127,12 @@ void EthereumPeer::requestStatus() m_requireTransactions = true; RLPStream s; bool latest = m_peerCapabilityVersion == host()->protocolVersion(); - prep(s, StatusPacket, latest ? 6 : 5) + prep(s, StatusPacket, 5) << (latest ? host()->protocolVersion() : EthereumHost::c_oldProtocolVersion) << host()->networkId() << host()->chain().details().totalDifficulty << host()->chain().currentHash() << host()->chain().genesisHash(); - if (latest) - s << u256(host()->chain().number()); sealAndSend(s); } @@ -214,12 +212,8 @@ void EthereumPeer::tick() auto s = session(); time_t now = std::chrono::system_clock::to_time_t(chrono::system_clock::now()); if (s && (now - m_lastAsk > 10 && m_asking != Asking::Nothing)) - { - clog(NetWarn) << "timeout: " << (now - m_lastAsk) << " " << - (m_asking == Asking::Nothing ? "nothing" : m_asking == Asking::State ? "state" : m_asking == Asking::Hashes ? "hashes" : m_asking == Asking::Blocks ? "blocks" : "?"); // timeout s->disconnect(PingTimeout); - } } bool EthereumPeer::isConversing() const @@ -247,20 +241,9 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r) m_latestHash = _r[3].toHash(); m_genesisHash = _r[4].toHash(); if (m_peerCapabilityVersion == host()->protocolVersion()) - { - if (_r.itemCount() != 6) - { - clog(NetImpolite) << "Peer does not support PV61+ status extension."; - m_protocolVersion = EthereumHost::c_oldProtocolVersion; - } - else - { - m_protocolVersion = host()->protocolVersion(); - m_latestBlockNumber = _r[5].toInt(); - } - } + m_protocolVersion = host()->protocolVersion(); - clog(NetMessageSummary) << "Status:" << m_protocolVersion << "/" << m_networkId << "/" << m_genesisHash << "/" << m_latestBlockNumber << ", TD:" << m_totalDifficulty << "=" << m_latestHash; + clog(NetMessageSummary) << "Status:" << m_protocolVersion << "/" << m_networkId << "/" << m_genesisHash << ", TD:" << m_totalDifficulty << "=" << m_latestHash; setIdle(); host()->onPeerStatus(dynamic_pointer_cast(dynamic_pointer_cast(shared_from_this()))); break; diff --git a/libethereum/EthereumPeer.h b/libethereum/EthereumPeer.h index faf3a0650..ef9fa542a 100644 --- a/libethereum/EthereumPeer.h +++ b/libethereum/EthereumPeer.h @@ -142,8 +142,6 @@ private: h256 m_latestHash; ///< Peer's latest block's hash that we know about or default null value if no need to sync. u256 m_totalDifficulty; ///< Peer's latest block's total difficulty. h256 m_genesisHash; ///< Peer's genesis hash - u256 m_latestBlockNumber; ///< Number of the latest block this peer has - /// This is built as we ask for hashes. Once no more hashes are given, we present this to the /// host who initialises the DownloadMan and m_sub becomes active for us to begin asking for blocks. From c438d60ae8353ef9f9424e619886603ce684052c Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 29 Jun 2015 22:19:24 +0200 Subject: [PATCH 051/290] removed obsolete invariant --- libethereum/BlockChainSync.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 7fa4a574d..88b68f614 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -813,7 +813,6 @@ bool PV60Sync::invariants() const BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("No peers asking for blocks")); if (downloadMan().isComplete()) BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("Block download complete but the state is still Blocks")); - return false; } if (m_state == SyncState::Waiting && !host().bq().isActive()) BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("Waiting while block queue is idle")); From 307c14dfbb4d37922d4e76a758bd8bf3165d6b26 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 30 Jun 2015 19:11:04 +0200 Subject: [PATCH 052/290] more invariant diagnostics --- libethereum/BlockQueue.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index 074278d9a..a09c2e320 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -21,6 +21,7 @@ #include "BlockQueue.h" #include +#include #include #include #include @@ -471,7 +472,13 @@ void BlockQueue::drain(VerifiedBlocks& o_out, unsigned _max) bool BlockQueue::invariants() const { Guard l(m_verification); - return m_readySet.size() == m_verified.size() + m_unverified.size() + m_verifying.size(); + if (!(m_readySet.size() == m_verified.size() + m_unverified.size() + m_verifying.size())) + { + std::stringstream s; + s << "Failed BlockQueue invariant: m_readySet: " << m_readySet.size() << " m_verified: " << m_verified.size() << " m_unverified: " << m_unverified.size() << " m_verifying" << m_verifying.size(); + BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment(s.str())); + } + return true; } void BlockQueue::noteReady_WITH_LOCK(h256 const& _good) From 2a31247150cc688513ea8b86e52bb5f4545dd141 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 30 Jun 2015 19:57:04 +0200 Subject: [PATCH 053/290] diable peers giving bad chain hashes --- libethereum/BlockChainSync.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 88b68f614..7368d7632 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -141,7 +141,10 @@ void BlockChainSync::onPeerBlocks(std::shared_ptr _peer, RLP const clog(NetMessageSummary) << "Blocks (" << dec << itemCount << "entries)" << (itemCount ? "" : ": NoMoreBlocks"); if (m_state != SyncState::Blocks && m_state != SyncState::NewBlocks && m_state != SyncState::Waiting) - clog(NetWarn) << "Unexpected Blocks received!"; + { + clog(NetMessageSummary) << "Ignoring unexpected blocks"; + return; + } if (m_state == SyncState::Waiting) { clog(NetAllDetail) << "Ignored blocks while waiting"; @@ -182,6 +185,7 @@ void BlockChainSync::onPeerBlocks(std::shared_ptr _peer, RLP const case ImportResult::BadChain: logNewBlock(h); _peer->disable("Malformed block received."); + restartSync(); return; case ImportResult::FutureTimeKnown: @@ -691,7 +695,8 @@ void PV60Sync::onPeerHashes(std::shared_ptr _peer, h256s const& _h else if (status == QueueStatus::Bad) { cwarn << "block hash bad!" << h << ". Bailing..."; - transition(_peer, SyncState::Idle); + _peer->disable("Bad blocks"); + restartSync(); return; } else if (status == QueueStatus::Unknown) @@ -1006,6 +1011,7 @@ void PV61Sync::onPeerHashes(std::shared_ptr _peer, h256s const& _h else if (status == QueueStatus::Bad) { cwarn << "block hash bad!" << h << ". Bailing..."; + _peer->disable("Bad blocks"); restartSync(); return; } From bd62db0f4a763cd241854f58a35d49ebe5300884 Mon Sep 17 00:00:00 2001 From: Dimitry Khokhlov Date: Tue, 30 Jun 2015 22:35:55 +0400 Subject: [PATCH 054/290] FuzzTest: a few more random code --- test/fuzzTesting/fuzzHelper.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/test/fuzzTesting/fuzzHelper.cpp b/test/fuzzTesting/fuzzHelper.cpp index 8e03bd767..158dd2798 100644 --- a/test/fuzzTesting/fuzzHelper.cpp +++ b/test/fuzzTesting/fuzzHelper.cpp @@ -143,16 +143,31 @@ std::string RandomCode::fillArguments(dev::eth::Instruction _opcode, RandomCodeO { switch (_opcode) { + case dev::eth::Instruction::CREATE: + //(CREATE value mem1 mem2) + code += getPushCode(randUniIntGen() % 128); //memlen1 + code += getPushCode(randUniIntGen() % 32); //memlen1 + code += getPushCode(randUniIntGen()); //value + break; case dev::eth::Instruction::CALL: + case dev::eth::Instruction::CALLCODE: //(CALL gaslimit address value memstart1 memlen1 memstart2 memlen2) - code += getPushCode(randUniIntGen() % 32); //memlen2 + //(CALLCODE gaslimit address value memstart1 memlen1 memstart2 memlen2) + code += getPushCode(randUniIntGen() % 128); //memlen2 code += getPushCode(randUniIntGen() % 32); //memstart2 - code += getPushCode(randUniIntGen() % 32); //memlen1 + code += getPushCode(randUniIntGen() % 128); //memlen1 code += getPushCode(randUniIntGen() % 32); //memlen1 code += getPushCode(randUniIntGen()); //value code += getPushCode(toString(_options.getRandomAddress()));//address code += getPushCode(randUniIntGen()); //gaslimit break; + case dev::eth::Instruction::SUICIDE: //(SUICIDE address) + code += getPushCode(toString(_options.getRandomAddress())); + break; + case dev::eth::Instruction::RETURN: //(RETURN memlen1 memlen2) + code += getPushCode(randUniIntGen() % 128); //memlen1 + code += getPushCode(randUniIntGen() % 32); //memlen1 + break; default: smart = false; } From 8afa6e1c464f8d515601fd617a750b8c65d68640 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 30 Jun 2015 23:00:15 +0200 Subject: [PATCH 055/290] add watchers.qml & KeyValuePanel.qml --- mix/ClientModel.cpp | 12 +++++++ mix/ClientModel.h | 2 ++ mix/qml/Block.qml | 4 +++ mix/qml/BlockChain.qml | 22 ++++++++++++ mix/qml/KeyValuePanel.qml | 66 +++++++++++++++++++++++++++++++++++ mix/qml/ScenarioExecution.qml | 24 ++++++++++++- mix/qml/Watchers.qml | 59 +++++++++++++++++++++++++++++++ 7 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 mix/qml/KeyValuePanel.qml create mode 100644 mix/qml/Watchers.qml diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index e07641db8..931f53e20 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -840,6 +840,18 @@ void ClientModel::onNewTransaction() gasUsed, sender, label, inputParameters, logs); QQmlEngine::setObjectOwnership(log, QQmlEngine::JavaScriptOwnership); emit newRecord(log); + QVariantMap accountBalances; + for (auto const& ctr : m_contractAddresses) + { + u256 wei = m_client.balanceAt(ctr); + accountBalances.insert(ctr, wei); + } + for (auto const& account : m_account) + { + u256 wei = m_client.balanceAt(account); + accountBalances.insert(ctr, wei); + } + emit newState(recordIndex, accountBalances); } } diff --git a/mix/ClientModel.h b/mix/ClientModel.h index b5b783b3d..b63489ddf 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -236,6 +236,8 @@ signals: void newRecord(RecordLogEntry* _r); /// State (transaction log) cleared void stateCleared(); + /// new state has been processed + void newState(unsigned _record, QVariantMap _accounts); private: RecordLogEntry* lastBlock() const; diff --git a/mix/qml/Block.qml b/mix/qml/Block.qml index 75d34a766..47edd8388 100644 --- a/mix/qml/Block.qml +++ b/mix/qml/Block.qml @@ -22,6 +22,7 @@ ColumnLayout property int blockIndex property variant scenario property string labelColor: "#414141" + signal txSelected(var txIndex) function calculateHeight() { @@ -204,9 +205,12 @@ ColumnLayout anchors.fill: parent onDoubleClicked: { + /* transactionDialog.stateAccounts = scenario.accounts transactionDialog.execute = false transactionDialog.open(index, blockIndex, transactions.get(index)) + */ + txSelected(index) } } diff --git a/mix/qml/BlockChain.qml b/mix/qml/BlockChain.qml index 02ff72be2..840bff766 100644 --- a/mix/qml/BlockChain.qml +++ b/mix/qml/BlockChain.qml @@ -14,11 +14,13 @@ import "." ColumnLayout { id: blockChainPanel property variant model + property var states: {} spacing: 0 property int previousWidth property variant debugTrRequested: [] signal chainChanged signal chainReloaded + signal txSelected(var blockIndex, var txIndex) Connections { @@ -54,6 +56,11 @@ ColumnLayout { previousWidth = width } + function state(record) + { + return states[record] + } + function load(scenario) { if (!scenario) @@ -61,6 +68,7 @@ ColumnLayout { if (model) rebuild.startBlinking() model = scenario + states = [] blockModel.clear() for (var b in model.blocks) blockModel.append(model.blocks[b]) @@ -164,6 +172,14 @@ ColumnLayout { model: blockModel Block { + Connections + { + target: block + onTxSelected: { + txSelected(index, txIndex) + } + } + id: block scenario: blockChainPanel.model Layout.preferredWidth: blockChainScrollView.width Layout.preferredHeight: @@ -271,6 +287,7 @@ ColumnLayout { if (ensureNotFuturetime.running) return; stopBlinking() + states = [] var retBlocks = []; var bAdded = 0; for (var j = 0; j < model.blocks.length; j++) @@ -475,6 +492,11 @@ ColumnLayout { model.blocks[model.blocks.length - 1].transactions.push(itemTr) blockModel.appendTransaction(itemTr) } + + onNewState: { + states[_record] = _accounts + } + onMiningComplete: { } diff --git a/mix/qml/KeyValuePanel.qml b/mix/qml/KeyValuePanel.qml new file mode 100644 index 000000000..cf16a42aa --- /dev/null +++ b/mix/qml/KeyValuePanel.qml @@ -0,0 +1,66 @@ +import QtQuick 2.2 +import QtQuick.Controls 1.1 +import QtQuick.Controls.Styles 1.1 +import QtQuick.Dialogs 1.1 +import QtQuick.Layouts 1.1 +import Qt.labs.settings 1.0 +import org.ethereum.qml.QEther 1.0 +import "js/Debugger.js" as Debugger +import "js/ErrorLocationFormater.js" as ErrorLocationFormater +import "js/TransactionHelper.js" as TransactionHelper +import "js/QEtherHelper.js" as QEtherHelper +import "." + +ColumnLayout { + id: root + property alias title: titleLabel.text + property variant data + + function key(index) + { + } + + function value(index) + { + } + + RowLayout + { + Label + { + id: titleLabel + } + } + + RowLayout + { + Repeater + { + id: repeaterKeyValue + RowLayout + { + Rectangle + { + id: key + Label + { + text: { + return root.key(index) + } + } + } + Rectangle + { + id: value + Label + { + text: { + return root.value(index) + } + } + } + } + } + } +} + diff --git a/mix/qml/ScenarioExecution.qml b/mix/qml/ScenarioExecution.qml index 3e9d8e089..65e4d5d94 100644 --- a/mix/qml/ScenarioExecution.qml +++ b/mix/qml/ScenarioExecution.qml @@ -18,11 +18,11 @@ Rectangle { onProjectLoaded: { loader.init() } - } Column { + id: scenarioColumn anchors.margins: 10 anchors.fill: parent spacing: 10 @@ -63,5 +63,27 @@ Rectangle { id: blockChain width: parent.width } + + Connections + { + target: blockChain + onTxSelected:{ + var tx = model.block[blockIndex].transactions[txIndex] + var state = blockChain.getState(tx.recordIndex) + watchers.updateWidthTx(tx, state) + } + } + } + + ScrollView + { + anchors.top: scenarioColumn.bottom + width: parent.width + height: 500 + Watchers + { + id: watchers + anchors.topMargin: 10 + } } } diff --git a/mix/qml/Watchers.qml b/mix/qml/Watchers.qml new file mode 100644 index 000000000..5cdc65846 --- /dev/null +++ b/mix/qml/Watchers.qml @@ -0,0 +1,59 @@ +import QtQuick 2.2 +import QtQuick.Controls 1.1 +import QtQuick.Controls.Styles 1.1 +import QtQuick.Dialogs 1.1 +import QtQuick.Layouts 1.1 +import Qt.labs.settings 1.0 +import org.ethereum.qml.QEther 1.0 +import "js/Debugger.js" as Debugger +import "js/ErrorLocationFormater.js" as ErrorLocationFormater +import "js/TransactionHelper.js" as TransactionHelper +import "js/QEtherHelper.js" as QEtherHelper +import "." + +ColumnLayout { + + property variant tx + property variant state + + function updateWidthTx(_tx, _state) + { + console.log("update tx") + console.log(JSON.stringify(tx)) + console.log(JSON.stringify(state)) + txLabel.text = tx.label + tx = _tx + state = _state + } + + RowLayout + { + Label { + id: txLabel + } + } + + KeyValuePanel + { + id: inputParams + title: qsTr("INPUT PARAMETERS") + } + + KeyValuePanel + { + id: returnParams + title: qsTr("RETURN PARAMETERS") + } + + KeyValuePanel + { + id: balance + title: qsTr("BALANCES") + } + + KeyValuePanel + { + id: events + title: qsTr("EVENTS") + } +} From a586e2cafe30ca0cd8c1a88dabbe1d01cf5623ad Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 30 Jun 2015 23:04:07 +0200 Subject: [PATCH 056/290] blocks no longer stuck in verifying state --- libethereum/BlockQueue.cpp | 41 ++++++++++++++++++++------------------ libethereum/BlockQueue.h | 1 + 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index 074278d9a..30ae65ed2 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -114,15 +114,11 @@ void BlockQueue::verifierBody() catch (...) { // bad block. - { - // has to be this order as that's how invariants() assumes. - WriteGuard l2(m_lock); - unique_lock l(m_verification); - m_readySet.erase(work.hash); - m_knownBad.insert(work.hash); - } - + // has to be this order as that's how invariants() assumes. + WriteGuard l2(m_lock); unique_lock l(m_verification); + m_readySet.erase(work.hash); + m_knownBad.insert(work.hash); for (auto it = m_verifying.begin(); it != m_verifying.end(); ++it) if (it->verified.info.mixHash == work.hash) { @@ -131,6 +127,7 @@ void BlockQueue::verifierBody() } cwarn << "BlockQueue missing our job: was there a GM?"; OK1:; + drainVerified(); continue; } @@ -149,17 +146,8 @@ void BlockQueue::verifierBody() } else m_verified.emplace_back(move(res)); - while (m_verifying.size() && !m_verifying.front().blockData.empty()) - { - if (m_knownBad.count(m_verifying.front().verified.info.parentHash)) - { - m_readySet.erase(m_verifying.front().verified.info.hash()); - m_knownBad.insert(res.verified.info.hash()); - } - else - m_verified.emplace_back(move(m_verifying.front())); - m_verifying.pop_front(); - } + + drainVerified(); ready = true; } else @@ -179,6 +167,21 @@ void BlockQueue::verifierBody() } } +void BlockQueue::drainVerified() +{ + while (m_verifying.size() && !m_verifying.front().blockData.empty()) + { + if (m_knownBad.count(m_verifying.front().verified.info.parentHash)) + { + m_readySet.erase(m_verifying.front().verified.info.hash()); + m_knownBad.insert(m_verifying.front().verified.info.hash()); + } + else + m_verified.emplace_back(move(m_verifying.front())); + m_verifying.pop_front(); + } +} + ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, bool _isOurs) { // Check if we already know this block. diff --git a/libethereum/BlockQueue.h b/libethereum/BlockQueue.h index 137048ec4..82547cd56 100644 --- a/libethereum/BlockQueue.h +++ b/libethereum/BlockQueue.h @@ -134,6 +134,7 @@ private: bool invariants() const override; void verifierBody(); + void drainVerified(); void collectUnknownBad(h256 const& _bad); void updateBad(h256 const& _bad); From 7a5b4db728135bc7ea8784617159a224a6c4ea3c Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 1 Jul 2015 09:13:55 +0200 Subject: [PATCH 057/290] Minor renaming in BlockQueue, remove unnecessary invariant check, add additional one. --- libethash-cl/ethash_cl_miner.cpp | 1 + libethereum/BlockQueue.cpp | 19 +++++++++---------- libethereum/BlockQueue.h | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index ec400f7a7..b4ef12cb5 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -495,6 +495,7 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook pending.pop(); } + (void)_msPerBatch; /* chrono::high_resolution_clock::duration d = chrono::high_resolution_clock::now() - t; if (d > chrono::milliseconds(_msPerBatch * 10 / 9)) { diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index 9e647c9c1..4eeeac066 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -242,7 +242,7 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo if (m_knownBad.count(bi.parentHash)) { m_knownBad.insert(bi.hash()); - updateBad(bi.hash()); + updateBad_WITH_LOCK(bi.hash()); // bad parent; this is bad too, note it as such return ImportResult::BadChain; } @@ -277,12 +277,12 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo } } -void BlockQueue::updateBad(h256 const& _bad) +void BlockQueue::updateBad_WITH_LOCK(h256 const& _bad) { DEV_INVARIANT_CHECK; DEV_GUARDED(m_verification) { - collectUnknownBad(_bad); + collectUnknownBad_WITH_BOTH_LOCKS(_bad); bool moreBad = true; while (moreBad) { @@ -294,7 +294,7 @@ void BlockQueue::updateBad(h256 const& _bad) { m_knownBad.insert(b.verified.info.hash()); m_readySet.erase(b.verified.info.hash()); - collectUnknownBad(b.verified.info.hash()); + collectUnknownBad_WITH_BOTH_LOCKS(b.verified.info.hash()); moreBad = true; } else @@ -307,7 +307,7 @@ void BlockQueue::updateBad(h256 const& _bad) { m_knownBad.insert(b.hash); m_readySet.erase(b.hash); - collectUnknownBad(b.hash); + collectUnknownBad_WITH_BOTH_LOCKS(b.hash); moreBad = true; } else @@ -321,18 +321,18 @@ void BlockQueue::updateBad(h256 const& _bad) h256 const& h = b.blockData.size() != 0 ? b.verified.info.hash() : b.verified.info.mixHash; m_knownBad.insert(h); m_readySet.erase(h); - collectUnknownBad(h); + collectUnknownBad_WITH_BOTH_LOCKS(h); moreBad = true; } else m_verifying.push_back(std::move(b)); } } - DEV_INVARIANT_CHECK; } -void BlockQueue::collectUnknownBad(h256 const& _bad) +void BlockQueue::collectUnknownBad_WITH_BOTH_LOCKS(h256 const& _bad) { + DEV_INVARIANT_CHECK; list badQueue(1, _bad); while (!badQueue.empty()) { @@ -349,7 +349,6 @@ void BlockQueue::collectUnknownBad(h256 const& _bad) } m_unknown.erase(r.first, r.second); } - } bool BlockQueue::doneDrain(h256s const& _bad) @@ -364,7 +363,7 @@ bool BlockQueue::doneDrain(h256s const& _bad) // at least one of them was bad. m_knownBad += _bad; for (h256 const& b : _bad) - updateBad(b); + updateBad_WITH_LOCK(b); } return !m_readySet.empty(); } diff --git a/libethereum/BlockQueue.h b/libethereum/BlockQueue.h index 137048ec4..e42b6a3bd 100644 --- a/libethereum/BlockQueue.h +++ b/libethereum/BlockQueue.h @@ -134,8 +134,8 @@ private: bool invariants() const override; void verifierBody(); - void collectUnknownBad(h256 const& _bad); - void updateBad(h256 const& _bad); + void collectUnknownBad_WITH_BOTH_LOCKS(h256 const& _bad); + void updateBad_WITH_LOCK(h256 const& _bad); mutable boost::shared_mutex m_lock; ///< General lock for the sets, m_future and m_unknown. h256Hash m_drainingSet; ///< All blocks being imported. From 3c78f0f9519f02a794b562e4873eacad075f134d Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 1 Jul 2015 09:42:03 +0200 Subject: [PATCH 058/290] Better logging/descriptive exceptions on invariants. --- libdevcore/Common.cpp | 9 ++++++--- libdevcore/Common.h | 16 +++++++++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index e33936102..5450f9311 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -32,10 +32,13 @@ char const* Version = "0.9.27"; const u256 UndefinedU256 = ~(u256)0; -void HasInvariants::checkInvariants() const +void InvariantChecker::checkInvariants() const { - if (!invariants()) - BOOST_THROW_EXCEPTION(FailedInvariant()); + if (!m_this->invariants()) + { + cwarn << "Invariant failed in" << m_function << "at" << m_file << ":" << m_line; + ::boost::exception_detail::throw_exception_(FailedInvariant(), m_function, m_file, m_line); + } } struct TimerChannel: public LogChannel { static const char* name(); static const int verbosity = 0; }; diff --git a/libdevcore/Common.h b/libdevcore/Common.h index f1d35bbc7..a3ab374a6 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -163,10 +163,6 @@ private: class HasInvariants { public: - /// Check invariants are met, throw if not. - void checkInvariants() const; - -protected: /// Reimplement to specify the invariants. virtual bool invariants() const = 0; }; @@ -175,16 +171,22 @@ protected: class InvariantChecker { public: - InvariantChecker(HasInvariants* _this): m_this(_this) { m_this->checkInvariants(); } - ~InvariantChecker() { m_this->checkInvariants(); } + InvariantChecker(HasInvariants* _this, char const* _fn, char const* _file, int _line): m_this(_this), m_function(_fn), m_file(_file), m_line(_line) { checkInvariants(); } + ~InvariantChecker() { checkInvariants(); } private: + /// Check invariants are met, throw if not. + void checkInvariants() const; + HasInvariants const* m_this; + char const* m_function; + char const* m_file; + int m_line; }; /// Scope guard for invariant check in a class derived from HasInvariants. #if ETH_DEBUG -#define DEV_INVARIANT_CHECK { ::dev::InvariantChecker __dev_invariantCheck(this); } +#define DEV_INVARIANT_CHECK { ::dev::InvariantChecker __dev_invariantCheck(this, BOOST_THROW_EXCEPTION_CURRENT_FUNCTION, __FILE__, __LINE__); } #else #define DEV_INVARIANT_CHECK (void)0; #endif From 7a0f3350b6f13a47640eaff414679bf1f9494187 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 1 Jul 2015 11:05:45 +0200 Subject: [PATCH 059/290] Fix importing. --- eth/main.cpp | 1 + libethereum/BlockQueue.cpp | 1 + libethereum/Client.cpp | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/eth/main.cpp b/eth/main.cpp index 4361598d4..0ccba6fca 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -827,6 +827,7 @@ int main(int argc, char** argv) cout << i << " more imported at " << (round(i * 10 / d) / 10) << " blocks/s. " << imported << " imported in " << e << " seconds at " << (round(imported * 10 / e) / 10) << " blocks/s (#" << web3.ethereum()->number() << ")" << endl; last = (unsigned)e; lastImported = imported; +// cout << web3.ethereum()->blockQueueStatus() << endl; } } diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index deeae9773..eb2cfbcab 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -181,6 +181,7 @@ void BlockQueue::verifierBody() ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, bool _isOurs) { + cdebug << std::this_thread::get_id(); // Check if we already know this block. h256 h = BlockInfo::headerHash(_block); diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 2b0a64491..bb7e6d993 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -89,13 +89,14 @@ void VersionChecker::setOk() ImportResult Client::queueBlock(bytes const& _block, bool _isSafe) { - if (m_bq.status().verified + m_bq.status().verifying + m_bq.status().unverified > 30000) + if (m_bq.status().verified + m_bq.status().verifying + m_bq.status().unverified > 500) this_thread::sleep_for(std::chrono::milliseconds(500)); return m_bq.import(&_block, bc(), _isSafe); } tuple Client::syncQueue(unsigned _max) { + stopWorking(); return m_bc.sync(m_bq, m_stateDB, _max); } From d2173cd47940d99666cbd0890fd932ddc1e1dc25 Mon Sep 17 00:00:00 2001 From: Dimitry Khokhlov Date: Wed, 1 Jul 2015 13:41:55 +0400 Subject: [PATCH 060/290] FuzzTests: More Smart Codes --- test/fuzzTesting/createRandomTest.cpp | 3 +- test/fuzzTesting/fuzzHelper.cpp | 117 +++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 3 deletions(-) diff --git a/test/fuzzTesting/createRandomTest.cpp b/test/fuzzTesting/createRandomTest.cpp index b4a00440e..c26c9b7f7 100644 --- a/test/fuzzTesting/createRandomTest.cpp +++ b/test/fuzzTesting/createRandomTest.cpp @@ -220,6 +220,7 @@ void parseTestWithTypes(std::string& _test) options.setWeight(dev::eth::Instruction::STOP, 10); //default 50 options.setWeight(dev::eth::Instruction::SSTORE, 70); options.setWeight(dev::eth::Instruction::CALL, 75); + options.setWeight(dev::eth::Instruction::CALLCODE, 55); options.addAddress(dev::Address("0xffffffffffffffffffffffffffffffffffffffff")); options.addAddress(dev::Address("0x1000000000000000000000000000000000000000")); options.addAddress(dev::Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87")); @@ -230,7 +231,7 @@ void parseTestWithTypes(std::string& _test) options.addAddress(dev::Address("0x0000000000000000000000000000000000000002")); options.addAddress(dev::Address("0x0000000000000000000000000000000000000003")); options.addAddress(dev::Address("0x0000000000000000000000000000000000000004")); - options.smartCodeProbability = 35; + options.smartCodeProbability = 60; std::vector types = getTypes(); for (unsigned i = 0; i < types.size(); i++) diff --git a/test/fuzzTesting/fuzzHelper.cpp b/test/fuzzTesting/fuzzHelper.cpp index 158dd2798..de7f56dc9 100644 --- a/test/fuzzTesting/fuzzHelper.cpp +++ b/test/fuzzTesting/fuzzHelper.cpp @@ -84,9 +84,17 @@ std::string RandomCode::generate(int _maxOpNumber, RandomCodeOptions _options) } } else + { + if (info.name.find_first_of("PUSH") > 0) + code += toCompactHex(opcode); code += fillArguments((dev::eth::Instruction) opcode, _options); - std::string byte = toCompactHex(opcode); - code += (byte == "") ? "00" : byte; + } + + if (info.name.find_first_of("PUSH") <= 0) + { + std::string byte = toCompactHex(opcode); + code += (byte == "") ? "00" : byte; + } } return code; } @@ -143,6 +151,111 @@ std::string RandomCode::fillArguments(dev::eth::Instruction _opcode, RandomCodeO { switch (_opcode) { + case dev::eth::Instruction::PUSH1: code += rndByteSequence(1); break; + case dev::eth::Instruction::PUSH2: code += rndByteSequence(2); break; + case dev::eth::Instruction::PUSH3: code += rndByteSequence(3); break; + case dev::eth::Instruction::PUSH4: code += rndByteSequence(4); break; + case dev::eth::Instruction::PUSH5: code += rndByteSequence(5); break; + case dev::eth::Instruction::PUSH6: code += rndByteSequence(6); break; + case dev::eth::Instruction::PUSH7: code += rndByteSequence(7); break; + case dev::eth::Instruction::PUSH8: code += rndByteSequence(8); break; + case dev::eth::Instruction::PUSH9: code += rndByteSequence(9); break; + case dev::eth::Instruction::PUSH10: code += rndByteSequence(10); break; + case dev::eth::Instruction::PUSH11: code += rndByteSequence(11); break; + case dev::eth::Instruction::PUSH12: code += rndByteSequence(12); break; + case dev::eth::Instruction::PUSH13: code += rndByteSequence(13); break; + case dev::eth::Instruction::PUSH14: code += rndByteSequence(14); break; + case dev::eth::Instruction::PUSH15: code += rndByteSequence(15); break; + case dev::eth::Instruction::PUSH16: code += rndByteSequence(16); break; + case dev::eth::Instruction::PUSH17: code += rndByteSequence(17); break; + case dev::eth::Instruction::PUSH18: code += rndByteSequence(18); break; + case dev::eth::Instruction::PUSH19: code += rndByteSequence(19); break; + case dev::eth::Instruction::PUSH20: code += rndByteSequence(20); break; + case dev::eth::Instruction::PUSH21: code += rndByteSequence(21); break; + case dev::eth::Instruction::PUSH22: code += rndByteSequence(22); break; + case dev::eth::Instruction::PUSH23: code += rndByteSequence(23); break; + case dev::eth::Instruction::PUSH24: code += rndByteSequence(24); break; + case dev::eth::Instruction::PUSH25: code += rndByteSequence(25); break; + case dev::eth::Instruction::PUSH26: code += rndByteSequence(26); break; + case dev::eth::Instruction::PUSH27: code += rndByteSequence(27); break; + case dev::eth::Instruction::PUSH28: code += rndByteSequence(28); break; + case dev::eth::Instruction::PUSH29: code += rndByteSequence(29); break; + case dev::eth::Instruction::PUSH30: code += rndByteSequence(30); break; + case dev::eth::Instruction::PUSH31: code += rndByteSequence(31); break; + case dev::eth::Instruction::PUSH32: code += rndByteSequence(32); break; + case dev::eth::Instruction::SWAP1: + case dev::eth::Instruction::SWAP2: + case dev::eth::Instruction::SWAP3: + case dev::eth::Instruction::SWAP4: + case dev::eth::Instruction::SWAP5: + case dev::eth::Instruction::SWAP6: + case dev::eth::Instruction::SWAP7: + case dev::eth::Instruction::SWAP8: + case dev::eth::Instruction::SWAP9: + case dev::eth::Instruction::SWAP10: + case dev::eth::Instruction::SWAP11: + case dev::eth::Instruction::SWAP12: + case dev::eth::Instruction::SWAP13: + case dev::eth::Instruction::SWAP14: + case dev::eth::Instruction::SWAP15: + case dev::eth::Instruction::SWAP16: + case dev::eth::Instruction::DUP1: + case dev::eth::Instruction::DUP2: + case dev::eth::Instruction::DUP3: + case dev::eth::Instruction::DUP4: + case dev::eth::Instruction::DUP5: + case dev::eth::Instruction::DUP6: + case dev::eth::Instruction::DUP7: + case dev::eth::Instruction::DUP8: + case dev::eth::Instruction::DUP9: + case dev::eth::Instruction::DUP10: + case dev::eth::Instruction::DUP11: + case dev::eth::Instruction::DUP12: + case dev::eth::Instruction::DUP13: + case dev::eth::Instruction::DUP14: + case dev::eth::Instruction::DUP15: + case dev::eth::Instruction::DUP16: + int times; + switch (_opcode) + { + case dev::eth::Instruction::DUP1: times = 1; break; + case dev::eth::Instruction::SWAP1: + case dev::eth::Instruction::DUP2: times = 2; break; + case dev::eth::Instruction::SWAP2: + case dev::eth::Instruction::DUP3: times = 3; break; + case dev::eth::Instruction::SWAP3: + case dev::eth::Instruction::DUP4: times = 4; break; + case dev::eth::Instruction::SWAP4: + case dev::eth::Instruction::DUP5: times = 5; break; + case dev::eth::Instruction::SWAP5: + case dev::eth::Instruction::DUP6: times = 6; break; + case dev::eth::Instruction::SWAP6: + case dev::eth::Instruction::DUP7: times = 7; break; + case dev::eth::Instruction::SWAP7: + case dev::eth::Instruction::DUP8: times = 8; break; + case dev::eth::Instruction::SWAP8: + case dev::eth::Instruction::DUP9: times = 9; break; + case dev::eth::Instruction::SWAP9: + case dev::eth::Instruction::DUP10: times = 10; break; + case dev::eth::Instruction::SWAP10: + case dev::eth::Instruction::DUP11: times = 11; break; + case dev::eth::Instruction::SWAP11: + case dev::eth::Instruction::DUP12: times = 12; break; + case dev::eth::Instruction::SWAP12: + case dev::eth::Instruction::DUP13: times = 13; break; + case dev::eth::Instruction::SWAP13: + case dev::eth::Instruction::DUP14: times = 14; break; + case dev::eth::Instruction::SWAP14: + case dev::eth::Instruction::DUP15: times = 15; break; + case dev::eth::Instruction::SWAP15: + case dev::eth::Instruction::DUP16: times = 16; break; + case dev::eth::Instruction::SWAP16: times = 17; break; + default: times = 1; + } + for (int i = 0; i < times; i ++) + code += getPushCode(randUniIntGen() % 32); + + break; case dev::eth::Instruction::CREATE: //(CREATE value mem1 mem2) code += getPushCode(randUniIntGen() % 128); //memlen1 From 7ba71da2806ac8e9fbf58b65bc6435660a3c4b0b Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 1 Jul 2015 11:47:34 +0200 Subject: [PATCH 061/290] style --- libethereum/BlockQueue.cpp | 8 ++++---- libethereum/BlockQueue.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index 30ae65ed2..344ee0609 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -127,7 +127,7 @@ void BlockQueue::verifierBody() } cwarn << "BlockQueue missing our job: was there a GM?"; OK1:; - drainVerified(); + drainVerified_WITH_BOTH_LOCKS(); continue; } @@ -147,7 +147,7 @@ void BlockQueue::verifierBody() else m_verified.emplace_back(move(res)); - drainVerified(); + drainVerified_WITH_BOTH_LOCKS(); ready = true; } else @@ -167,9 +167,9 @@ void BlockQueue::verifierBody() } } -void BlockQueue::drainVerified() +void BlockQueue::drainVerified_WITH_BOTH_LOCKS() { - while (m_verifying.size() && !m_verifying.front().blockData.empty()) + while (!m_verifying.empty() && !m_verifying.front().blockData.empty()) { if (m_knownBad.count(m_verifying.front().verified.info.parentHash)) { diff --git a/libethereum/BlockQueue.h b/libethereum/BlockQueue.h index 82547cd56..18446c613 100644 --- a/libethereum/BlockQueue.h +++ b/libethereum/BlockQueue.h @@ -134,7 +134,7 @@ private: bool invariants() const override; void verifierBody(); - void drainVerified(); + void drainVerified_WITH_BOTH_LOCKS(); void collectUnknownBad(h256 const& _bad); void updateBad(h256 const& _bad); From 91452da11d0828844267e7ce95f99807a08ae2b2 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 1 Jul 2015 12:02:17 +0200 Subject: [PATCH 062/290] Minor optimisations. --- libethereum/BlockChain.cpp | 2 +- libethereum/Client.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 4d05ea7db..47725e088 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -325,7 +325,7 @@ tuple BlockChain::sync(BlockQueue& _bq, OverlayDB c { // Nonce & uncle nonces already verified in verification thread at this point. ImportRoute r; - DEV_TIMED_ABOVE("Block import", 500) + DEV_TIMED_ABOVE("Block import " + toString(block.verified.info.number), 500) r = import(block.verified, _stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce & ~ImportRequirements::CheckUncles); fresh += r.liveBlocks; dead += r.deadBlocks; diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index bb7e6d993..c7d7c60c4 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -89,7 +89,7 @@ void VersionChecker::setOk() ImportResult Client::queueBlock(bytes const& _block, bool _isSafe) { - if (m_bq.status().verified + m_bq.status().verifying + m_bq.status().unverified > 500) + if (m_bq.status().verified + m_bq.status().verifying + m_bq.status().unverified > 10000) this_thread::sleep_for(std::chrono::milliseconds(500)); return m_bq.import(&_block, bc(), _isSafe); } From 057e374bce9b52e1911f3ac8c16293b7a18bcf84 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 1 Jul 2015 13:52:31 +0200 Subject: [PATCH 063/290] Remove unneeded dummy use. --- libethash-cl/ethash_cl_miner.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index c9e431db7..3a72810fa 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -497,7 +497,6 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook pending.pop(); } - (void)_msPerBatch; /* chrono::high_resolution_clock::duration d = chrono::high_resolution_clock::now() - t; if (d > chrono::milliseconds(_msPerBatch * 10 / 9)) { From 34b2767a59d74e08e8d73f59591eb375732c214b Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 1 Jul 2015 14:06:01 +0200 Subject: [PATCH 064/290] isKnown const& --- libethereum/ClientBase.cpp | 4 ++-- libethereum/ClientBase.h | 4 ++-- libethereum/Interface.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 3d4411505..d6d259380 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -481,7 +481,7 @@ int ClientBase::compareBlockHashes(h256 _h1, h256 _h2) const return -1; } -bool ClientBase::isKnown(h256 _hash) const +bool ClientBase::isKnown(h256 const& _hash) const { return _hash == PendingBlockHash || _hash == LatestBlockHash || @@ -496,7 +496,7 @@ bool ClientBase::isKnown(BlockNumber _block) const bc().numberHash(_block) != h256(); } -bool ClientBase::isKnownTransaction(h256 _transactionHash) const +bool ClientBase::isKnownTransaction(h256 const& _transactionHash) const { return bc().isKnownTransaction(_transactionHash); } diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index aac10ae60..d2d22a08f 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -149,9 +149,9 @@ public: /// Get the coinbase address virtual Address address() const override; - virtual bool isKnown(h256 _hash) const override; + virtual bool isKnown(h256 const& _hash) const override; virtual bool isKnown(BlockNumber _block) const override; - virtual bool isKnownTransaction(h256 _transactionHash) const override; + virtual bool isKnownTransaction(h256 const& _transactionHash) const override; /// TODO: consider moving it to a separate interface diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 1073b45ff..f24f1b5c3 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -133,7 +133,7 @@ public: // [BLOCK QUERY API] - virtual bool isKnownTransaction(h256 _transactionHash) const = 0; + virtual bool isKnownTransaction(h256 const& _transactionHash) const = 0; virtual Transaction transaction(h256 _transactionHash) const = 0; virtual std::pair transactionLocation(h256 const& _transactionHash) const = 0; virtual h256 hashFromNumber(BlockNumber _number) const = 0; @@ -141,7 +141,7 @@ public: virtual int compareBlockHashes(h256 _h1, h256 _h2) const = 0; virtual bool isKnown(BlockNumber _block) const = 0; - virtual bool isKnown(h256 _hash) const = 0; + virtual bool isKnown(h256 const& _hash) const = 0; virtual BlockInfo blockInfo(h256 _hash) const = 0; virtual BlockDetails blockDetails(h256 _hash) const = 0; virtual Transaction transaction(h256 _blockHash, unsigned _i) const = 0; From 1e652c0757b5440feb5ba32d46f8a887c32f57c2 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 1 Jul 2015 14:36:10 +0200 Subject: [PATCH 065/290] Squashed 'libjsqrc/ethereumjs/' changes from 2a0b46a..d5d2115 d5d2115 example contract using array, fixed #185 21ed235 removed connection keep-alive c44fe01 version 0.7.1 d9b785e fixed #248 490dde5 fixed encoding/decoding strings, #249 b3f5d09 fixed long bytes dynamic decoding/encoding, #249 d097821 small filter improvement d59b1cd removed xhr from browser 42b6e9d version 0.7.0 fe6defd gulp 44dcd24 set connection keepalive 2b17c0f gulpfile changes 4a46c73 Merge pull request #228 from ethereum/strings 93c8006 tests for encoding and decoding prematurely terminated strings and strings containing internal zeros 7dd44e7 Merge branch 'strings' of https://github.com/ethereum/ethereum.js into strings 390a9ff Merge branch 'develop' into strings bcd9cfb updated deps, removed unused karma ef15fc1 Merge pull request #244 from ethereum/allevents 6f74d57 Merge branch 'develop' into allevents 7aca17e Merge branch 'develop' into allevents c5ee34d fix for optional event parameters 8170a0a Merge pull request #245 from ethereum/filterInstantWatch 76a094c fixed all issues noted by marek d78b512 add possible callback to filters e1b17a9 re-build develop af9c027 all events filter b270616 version 0.6.1 c47d6a8 gulp 7cf7cf3 map file 6da1d3e gulp 450042e Update eth.js 3951286 Added sendRawTransaction 323b529 merged develop 16ffdf6 merged master ecf0a2c changed | to Math.floor d2b5ba2 Merge pull request #239 from ethereum/mistFixes 9e6bf9d removed browser XHR 9061116 fixed build issues in formatInputDynamicBytes 0e3b29c fixed coverage issue d51e9a2 merged latest develop f0247aa made meteor package available on the server side as well e97c5f5 fixed and tested meteor package init 3e49f56 add currentProvidor and mist fixes bd6d9ba merged develop 7b730b1 Merge branch 'strings' of github.com:ethereum/web3.js into strings cc533d9 fixed bytes wrong encoding 8c6f976 Merge branch 'develop' into strings 7c970e3 add bytes32 test with leading 0 9c7f7bb re-add .map files 189484f add extra int tests 73cc711 Merge branch 'develop' into strings fa3239f abi string type, fixes #216, #218, #219 git-subtree-dir: libjsqrc/ethereumjs git-subtree-split: d5d2115bf9ad07a736a189e1022b7d3a549e4006 --- .travis.yml | 1 - bower.json | 2 +- dist/web3-light.js | 312 +++++++++++++++++++++++-------- dist/web3-light.min.js | 4 +- dist/web3.js | 314 ++++++++++++++++++++++++-------- dist/web3.js.map | 26 +-- dist/web3.min.js | 6 +- example/contract_array.html | 83 +++++++++ gulpfile.js | 27 ++- karma.conf.js | 95 ---------- lib/solidity/coder.js | 7 + lib/solidity/formatters.js | 56 ++++-- lib/solidity/param.js | 9 +- lib/utils/utils.js | 24 ++- lib/version.json | 2 +- lib/web3.js | 18 +- lib/web3/allevents.js | 81 ++++++++ lib/web3/contract.js | 10 +- lib/web3/event.js | 18 +- lib/web3/filter.js | 23 ++- lib/web3/function.js | 3 +- lib/web3/httpprovider.js | 3 +- package-init.js | 15 +- package.js | 4 +- package.json | 25 +-- test/batch.js | 25 ++- test/coder.decodeParam.js | 98 ++++++++-- test/coder.encodeParam.js | 87 +++++++-- test/contract.js | 141 ++++++++++++++ test/polling.js | 40 ++++ test/utils.toHex.js | 1 + test/web3.eth.filter.methods.js | 8 +- 32 files changed, 1179 insertions(+), 389 deletions(-) create mode 100644 example/contract_array.html delete mode 100644 karma.conf.js create mode 100644 lib/web3/allevents.js diff --git a/.travis.yml b/.travis.yml index 92fa1cf35..175cd47b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,6 @@ script: - "jshint *.js lib" after_script: - npm run-script build - - npm run-script karma - npm run-script test-coveralls - cd test/node && npm install && node app.js diff --git a/bower.json b/bower.json index cb63bd076..fb38bda61 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "web3", "namespace": "ethereum", - "version": "0.6.0", + "version": "0.7.1", "description": "Ethereum Compatible JavaScript API", "main": [ "./dist/web3.js", diff --git a/dist/web3-light.js b/dist/web3-light.js index a57cac292..f939d164b 100644 --- a/dist/web3-light.js +++ b/dist/web3-light.js @@ -263,6 +263,13 @@ var coder = new SolidityCoder([ inputFormatter: f.formatInputBytes, outputFormatter: f.formatOutputBytes }), + new SolidityType({ + name: 'string', + match: 'strict', + mode: 'bytes', + inputFormatter: f.formatInputString, + outputFormatter: f.formatOutputString + }), new SolidityType({ name: 'real', match: 'prefix', @@ -328,26 +335,43 @@ var formatInputInt = function (value) { }; /** - * Formats input value to byte representation of string + * Formats input bytes * * @method formatInputBytes * @param {String} * @returns {SolidityParam} */ var formatInputBytes = function (value) { - var result = utils.fromAscii(value, c.ETH_PADDING).substr(2); + var result = utils.padRight(utils.toHex(value).substr(2), 64); return new SolidityParam(result); }; /** - * Formats input value to byte representation of string + * Formats input bytes * - * @method formatInputDynamicBytes + * @method formatDynamicInputBytes * @param {String} * @returns {SolidityParam} */ var formatInputDynamicBytes = function (value) { - var result = utils.fromAscii(value, c.ETH_PADDING).substr(2); + value = utils.toHex(value).substr(2); + var l = Math.floor((value.length + 63) / 64); + var result = utils.padRight(value, l * 64); + var length = Math.floor(value.length / 2); + return new SolidityParam(formatInputInt(length).value + result, 32); +}; + +/** + * Formats input value to byte representation of string + * + * @method formatInputString + * @param {String} + * @returns {SolidityParam} + */ +var formatInputString = function (value) { + var result = utils.fromAscii(value).substr(2); + var l = Math.floor((result.length + 63) / 64); + result = utils.padRight(result, l * 64); return new SolidityParam(formatInputInt(value.length).value + result, 32); }; @@ -450,27 +474,38 @@ var formatOutputBool = function (param) { }; /** - * Should be used to format output string + * Should be used to format output bytes * * @method formatOutputBytes * @param {SolidityParam} left-aligned hex representation of string - * @returns {String} ascii string + * @returns {String} hex string */ var formatOutputBytes = function (param) { - // length might also be important! - return utils.toAscii(param.staticPart()); + return '0x' + param.staticPart(); }; /** - * Should be used to format output string + * Should be used to format output bytes * * @method formatOutputDynamicBytes * @param {SolidityParam} left-aligned hex representation of string - * @returns {String} ascii string + * @returns {String} hex string */ var formatOutputDynamicBytes = function (param) { - // length might also be important! - return utils.toAscii(param.dynamicPart().slice(64)); + var length = (new BigNumber(param.dynamicPart().slice(0, 64), 16)).toNumber() * 2; + return '0x' + param.dynamicPart().substr(64, length); +}; + +/** + * Should be used to format output string + * + * @method formatOutputString + * @param {SolidityParam} left-aligned hex representation of string + * @returns {String} ascii string + */ +var formatOutputString = function (param) { + var length = (new BigNumber(param.dynamicPart().slice(0, 64), 16)).toNumber() * 2; + return utils.toAscii(param.dynamicPart().substr(64, length)); }; /** @@ -489,6 +524,7 @@ module.exports = { formatInputInt: formatInputInt, formatInputBytes: formatInputBytes, formatInputDynamicBytes: formatInputDynamicBytes, + formatInputString: formatInputString, formatInputBool: formatInputBool, formatInputReal: formatInputReal, formatOutputInt: formatOutputInt, @@ -498,6 +534,7 @@ module.exports = { formatOutputBool: formatOutputBool, formatOutputBytes: formatOutputBytes, formatOutputDynamicBytes: formatOutputDynamicBytes, + formatOutputString: formatOutputString, formatOutputAddress: formatOutputAddress }; @@ -687,13 +724,14 @@ var getOffset = function (bytes, index) { */ SolidityParam.decodeBytes = function (bytes, index) { index = index || 0; - //TODO add support for strings longer than 32 bytes - //var length = parseInt('0x' + bytes.substr(offset * 64, 64)); var offset = getOffset(bytes, index); - // 2 * , cause we also parse length - return new SolidityParam(bytes.substr(offset * 2, 2 * 64), 0); + var l = parseInt('0x' + bytes.substr(offset * 2, 64)); + l = Math.floor((l + 31) / 32); + + // (1 + l) * , cause we also parse length + return new SolidityParam(bytes.substr(offset * 2, (1 + l) * 64), 0); }; /** @@ -846,7 +884,7 @@ module.exports = function (str, isNew) { }; -},{"./utils":7,"crypto-js/sha3":33}],7:[function(require,module,exports){ +},{"./utils":7,"crypto-js/sha3":34}],7:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -924,6 +962,19 @@ var padLeft = function (string, chars, sign) { return new Array(chars - string.length + 1).join(sign ? sign : "0") + string; }; +/** + * Should be called to pad string to expected length + * + * @method padRight + * @param {String} string to be padded + * @param {Number} characters that result string should have + * @param {String} sign, by default 0 + * @returns {String} right aligned string + */ +var padRight = function (string, chars, sign) { + return string + (new Array(chars - string.length + 1).join(sign ? sign : "0")); +}; + /** * Should be called to get sting from it's hex representation * @@ -940,10 +991,6 @@ var toAscii = function(hex) { } for (; i < l; i+=2) { var code = parseInt(hex.substr(i, 2), 16); - if (code === 0) { - break; - } - str += String.fromCharCode(code); } @@ -1053,7 +1100,7 @@ var fromDecimal = function (value) { * @return {String} */ var toHex = function (val) { - /*jshint maxcomplexity:7 */ + /*jshint maxcomplexity: 8 */ if (isBoolean(val)) return fromDecimal(+val); @@ -1067,9 +1114,11 @@ var toHex = function (val) { // if its a negative number, pass it through fromDecimal if (isString(val)) { if (val.indexOf('-0x') === 0) - return fromDecimal(val); + return fromDecimal(val); else if (!isFinite(val)) return fromAscii(val); + else if(val.indexOf('0x') === 0) + return val; } return fromDecimal(val); @@ -1320,6 +1369,7 @@ var isIBAN = function (iban) { module.exports = { padLeft: padLeft, + padRight: padRight, toHex: toHex, toDecimal: toDecimal, fromDecimal: fromDecimal, @@ -1348,7 +1398,7 @@ module.exports = { },{"bignumber.js":"bignumber.js"}],8:[function(require,module,exports){ module.exports={ - "version": "0.6.0" + "version": "0.7.1" } },{}],9:[function(require,module,exports){ @@ -1434,31 +1484,25 @@ var setupProperties = function (obj, properties) { /// setups web3 object, and it's in-browser executed methods var web3 = {}; web3.providers = {}; +web3.currentProvider = null; web3.version = {}; web3.version.api = version.version; web3.eth = {}; /*jshint maxparams:4 */ -web3.eth.filter = function (fil, eventParams, options, formatter) { - - // if its event, treat it differently - // TODO: simplify and remove - if (fil._isEvent) { - return fil(eventParams, options); - } - - // output logs works for blockFilter and pendingTransaction filters? - return new Filter(fil, watches.eth(), formatter || formatters.outputLogFormatter); +web3.eth.filter = function (fil, callback) { + return new Filter(fil, watches.eth(), formatters.outputLogFormatter, callback); }; /*jshint maxparams:3 */ web3.shh = {}; -web3.shh.filter = function (fil) { - return new Filter(fil, watches.shh(), formatters.outputPostFormatter); +web3.shh.filter = function (fil, callback) { + return new Filter(fil, watches.shh(), formatters.outputPostFormatter, callback); }; web3.net = {}; web3.db = {}; web3.setProvider = function (provider) { + this.currentProvider = provider; RequestManager.getInstance().setProvider(provider); }; web3.reset = function () { @@ -1531,7 +1575,90 @@ setupMethods(web3.shh, shh.methods); module.exports = web3; -},{"./utils/config":5,"./utils/sha3":6,"./utils/utils":7,"./version.json":8,"./web3/batch":10,"./web3/db":12,"./web3/eth":14,"./web3/filter":16,"./web3/formatters":17,"./web3/method":22,"./web3/net":24,"./web3/property":25,"./web3/requestmanager":27,"./web3/shh":28,"./web3/watches":30}],10:[function(require,module,exports){ +},{"./utils/config":5,"./utils/sha3":6,"./utils/utils":7,"./version.json":8,"./web3/batch":11,"./web3/db":13,"./web3/eth":15,"./web3/filter":17,"./web3/formatters":18,"./web3/method":23,"./web3/net":25,"./web3/property":26,"./web3/requestmanager":28,"./web3/shh":29,"./web3/watches":31}],10:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** + * @file allevents.js + * @author Marek Kotewicz + * @date 2014 + */ + +var sha3 = require('../utils/sha3'); +var SolidityEvent = require('./event'); +var formatters = require('./formatters'); +var utils = require('../utils/utils'); +var Filter = require('./filter'); +var watches = require('./watches'); + +var AllSolidityEvents = function (json, address) { + this._json = json; + this._address = address; +}; + +AllSolidityEvents.prototype.encode = function (options) { + options = options || {}; + var result = {}; + + ['fromBlock', 'toBlock'].filter(function (f) { + return options[f] !== undefined; + }).forEach(function (f) { + result[f] = formatters.inputBlockNumberFormatter(options[f]); + }); + + result.topics = [null, null, null, null, null]; // match all topics + result.address = this._address; + + return result; +}; + +AllSolidityEvents.prototype.decode = function (data) { + data.data = data.data || ''; + data.topics = data.topics || []; + + var eventTopic = data.topics[0].slice(2); + var match = this._json.filter(function (j) { + return eventTopic === sha3(utils.transformToFullName(j)); + })[0]; + + if (!match) { // cannot find matching event? + console.warn('cannot find event for log'); + return data; + } + + var event = new SolidityEvent(match, this._address); + return event.decode(data); +}; + +AllSolidityEvents.prototype.execute = function (options, callback) { + var o = this.encode(options); + var formatter = this.decode.bind(this); + return new Filter(o, watches.eth(), formatter, callback); +}; + +AllSolidityEvents.prototype.attachToContract = function (contract) { + var execute = this.execute.bind(this); + contract.allEvents = execute; +}; + +module.exports = AllSolidityEvents; + + +},{"../utils/sha3":6,"../utils/utils":7,"./event":16,"./filter":17,"./formatters":18,"./watches":31}],11:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1594,7 +1721,7 @@ Batch.prototype.execute = function () { module.exports = Batch; -},{"./requestmanager":27}],11:[function(require,module,exports){ +},{"./requestmanager":28}],12:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1622,6 +1749,7 @@ var utils = require('../utils/utils'); var coder = require('../solidity/coder'); var SolidityEvent = require('./event'); var SolidityFunction = require('./function'); +var AllEvents = require('./allevents'); /** * Should be called to encode constructor params @@ -1667,9 +1795,14 @@ var addFunctionsToContract = function (contract, abi) { * @param {Array} abi */ var addEventsToContract = function (contract, abi) { - abi.filter(function (json) { + var events = abi.filter(function (json) { return json.type === 'event'; - }).map(function (json) { + }); + + var All = new AllEvents(events, contract.address); + All.attachToContract(contract); + + events.map(function (json) { return new SolidityEvent(json, contract.address); }).forEach(function (e) { e.attachToContract(contract); @@ -1776,7 +1909,7 @@ var Contract = function (abi, address) { module.exports = contract; -},{"../solidity/coder":1,"../utils/utils":7,"../web3":9,"./event":15,"./function":18}],12:[function(require,module,exports){ +},{"../solidity/coder":1,"../utils/utils":7,"../web3":9,"./allevents":10,"./event":16,"./function":19}],13:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1834,7 +1967,7 @@ module.exports = { methods: methods }; -},{"./method":22}],13:[function(require,module,exports){ +},{"./method":23}],14:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1874,7 +2007,7 @@ module.exports = { }; -},{}],14:[function(require,module,exports){ +},{}],15:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2159,7 +2292,7 @@ module.exports = { }; -},{"../utils/utils":7,"./formatters":17,"./method":22,"./property":25}],15:[function(require,module,exports){ +},{"../utils/utils":7,"./formatters":18,"./method":23,"./property":26}],16:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2184,9 +2317,10 @@ module.exports = { var utils = require('../utils/utils'); var coder = require('../solidity/coder'); -var web3 = require('../web3'); var formatters = require('./formatters'); var sha3 = require('../utils/sha3'); +var Filter = require('./filter'); +var watches = require('./watches'); /** * This prototype should be used to create event filters @@ -2332,10 +2466,21 @@ SolidityEvent.prototype.decode = function (data) { * @param {Object} options * @return {Object} filter object */ -SolidityEvent.prototype.execute = function (indexed, options) { +SolidityEvent.prototype.execute = function (indexed, options, callback) { + + if (utils.isFunction(arguments[arguments.length - 1])) { + callback = arguments[arguments.length - 1]; + if(arguments.length === 2) + options = null; + if(arguments.length === 1) { + options = null; + indexed = {}; + } + } + var o = this.encode(indexed, options); var formatter = this.decode.bind(this); - return web3.eth.filter(o, undefined, undefined, formatter); + return new Filter(o, watches.eth(), formatter, callback); }; /** @@ -2356,7 +2501,7 @@ SolidityEvent.prototype.attachToContract = function (contract) { module.exports = SolidityEvent; -},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9,"./formatters":17}],16:[function(require,module,exports){ +},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"./filter":17,"./formatters":18,"./watches":31}],17:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2486,7 +2631,7 @@ var pollFilter = function(self) { }; -var Filter = function (options, methods, formatter) { +var Filter = function (options, methods, formatter, callback) { var self = this; var implementation = {}; methods.forEach(function (method) { @@ -2494,23 +2639,32 @@ var Filter = function (options, methods, formatter) { }); this.options = getOptions(options); this.implementation = implementation; + this.filterId = null; this.callbacks = []; this.pollFilters = []; this.formatter = formatter; this.implementation.newFilter(this.options, function(error, id){ if(error) { - self.callbacks.forEach(function(callback){ - callback(error); + self.callbacks.forEach(function(cb){ + cb(error); }); } else { self.filterId = id; - // get filter logs at start - self.callbacks.forEach(function(callback){ - getLogsAtStart(self, callback); + + // get filter logs for the already existing watch calls + self.callbacks.forEach(function(cb){ + getLogsAtStart(self, cb); }); - pollFilter(self); + if(self.callbacks.length > 0) + pollFilter(self); + + // start to watch immediately + if(callback) { + return self.watch(callback); + } } }); + }; Filter.prototype.watch = function (callback) { @@ -2556,7 +2710,7 @@ Filter.prototype.get = function (callback) { module.exports = Filter; -},{"../utils/utils":7,"./formatters":17,"./requestmanager":27}],17:[function(require,module,exports){ +},{"../utils/utils":7,"./formatters":18,"./requestmanager":28}],18:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2778,7 +2932,7 @@ module.exports = { }; -},{"../utils/config":5,"../utils/utils":7}],18:[function(require,module,exports){ +},{"../utils/config":5,"../utils/utils":7}],19:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2969,8 +3123,9 @@ SolidityFunction.prototype.request = function () { var format = this.unpackOutput.bind(this); return { + method: this._constant ? 'eth_call' : 'eth_sendTransaction', callback: callback, - payload: payload, + params: [payload], format: format }; }; @@ -3014,7 +3169,7 @@ SolidityFunction.prototype.attachToContract = function (contract) { module.exports = SolidityFunction; -},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9,"./formatters":17}],19:[function(require,module,exports){ +},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9,"./formatters":18}],20:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3041,7 +3196,8 @@ module.exports = SolidityFunction; "use strict"; -var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line +// resolves the problem for electron/atom shell environments, which use node integration, but have no process variable available +var XMLHttpRequest = (typeof window !== 'undefined' && window.XMLHttpRequest) ? window.XMLHttpRequest : require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line var errors = require('./errors'); var HttpProvider = function (host) { @@ -3108,7 +3264,7 @@ HttpProvider.prototype.sendAsync = function (payload, callback) { module.exports = HttpProvider; -},{"./errors":13,"xmlhttprequest":4}],20:[function(require,module,exports){ +},{"./errors":14,"xmlhttprequest":4}],21:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3218,7 +3374,7 @@ ICAP.prototype.address = function () { module.exports = ICAP; -},{"../utils/utils":7}],21:[function(require,module,exports){ +},{"../utils/utils":7}],22:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3311,7 +3467,7 @@ Jsonrpc.prototype.toBatchPayload = function (messages) { module.exports = Jsonrpc; -},{}],22:[function(require,module,exports){ +},{}],23:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3485,7 +3641,7 @@ Method.prototype.send = function () { module.exports = Method; -},{"../utils/utils":7,"./errors":13,"./requestmanager":27}],23:[function(require,module,exports){ +},{"../utils/utils":7,"./errors":14,"./requestmanager":28}],24:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3533,7 +3689,7 @@ var abi = [ module.exports = contract(abi).at(address); -},{"./contract":11}],24:[function(require,module,exports){ +},{"./contract":12}],25:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3583,7 +3739,7 @@ module.exports = { }; -},{"../utils/utils":7,"./property":25}],25:[function(require,module,exports){ +},{"../utils/utils":7,"./property":26}],26:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3701,7 +3857,7 @@ Property.prototype.getAsync = function (callback) { module.exports = Property; -},{"./requestmanager":27}],26:[function(require,module,exports){ +},{"./requestmanager":28}],27:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3736,7 +3892,7 @@ QtSyncProvider.prototype.send = function (payload) { module.exports = QtSyncProvider; -},{}],27:[function(require,module,exports){ +},{}],28:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -4001,7 +4157,7 @@ RequestManager.prototype.poll = function () { module.exports = RequestManager; -},{"../utils/config":5,"../utils/utils":7,"./errors":13,"./jsonrpc":21}],28:[function(require,module,exports){ +},{"../utils/config":5,"../utils/utils":7,"./errors":14,"./jsonrpc":22}],29:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -4071,7 +4227,7 @@ module.exports = { }; -},{"./formatters":17,"./method":22}],29:[function(require,module,exports){ +},{"./formatters":18,"./method":23}],30:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -4167,7 +4323,7 @@ var deposit = function (from, address, value, client, callback) { module.exports = transfer; -},{"../web3":9,"./contract":11,"./icap":20,"./namereg":23}],30:[function(require,module,exports){ +},{"../web3":9,"./contract":12,"./icap":21,"./namereg":24}],31:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -4283,9 +4439,9 @@ module.exports = { }; -},{"./method":22}],31:[function(require,module,exports){ +},{"./method":23}],32:[function(require,module,exports){ -},{}],32:[function(require,module,exports){ +},{}],33:[function(require,module,exports){ ;(function (root, factory) { if (typeof exports === "object") { // CommonJS @@ -5028,7 +5184,7 @@ module.exports = { return CryptoJS; })); -},{}],33:[function(require,module,exports){ +},{}],34:[function(require,module,exports){ ;(function (root, factory, undef) { if (typeof exports === "object") { // CommonJS @@ -5352,7 +5508,7 @@ module.exports = { return CryptoJS.SHA3; })); -},{"./core":32,"./x64-core":34}],34:[function(require,module,exports){ +},{"./core":33,"./x64-core":35}],35:[function(require,module,exports){ ;(function (root, factory) { if (typeof exports === "object") { // CommonJS @@ -5657,7 +5813,7 @@ module.exports = { return CryptoJS; })); -},{"./core":32}],"bignumber.js":[function(require,module,exports){ +},{"./core":33}],"bignumber.js":[function(require,module,exports){ 'use strict'; module.exports = BigNumber; // jshint ignore:line @@ -5679,5 +5835,5 @@ if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') { module.exports = web3; -},{"./lib/web3":9,"./lib/web3/contract":11,"./lib/web3/httpprovider":19,"./lib/web3/namereg":23,"./lib/web3/qtsync":26,"./lib/web3/transfer":29}]},{},["web3"]) +},{"./lib/web3":9,"./lib/web3/contract":12,"./lib/web3/httpprovider":20,"./lib/web3/namereg":24,"./lib/web3/qtsync":27,"./lib/web3/transfer":30}]},{},["web3"]) //# sourceMappingURL=web3-light.js.map diff --git a/dist/web3-light.min.js b/dist/web3-light.min.js index 962e16e5f..9907881ad 100644 --- a/dist/web3-light.min.js +++ b/dist/web3-light.min.js @@ -1,2 +1,2 @@ -require=function t(e,n,r){function o(a,s){if(!n[a]){if(!e[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;ai;i+=64)n.push(this._outputFormatter(new a(t.dynamicPart().substr(i+64,64))));return n}return this._outputFormatter(t)},u.prototype.sliceParam=function(t,e,n){return"bytes"===this._mode?a.decodeBytes(t,e):s(n)?a.decodeArray(t,e):a.decodeParam(t,e)};var c=function(t){this._types=t};c.prototype._requireType=function(t){var e=this._types.filter(function(e){return e.isType(t)})[0];if(!e)throw Error("invalid solidity type!: "+t);return e},c.prototype._formatInput=function(t,e){return this._requireType(t).formatInput(e,s(t))},c.prototype.encodeParam=function(t,e){return this._formatInput(t,e).encode()},c.prototype.encodeParams=function(t,e){var n=this,r=t.map(function(t,r){return n._formatInput(t,e[r])});return a.encodeList(r)},c.prototype.decodeParam=function(t,e){return this.decodeParams([t],e)[0]},c.prototype.decodeParams=function(t,e){var n=this;return t.map(function(t,r){var o=n._requireType(t),i=o.sliceParam(e,r,t);return o.formatOutput(i,s(t))})};var l=new c([new u({name:"address",match:"strict",mode:"value",inputFormatter:i.formatInputInt,outputFormatter:i.formatOutputAddress}),new u({name:"bool",match:"strict",mode:"value",inputFormatter:i.formatInputBool,outputFormatter:i.formatOutputBool}),new u({name:"int",match:"prefix",mode:"value",inputFormatter:i.formatInputInt,outputFormatter:i.formatOutputInt}),new u({name:"uint",match:"prefix",mode:"value",inputFormatter:i.formatInputInt,outputFormatter:i.formatOutputUInt}),new u({name:"bytes",match:"strict",mode:"bytes",inputFormatter:i.formatInputDynamicBytes,outputFormatter:i.formatOutputDynamicBytes}),new u({name:"bytes",match:"prefix",mode:"value",inputFormatter:i.formatInputBytes,outputFormatter:i.formatOutputBytes}),new u({name:"real",match:"prefix",mode:"value",inputFormatter:i.formatInputReal,outputFormatter:i.formatOutputReal}),new u({name:"ureal",match:"prefix",mode:"value",inputFormatter:i.formatInputReal,outputFormatter:i.formatOutputUReal})]);e.exports=l},{"../utils/utils":7,"./formatters":2,"./param":3,"bignumber.js":"bignumber.js"}],2:[function(t,e,n){var r=t("bignumber.js"),o=t("../utils/utils"),i=t("../utils/config"),a=t("./param"),s=function(t){var e=2*i.ETH_PADDING;r.config(i.ETH_BIGNUMBER_ROUNDING_MODE);var n=o.padLeft(o.toTwosComplement(t).round().toString(16),e);return new a(n)},u=function(t){var e=o.fromAscii(t,i.ETH_PADDING).substr(2);return new a(e)},c=function(t){var e=o.fromAscii(t,i.ETH_PADDING).substr(2);return new a(s(t.length).value+e,32)},l=function(t){var e="000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0");return new a(e)},p=function(t){return s(new r(t).times(new r(2).pow(128)))},f=function(t){return"1"===new r(t.substr(0,1),16).toString(2).substr(0,1)},m=function(t){var e=t.staticPart()||"0";return f(e)?new r(e,16).minus(new r("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new r(e,16)},h=function(t){var e=t.staticPart()||"0";return new r(e,16)},d=function(t){return m(t).dividedBy(new r(2).pow(128))},y=function(t){return h(t).dividedBy(new r(2).pow(128))},g=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t.staticPart()?!0:!1},v=function(t){return o.toAscii(t.staticPart())},b=function(t){return o.toAscii(t.dynamicPart().slice(64))},w=function(t){var e=t.staticPart();return"0x"+e.slice(e.length-40,e.length)};e.exports={formatInputInt:s,formatInputBytes:u,formatInputDynamicBytes:c,formatInputBool:l,formatInputReal:p,formatOutputInt:m,formatOutputUInt:h,formatOutputReal:d,formatOutputUReal:y,formatOutputBool:g,formatOutputBytes:v,formatOutputDynamicBytes:b,formatOutputAddress:w}},{"../utils/config":5,"../utils/utils":7,"./param":3,"bignumber.js":"bignumber.js"}],3:[function(t,e,n){var r=t("../utils/utils"),o=function(t,e){this.value=t||"",this.offset=e};o.prototype.dynamicPartLength=function(){return this.dynamicPart().length/2},o.prototype.withOffset=function(t){return new o(this.value,t)},o.prototype.combine=function(t){return new o(this.value+t.value)},o.prototype.isDynamic=function(){return this.value.length>64||void 0!==this.offset},o.prototype.offsetAsBytes=function(){return this.isDynamic()?r.padLeft(r.toTwosComplement(this.offset).toString(16),64):""},o.prototype.staticPart=function(){return this.isDynamic()?this.offsetAsBytes():this.value},o.prototype.dynamicPart=function(){return this.isDynamic()?this.value:""},o.prototype.encode=function(){return this.staticPart()+this.dynamicPart()},o.encodeList=function(t){var e=32*t.length,n=t.map(function(t){if(!t.isDynamic())return t;var n=e;return e+=t.dynamicPartLength(),t.withOffset(n)});return n.reduce(function(t,e){return t+e.dynamicPart()},n.reduce(function(t,e){return t+e.staticPart()},""))},o.decodeParam=function(t,e){return e=e||0,new o(t.substr(64*e,64))};var i=function(t,e){return parseInt("0x"+t.substr(64*e,64))};o.decodeBytes=function(t,e){e=e||0;var n=i(t,e);return new o(t.substr(2*n,128),0)},o.decodeArray=function(t,e){e=e||0;var n=i(t,e),r=parseInt("0x"+t.substr(2*n,64));return new o(t.substr(2*n,64*(r+1)),0)},e.exports=o},{"../utils/utils":7}],4:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],5:[function(t,e,n){var r=t("bignumber.js"),o=["wei","kwei","Mwei","Gwei","szabo","finney","femtoether","picoether","nanoether","microether","milliether","nano","micro","milli","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:o,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:r.ROUND_DOWN},ETH_POLLING_TIMEOUT:500,defaultBlock:"latest",defaultAccount:void 0}},{"bignumber.js":"bignumber.js"}],6:[function(t,e,n){var r=t("./utils"),o=t("crypto-js/sha3");e.exports=function(t,e){return"0x"!==t.substr(0,2)||e||(console.warn("requirement of using web3.fromAscii before sha3 is deprecated"),console.warn("new usage: 'web3.sha3(\"hello\")'"),console.warn("see https://github.com/ethereum/web3.js/pull/205"),console.warn("if you need to hash hex value, you can do 'sha3(\"0xfff\", true)'"),t=r.toAscii(t)),o(t,{outputLength:256}).toString()}},{"./utils":7,"crypto-js/sha3":33}],7:[function(t,e,n){var r=t("bignumber.js"),o={wei:"1",kwei:"1000",ada:"1000",femtoether:"1000",mwei:"1000000",babbage:"1000000",picoether:"1000000",gwei:"1000000000",shannon:"1000000000",nanoether:"1000000000",nano:"1000000000",szabo:"1000000000000",microether:"1000000000000",micro:"1000000000000",finney:"1000000000000000",milliether:"1000000000000000",milli:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},i=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},a=function(t){var e="",n=0,r=t.length;for("0x"===t.substring(0,2)&&(n=2);r>n;n+=2){var o=parseInt(t.substr(n,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},s=function(t){for(var e="",n=0;nthis._inputTypes.length&&!i.isObject(t[t.length-1])?a.inputDefaultBlockNumberFormatter(t.pop()):void 0},u.prototype.toPayload=function(t){var e={};return t.length>this._inputTypes.length&&i.isObject(t[t.length-1])&&(e=t[t.length-1]),e.to=this._address,e.data="0x"+this.signature()+o.encodeParams(this._inputTypes,t),e},u.prototype.signature=function(){return s(this._name).slice(0,8)},u.prototype.unpackOutput=function(t){if(t){t=t.length>=2?t.slice(2):t;var e=o.decodeParams(this._outputTypes,t);return 1===e.length?e[0]:e}},u.prototype.call=function(){var t=Array.prototype.slice.call(arguments).filter(function(t){return void 0!==t}),e=this.extractCallback(t),n=this.extractDefaultBlock(t),o=this.toPayload(t);if(!e){var i=r.eth.call(o,n);return this.unpackOutput(i)}var a=this;r.eth.call(o,n,function(t,n){e(t,a.unpackOutput(n))})},u.prototype.sendTransaction=function(){var t=Array.prototype.slice.call(arguments).filter(function(t){return void 0!==t}),e=this.extractCallback(t),n=this.toPayload(t);return e?void r.eth.sendTransaction(n,e):r.eth.sendTransaction(n)},u.prototype.estimateGas=function(){var t=Array.prototype.slice.call(arguments),e=this.extractCallback(t),n=this.toPayload(t);return e?void r.eth.estimateGas(n,e):r.eth.estimateGas(n)},u.prototype.displayName=function(){return i.extractDisplayName(this._name)},u.prototype.typeName=function(){return i.extractTypeName(this._name)},u.prototype.request=function(){var t=Array.prototype.slice.call(arguments),e=this.extractCallback(t),n=this.toPayload(t),r=this.unpackOutput.bind(this);return{callback:e,payload:n,format:r}},u.prototype.execute=function(){var t=!this._constant;return t?this.sendTransaction.apply(this,Array.prototype.slice.call(arguments)):this.call.apply(this,Array.prototype.slice.call(arguments))},u.prototype.attachToContract=function(t){var e=this.execute.bind(this);e.request=this.request.bind(this),e.call=this.call.bind(this),e.sendTransaction=this.sendTransaction.bind(this),e.estimateGas=this.estimateGas.bind(this);var n=this.displayName();t[n]||(t[n]=e),t[n][this.typeName()]=e},e.exports=u},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9,"./formatters":17}],19:[function(t,e,n){"use strict";var r=t("xmlhttprequest").XMLHttpRequest,o=t("./errors"),i=function(t){this.host=t||"http://localhost:8545"};i.prototype.send=function(t){var e=new r;e.open("POST",this.host,!1),e.setRequestHeader("Content-type","application/json");try{e.send(JSON.stringify(t))}catch(n){throw o.InvalidConnection(this.host)}var i=e.responseText;try{i=JSON.parse(i)}catch(a){throw o.InvalidResponse(i)}return i},i.prototype.sendAsync=function(t,e){var n=new r;n.onreadystatechange=function(){if(4===n.readyState){var t=n.responseText,r=null;try{t=JSON.parse(t)}catch(i){r=o.InvalidResponse(t)}e(r,t)}},n.open("POST",this.host,!0),n.setRequestHeader("Content-type","application/json");try{n.send(JSON.stringify(t))}catch(i){e(o.InvalidConnection(this.host))}},e.exports=i},{"./errors":13,xmlhttprequest:4}],20:[function(t,e,n){var r=t("../utils/utils"),o=function(t){this._iban=t};o.prototype.isValid=function(){return r.isIBAN(this._iban)},o.prototype.isDirect=function(){return 34===this._iban.length},o.prototype.isIndirect=function(){return 20===this._iban.length},o.prototype.checksum=function(){return this._iban.substr(2,2)},o.prototype.institution=function(){return this.isIndirect()?this._iban.substr(7,4):""},o.prototype.client=function(){return this.isIndirect()?this._iban.substr(11):""},o.prototype.address=function(){return this.isDirect()?this._iban.substr(4):""},e.exports=o},{"../utils/utils":7}],21:[function(t,e,n){var r=function(){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,void(this.messageId=1))};r.getInstance=function(){var t=new r;return t},r.prototype.toPayload=function(t,e){return t||console.error("jsonrpc method should be specified!"),{jsonrpc:"2.0",method:t,params:e||[],id:this.messageId++}},r.prototype.isValidResponse=function(t){return!!t&&!t.error&&"2.0"===t.jsonrpc&&"number"==typeof t.id&&void 0!==t.result},r.prototype.toBatchPayload=function(t){var e=this;return t.map(function(t){return e.toPayload(t.method,t.params)})},e.exports=r},{}],22:[function(t,e,n){var r=t("./requestmanager"),o=t("../utils/utils"),i=t("./errors"),a=function(t){this.name=t.name,this.call=t.call,this.params=t.params||0,this.inputFormatter=t.inputFormatter,this.outputFormatter=t.outputFormatter};a.prototype.getCall=function(t){return o.isFunction(this.call)?this.call(t):this.call},a.prototype.extractCallback=function(t){return o.isFunction(t[t.length-1])?t.pop():void 0},a.prototype.validateArgs=function(t){if(t.length!==this.params)throw i.InvalidNumberOfParams()},a.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter.map(function(e,n){return e?e(t[n]):t[n]}):t},a.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},a.prototype.attachToObject=function(t){var e=this.send.bind(this);e.request=this.request.bind(this),e.call=this.call;var n=this.name.split(".");n.length>1?(t[n[0]]=t[n[0]]||{},t[n[0]][n[1]]=e):t[n[0]]=e},a.prototype.toPayload=function(t){var e=this.getCall(t),n=this.extractCallback(t),r=this.formatInput(t);return this.validateArgs(r),{method:e,params:r,callback:n}},a.prototype.request=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));return t.format=this.formatOutput.bind(this),t},a.prototype.send=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));if(t.callback){var e=this;return r.getInstance().sendAsync(t,function(n,r){t.callback(n,e.formatOutput(r))})}return this.formatOutput(r.getInstance().send(t))},e.exports=a},{"../utils/utils":7,"./errors":13,"./requestmanager":27}],23:[function(t,e,n){var r=t("./contract"),o="0xc6d9d2cd449a754c494264e1809c50e34d64562b",i=[{constant:!0,inputs:[{name:"_owner",type:"address"}],name:"name",outputs:[{name:"o_name",type:"bytes32"}],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"owner",outputs:[{name:"",type:"address"}],type:"function"},{constant:!0, -inputs:[{name:"_name",type:"bytes32"}],name:"content",outputs:[{name:"",type:"bytes32"}],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"addr",outputs:[{name:"",type:"address"}],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"}],name:"reserve",outputs:[],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"subRegistrar",outputs:[{name:"o_subRegistrar",type:"address"}],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_newOwner",type:"address"}],name:"transfer",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_registrar",type:"address"}],name:"setSubRegistrar",outputs:[],type:"function"},{constant:!1,inputs:[],name:"Registrar",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_a",type:"address"},{name:"_primary",type:"bool"}],name:"setAddress",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_content",type:"bytes32"}],name:"setContent",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"}],name:"disown",outputs:[],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"register",outputs:[{name:"",type:"address"}],type:"function"},{anonymous:!1,inputs:[{indexed:!0,name:"name",type:"bytes32"}],name:"Changed",type:"event"},{anonymous:!1,inputs:[{indexed:!0,name:"name",type:"bytes32"},{indexed:!0,name:"addr",type:"address"}],name:"PrimaryChanged",type:"event"}];e.exports=r(i).at(o)},{"./contract":11}],24:[function(t,e,n){var r=t("../utils/utils"),o=t("./property"),i=[],a=[new o({name:"listening",getter:"net_listening"}),new o({name:"peerCount",getter:"net_peerCount",outputFormatter:r.toDecimal})];e.exports={methods:i,properties:a}},{"../utils/utils":7,"./property":25}],25:[function(t,e,n){var r=t("./requestmanager"),o=function(t){this.name=t.name,this.getter=t.getter,this.setter=t.setter,this.outputFormatter=t.outputFormatter,this.inputFormatter=t.inputFormatter};o.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter(t):t},o.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},o.prototype.attachToObject=function(t){var e={get:this.get.bind(this)},n=this.name.split("."),r=n[0];n.length>1&&(t[n[0]]=t[n[0]]||{},t=t[n[0]],r=n[1]),Object.defineProperty(t,r,e);var o=function(t,e){return t+e.charAt(0).toUpperCase()+e.slice(1)};t[o("get",r)]=this.getAsync.bind(this)},o.prototype.get=function(){return this.formatOutput(r.getInstance().send({method:this.getter}))},o.prototype.getAsync=function(t){var e=this;r.getInstance().sendAsync({method:this.getter},function(n,r){return n?t(n):void t(n,e.formatOutput(r))})},e.exports=o},{"./requestmanager":27}],26:[function(t,e,n){var r=function(){};r.prototype.send=function(t){var e=navigator.qt.callMethod(JSON.stringify(t));return JSON.parse(e)},e.exports=r},{}],27:[function(t,e,n){var r=t("./jsonrpc"),o=t("../utils/utils"),i=t("../utils/config"),a=t("./errors"),s=function(t){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,this.provider=t,this.polls={},this.timeout=null,void(this.isPolling=!1))};s.getInstance=function(){var t=new s;return t},s.prototype.send=function(t){if(!this.provider)return console.error(a.InvalidProvider()),null;var e=r.getInstance().toPayload(t.method,t.params),n=this.provider.send(e);if(!r.getInstance().isValidResponse(n))throw a.InvalidResponse(n);return n.result},s.prototype.sendAsync=function(t,e){if(!this.provider)return e(a.InvalidProvider());var n=r.getInstance().toPayload(t.method,t.params);this.provider.sendAsync(n,function(t,n){return t?e(t):r.getInstance().isValidResponse(n)?void e(null,n.result):e(a.InvalidResponse(n))})},s.prototype.sendBatch=function(t,e){if(!this.provider)return e(a.InvalidProvider());var n=r.getInstance().toBatchPayload(t);this.provider.sendAsync(n,function(t,n){return t?e(t):o.isArray(n)?void e(t,n):e(a.InvalidResponse(n))})},s.prototype.setProvider=function(t){this.provider=t,this.provider&&!this.isPolling&&(this.poll(),this.isPolling=!0)},s.prototype.startPolling=function(t,e,n,r){this.polls["poll_"+e]={data:t,id:e,callback:n,uninstall:r}},s.prototype.stopPolling=function(t){delete this.polls["poll_"+t]},s.prototype.reset=function(){for(var t in this.polls)this.polls[t].uninstall();this.polls={},this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.poll()},s.prototype.poll=function(){if(this.timeout=setTimeout(this.poll.bind(this),i.ETH_POLLING_TIMEOUT),0!==Object.keys(this.polls).length){if(!this.provider)return void console.error(a.InvalidProvider());var t=[],e=[];for(var n in this.polls)t.push(this.polls[n].data),e.push(n);if(0!==t.length){var s=r.getInstance().toBatchPayload(t),u=this;this.provider.sendAsync(s,function(t,n){if(!t){if(!o.isArray(n))throw a.InvalidResponse(n);n.map(function(t,n){var r=e[n];return u.polls[r]?(t.callback=u.polls[r].callback,t):!1}).filter(function(t){return!!t}).filter(function(t){var e=r.getInstance().isValidResponse(t);return e||t.callback(a.InvalidResponse(t)),e}).filter(function(t){return o.isArray(t.result)&&t.result.length>0}).forEach(function(t){t.callback(null,t.result)})}})}}},e.exports=s},{"../utils/config":5,"../utils/utils":7,"./errors":13,"./jsonrpc":21}],28:[function(t,e,n){var r=t("./method"),o=t("./formatters"),i=new r({name:"post",call:"shh_post",params:1,inputFormatter:[o.inputPostFormatter]}),a=new r({name:"newIdentity",call:"shh_newIdentity",params:0}),s=new r({name:"hasIdentity",call:"shh_hasIdentity",params:1}),u=new r({name:"newGroup",call:"shh_newGroup",params:0}),c=new r({name:"addToGroup",call:"shh_addToGroup",params:0}),l=[i,a,s,u,c];e.exports={methods:l}},{"./formatters":17,"./method":22}],29:[function(t,e,n){var r=t("../web3"),o=t("./icap"),i=t("./namereg"),a=t("./contract"),s=function(t,e,n,r){var a=new o(e);if(!a.isValid())throw new Error("invalid iban address");if(a.isDirect())return u(t,a.address(),n,r);if(!r){var s=i.addr(a.institution());return c(t,s,n,a.client())}i.addr(a.insitution(),function(e,o){return c(t,o,n,a.client(),r)})},u=function(t,e,n,o){return r.eth.sendTransaction({address:e,from:t,value:n},o)},c=function(t,e,n,r,o){var i=[{constant:!1,inputs:[{name:"name",type:"bytes32"}],name:"deposit",outputs:[],type:"function"}];return a(i).at(e).deposit(r,{from:t,value:n},o)};e.exports=s},{"../web3":9,"./contract":11,"./icap":20,"./namereg":23}],30:[function(t,e,n){var r=t("./method"),o=function(){var t=function(t){var e=t[0];switch(e){case"latest":return t.shift(),this.params=0,"eth_newBlockFilter";case"pending":return t.shift(),this.params=0,"eth_newPendingTransactionFilter";default:return"eth_newFilter"}},e=new r({name:"newFilter",call:t,params:1}),n=new r({name:"uninstallFilter",call:"eth_uninstallFilter",params:1}),o=new r({name:"getLogs",call:"eth_getFilterLogs",params:1}),i=new r({name:"poll",call:"eth_getFilterChanges",params:1});return[e,n,o,i]},i=function(){var t=new r({name:"newFilter",call:"shh_newFilter",params:1}),e=new r({name:"uninstallFilter",call:"shh_uninstallFilter",params:1}),n=new r({name:"getLogs",call:"shh_getMessages",params:1}),o=new r({name:"poll",call:"shh_getFilterChanges",params:1});return[t,e,n,o]};e.exports={eth:o,shh:i}},{"./method":22}],31:[function(t,e,n){},{}],32:[function(t,e,n){!function(t,r){"object"==typeof n?e.exports=n=r():"function"==typeof define&&define.amd?define([],r):t.CryptoJS=r()}(this,function(){var t=t||function(t,e){var n={},r=n.lib={},o=r.Base=function(){function t(){}return{extend:function(e){t.prototype=this;var n=new t;return e&&n.mixIn(e),n.hasOwnProperty("init")||(n.init=function(){n.$super.init.apply(this,arguments)}),n.init.prototype=n,n.$super=this,n},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}}}(),i=r.WordArray=o.extend({init:function(t,n){t=this.words=t||[],this.sigBytes=n!=e?n:4*t.length},toString:function(t){return(t||s).stringify(this)},concat:function(t){var e=this.words,n=t.words,r=this.sigBytes,o=t.sigBytes;if(this.clamp(),r%4)for(var i=0;o>i;i++){var a=n[i>>>2]>>>24-i%4*8&255;e[r+i>>>2]|=a<<24-(r+i)%4*8}else for(var i=0;o>i;i+=4)e[r+i>>>2]=n[i>>>2];return this.sigBytes+=o,this},clamp:function(){var e=this.words,n=this.sigBytes;e[n>>>2]&=4294967295<<32-n%4*8,e.length=t.ceil(n/4)},clone:function(){var t=o.clone.call(this);return t.words=this.words.slice(0),t},random:function(e){for(var n,r=[],o=function(e){var e=e,n=987654321,r=4294967295;return function(){n=36969*(65535&n)+(n>>16)&r,e=18e3*(65535&e)+(e>>16)&r;var o=(n<<16)+e&r;return o/=4294967296,o+=.5,o*(t.random()>.5?1:-1)}},a=0;e>a;a+=4){var s=o(4294967296*(n||t.random()));n=987654071*s(),r.push(4294967296*s()|0)}return new i.init(r,e)}}),a=n.enc={},s=a.Hex={stringify:function(t){for(var e=t.words,n=t.sigBytes,r=[],o=0;n>o;o++){var i=e[o>>>2]>>>24-o%4*8&255;r.push((i>>>4).toString(16)),r.push((15&i).toString(16))}return r.join("")},parse:function(t){for(var e=t.length,n=[],r=0;e>r;r+=2)n[r>>>3]|=parseInt(t.substr(r,2),16)<<24-r%8*4;return new i.init(n,e/2)}},u=a.Latin1={stringify:function(t){for(var e=t.words,n=t.sigBytes,r=[],o=0;n>o;o++){var i=e[o>>>2]>>>24-o%4*8&255;r.push(String.fromCharCode(i))}return r.join("")},parse:function(t){for(var e=t.length,n=[],r=0;e>r;r++)n[r>>>2]|=(255&t.charCodeAt(r))<<24-r%4*8;return new i.init(n,e)}},c=a.Utf8={stringify:function(t){try{return decodeURIComponent(escape(u.stringify(t)))}catch(e){throw new Error("Malformed UTF-8 data")}},parse:function(t){return u.parse(unescape(encodeURIComponent(t)))}},l=r.BufferedBlockAlgorithm=o.extend({reset:function(){this._data=new i.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=c.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(e){var n=this._data,r=n.words,o=n.sigBytes,a=this.blockSize,s=4*a,u=o/s;u=e?t.ceil(u):t.max((0|u)-this._minBufferSize,0);var c=u*a,l=t.min(4*c,o);if(c){for(var p=0;c>p;p+=a)this._doProcessBlock(r,p);var f=r.splice(0,c);n.sigBytes-=l}return new i.init(f,l)},clone:function(){var t=o.clone.call(this);return t._data=this._data.clone(),t},_minBufferSize:0}),p=(r.Hasher=l.extend({cfg:o.extend(),init:function(t){this.cfg=this.cfg.extend(t),this.reset()},reset:function(){l.reset.call(this),this._doReset()},update:function(t){return this._append(t),this._process(),this},finalize:function(t){t&&this._append(t);var e=this._doFinalize();return e},blockSize:16,_createHelper:function(t){return function(e,n){return new t.init(n).finalize(e)}},_createHmacHelper:function(t){return function(e,n){return new p.HMAC.init(t,n).finalize(e)}}}),n.algo={});return n}(Math);return t})},{}],33:[function(t,e,n){!function(r,o,i){"object"==typeof n?e.exports=n=o(t("./core"),t("./x64-core")):"function"==typeof define&&define.amd?define(["./core","./x64-core"],o):o(r.CryptoJS)}(this,function(t){return function(e){var n=t,r=n.lib,o=r.WordArray,i=r.Hasher,a=n.x64,s=a.Word,u=n.algo,c=[],l=[],p=[];!function(){for(var t=1,e=0,n=0;24>n;n++){c[t+5*e]=(n+1)*(n+2)/2%64;var r=e%5,o=(2*t+3*e)%5;t=r,e=o}for(var t=0;5>t;t++)for(var e=0;5>e;e++)l[t+5*e]=e+(2*t+3*e)%5*5;for(var i=1,a=0;24>a;a++){for(var u=0,f=0,m=0;7>m;m++){if(1&i){var h=(1<h?f^=1<t;t++)f[t]=s.create()}();var m=u.SHA3=i.extend({cfg:i.cfg.extend({outputLength:512}),_doReset:function(){for(var t=this._state=[],e=0;25>e;e++)t[e]=new s.init;this.blockSize=(1600-2*this.cfg.outputLength)/32},_doProcessBlock:function(t,e){for(var n=this._state,r=this.blockSize/2,o=0;r>o;o++){var i=t[e+2*o],a=t[e+2*o+1];i=16711935&(i<<8|i>>>24)|4278255360&(i<<24|i>>>8),a=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8);var s=n[o];s.high^=a,s.low^=i}for(var u=0;24>u;u++){for(var m=0;5>m;m++){for(var h=0,d=0,y=0;5>y;y++){var s=n[m+5*y];h^=s.high,d^=s.low}var g=f[m];g.high=h,g.low=d}for(var m=0;5>m;m++)for(var v=f[(m+4)%5],b=f[(m+1)%5],w=b.high,_=b.low,h=v.high^(w<<1|_>>>31),d=v.low^(_<<1|w>>>31),y=0;5>y;y++){var s=n[m+5*y];s.high^=h,s.low^=d}for(var x=1;25>x;x++){var s=n[x],F=s.high,B=s.low,I=c[x];if(32>I)var h=F<>>32-I,d=B<>>32-I;else var h=B<>>64-I,d=F<>>64-I;var k=f[l[x]];k.high=h,k.low=d}var N=f[0],P=n[0];N.high=P.high,N.low=P.low;for(var m=0;5>m;m++)for(var y=0;5>y;y++){var x=m+5*y,s=n[x],A=f[x],O=f[(m+1)%5+5*y],T=f[(m+2)%5+5*y];s.high=A.high^~O.high&T.high,s.low=A.low^~O.low&T.low}var s=n[0],D=p[u];s.high^=D.high,s.low^=D.low}},_doFinalize:function(){var t=this._data,n=t.words,r=(8*this._nDataBytes,8*t.sigBytes),i=32*this.blockSize;n[r>>>5]|=1<<24-r%32,n[(e.ceil((r+1)/i)*i>>>5)-1]|=128,t.sigBytes=4*n.length,this._process();for(var a=this._state,s=this.cfg.outputLength/8,u=s/8,c=[],l=0;u>l;l++){var p=a[l],f=p.high,m=p.low;f=16711935&(f<<8|f>>>24)|4278255360&(f<<24|f>>>8),m=16711935&(m<<8|m>>>24)|4278255360&(m<<24|m>>>8),c.push(m),c.push(f)}return new o.init(c,s)},clone:function(){for(var t=i.clone.call(this),e=t._state=this._state.slice(0),n=0;25>n;n++)e[n]=e[n].clone();return t}});n.SHA3=i._createHelper(m),n.HmacSHA3=i._createHmacHelper(m)}(Math),t.SHA3})},{"./core":32,"./x64-core":34}],34:[function(t,e,n){!function(r,o){"object"==typeof n?e.exports=n=o(t("./core")):"function"==typeof define&&define.amd?define(["./core"],o):o(r.CryptoJS)}(this,function(t){return function(e){{var n=t,r=n.lib,o=r.Base,i=r.WordArray,a=n.x64={};a.Word=o.extend({init:function(t,e){this.high=t,this.low=e}}),a.WordArray=o.extend({init:function(t,n){t=this.words=t||[],this.sigBytes=n!=e?n:8*t.length},toX32:function(){for(var t=this.words,e=t.length,n=[],r=0;e>r;r++){var o=t[r];n.push(o.high),n.push(o.low)}return i.create(n,this.sigBytes)},clone:function(){for(var t=o.clone.call(this),e=t.words=this.words.slice(0),n=e.length,r=0;n>r;r++)e[r]=e[r].clone();return t}})}}(),t})},{"./core":32}],"bignumber.js":[function(t,e,n){"use strict";e.exports=BigNumber},{}],web3:[function(t,e,n){var r=t("./lib/web3");r.providers.HttpProvider=t("./lib/web3/httpprovider"),r.providers.QtSyncProvider=t("./lib/web3/qtsync"),r.eth.contract=t("./lib/web3/contract"),r.eth.namereg=t("./lib/web3/namereg"),r.eth.sendIBANTransaction=t("./lib/web3/transfer"),"undefined"!=typeof window&&"undefined"==typeof window.web3&&(window.web3=r),e.exports=r},{"./lib/web3":9,"./lib/web3/contract":11,"./lib/web3/httpprovider":19,"./lib/web3/namereg":23,"./lib/web3/qtsync":26,"./lib/web3/transfer":29}]},{},["web3"]); \ No newline at end of file +require=function t(e,n,r){function o(a,s){if(!n[a]){if(!e[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;ai;i+=64)n.push(this._outputFormatter(new a(t.dynamicPart().substr(i+64,64))));return n}return this._outputFormatter(t)},u.prototype.sliceParam=function(t,e,n){return"bytes"===this._mode?a.decodeBytes(t,e):s(n)?a.decodeArray(t,e):a.decodeParam(t,e)};var c=function(t){this._types=t};c.prototype._requireType=function(t){var e=this._types.filter(function(e){return e.isType(t)})[0];if(!e)throw Error("invalid solidity type!: "+t);return e},c.prototype._formatInput=function(t,e){return this._requireType(t).formatInput(e,s(t))},c.prototype.encodeParam=function(t,e){return this._formatInput(t,e).encode()},c.prototype.encodeParams=function(t,e){var n=this,r=t.map(function(t,r){return n._formatInput(t,e[r])});return a.encodeList(r)},c.prototype.decodeParam=function(t,e){return this.decodeParams([t],e)[0]},c.prototype.decodeParams=function(t,e){var n=this;return t.map(function(t,r){var o=n._requireType(t),i=o.sliceParam(e,r,t);return o.formatOutput(i,s(t))})};var l=new c([new u({name:"address",match:"strict",mode:"value",inputFormatter:i.formatInputInt,outputFormatter:i.formatOutputAddress}),new u({name:"bool",match:"strict",mode:"value",inputFormatter:i.formatInputBool,outputFormatter:i.formatOutputBool}),new u({name:"int",match:"prefix",mode:"value",inputFormatter:i.formatInputInt,outputFormatter:i.formatOutputInt}),new u({name:"uint",match:"prefix",mode:"value",inputFormatter:i.formatInputInt,outputFormatter:i.formatOutputUInt}),new u({name:"bytes",match:"strict",mode:"bytes",inputFormatter:i.formatInputDynamicBytes,outputFormatter:i.formatOutputDynamicBytes}),new u({name:"bytes",match:"prefix",mode:"value",inputFormatter:i.formatInputBytes,outputFormatter:i.formatOutputBytes}),new u({name:"string",match:"strict",mode:"bytes",inputFormatter:i.formatInputString,outputFormatter:i.formatOutputString}),new u({name:"real",match:"prefix",mode:"value",inputFormatter:i.formatInputReal,outputFormatter:i.formatOutputReal}),new u({name:"ureal",match:"prefix",mode:"value",inputFormatter:i.formatInputReal,outputFormatter:i.formatOutputUReal})]);e.exports=l},{"../utils/utils":7,"./formatters":2,"./param":3,"bignumber.js":"bignumber.js"}],2:[function(t,e,n){var r=t("bignumber.js"),o=t("../utils/utils"),i=t("../utils/config"),a=t("./param"),s=function(t){var e=2*i.ETH_PADDING;r.config(i.ETH_BIGNUMBER_ROUNDING_MODE);var n=o.padLeft(o.toTwosComplement(t).round().toString(16),e);return new a(n)},u=function(t){var e=o.padRight(o.toHex(t).substr(2),64);return new a(e)},c=function(t){t=o.toHex(t).substr(2);var e=Math.floor((t.length+63)/64),n=o.padRight(t,64*e),r=Math.floor(t.length/2);return new a(s(r).value+n,32)},l=function(t){var e=o.fromAscii(t).substr(2),n=Math.floor((e.length+63)/64);return e=o.padRight(e,64*n),new a(s(t.length).value+e,32)},p=function(t){var e="000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0");return new a(e)},f=function(t){return s(new r(t).times(new r(2).pow(128)))},m=function(t){return"1"===new r(t.substr(0,1),16).toString(2).substr(0,1)},h=function(t){var e=t.staticPart()||"0";return m(e)?new r(e,16).minus(new r("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new r(e,16)},d=function(t){var e=t.staticPart()||"0";return new r(e,16)},y=function(t){return h(t).dividedBy(new r(2).pow(128))},g=function(t){return d(t).dividedBy(new r(2).pow(128))},v=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t.staticPart()?!0:!1},b=function(t){return"0x"+t.staticPart()},w=function(t){var e=2*new r(t.dynamicPart().slice(0,64),16).toNumber();return"0x"+t.dynamicPart().substr(64,e)},_=function(t){var e=2*new r(t.dynamicPart().slice(0,64),16).toNumber();return o.toAscii(t.dynamicPart().substr(64,e))},x=function(t){var e=t.staticPart();return"0x"+e.slice(e.length-40,e.length)};e.exports={formatInputInt:s,formatInputBytes:u,formatInputDynamicBytes:c,formatInputString:l,formatInputBool:p,formatInputReal:f,formatOutputInt:h,formatOutputUInt:d,formatOutputReal:y,formatOutputUReal:g,formatOutputBool:v,formatOutputBytes:b,formatOutputDynamicBytes:w,formatOutputString:_,formatOutputAddress:x}},{"../utils/config":5,"../utils/utils":7,"./param":3,"bignumber.js":"bignumber.js"}],3:[function(t,e,n){var r=t("../utils/utils"),o=function(t,e){this.value=t||"",this.offset=e};o.prototype.dynamicPartLength=function(){return this.dynamicPart().length/2},o.prototype.withOffset=function(t){return new o(this.value,t)},o.prototype.combine=function(t){return new o(this.value+t.value)},o.prototype.isDynamic=function(){return this.value.length>64||void 0!==this.offset},o.prototype.offsetAsBytes=function(){return this.isDynamic()?r.padLeft(r.toTwosComplement(this.offset).toString(16),64):""},o.prototype.staticPart=function(){return this.isDynamic()?this.offsetAsBytes():this.value},o.prototype.dynamicPart=function(){return this.isDynamic()?this.value:""},o.prototype.encode=function(){return this.staticPart()+this.dynamicPart()},o.encodeList=function(t){var e=32*t.length,n=t.map(function(t){if(!t.isDynamic())return t;var n=e;return e+=t.dynamicPartLength(),t.withOffset(n)});return n.reduce(function(t,e){return t+e.dynamicPart()},n.reduce(function(t,e){return t+e.staticPart()},""))},o.decodeParam=function(t,e){return e=e||0,new o(t.substr(64*e,64))};var i=function(t,e){return parseInt("0x"+t.substr(64*e,64))};o.decodeBytes=function(t,e){e=e||0;var n=i(t,e),r=parseInt("0x"+t.substr(2*n,64));return r=Math.floor((r+31)/32),new o(t.substr(2*n,64*(1+r)),0)},o.decodeArray=function(t,e){e=e||0;var n=i(t,e),r=parseInt("0x"+t.substr(2*n,64));return new o(t.substr(2*n,64*(r+1)),0)},e.exports=o},{"../utils/utils":7}],4:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],5:[function(t,e,n){var r=t("bignumber.js"),o=["wei","kwei","Mwei","Gwei","szabo","finney","femtoether","picoether","nanoether","microether","milliether","nano","micro","milli","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:o,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:r.ROUND_DOWN},ETH_POLLING_TIMEOUT:500,defaultBlock:"latest",defaultAccount:void 0}},{"bignumber.js":"bignumber.js"}],6:[function(t,e,n){var r=t("./utils"),o=t("crypto-js/sha3");e.exports=function(t,e){return"0x"!==t.substr(0,2)||e||(console.warn("requirement of using web3.fromAscii before sha3 is deprecated"),console.warn("new usage: 'web3.sha3(\"hello\")'"),console.warn("see https://github.com/ethereum/web3.js/pull/205"),console.warn("if you need to hash hex value, you can do 'sha3(\"0xfff\", true)'"),t=r.toAscii(t)),o(t,{outputLength:256}).toString()}},{"./utils":7,"crypto-js/sha3":34}],7:[function(t,e,n){var r=t("bignumber.js"),o={wei:"1",kwei:"1000",ada:"1000",femtoether:"1000",mwei:"1000000",babbage:"1000000",picoether:"1000000",gwei:"1000000000",shannon:"1000000000",nanoether:"1000000000",nano:"1000000000",szabo:"1000000000000",microether:"1000000000000",micro:"1000000000000",finney:"1000000000000000",milliether:"1000000000000000",milli:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},i=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},a=function(t,e,n){return t+new Array(e-t.length+1).join(n?n:"0")},s=function(t){var e="",n=0,r=t.length;for("0x"===t.substring(0,2)&&(n=2);r>n;n+=2){var o=parseInt(t.substr(n,2),16);e+=String.fromCharCode(o)}return e},u=function(t){for(var e="",n=0;n0&&c(o),r)return o.watch(r)})};l.prototype.watch=function(t){return this.callbacks.push(t),this.filterId&&(u(this,t),c(this)),this},l.prototype.stopWatching=function(){r.getInstance().stopPolling(this.filterId),this.implementation.uninstallFilter(this.filterId,function(){}),this.callbacks=[]},l.prototype.get=function(t){var e=this;if(!i.isFunction(t)){var n=this.implementation.getLogs(this.filterId);return n.map(function(t){return e.formatter?e.formatter(t):t})}return this.implementation.getLogs(this.filterId,function(n,r){n?t(n):t(null,r.map(function(t){return e.formatter?e.formatter(t):t}))}),this},e.exports=l},{"../utils/utils":7,"./formatters":18,"./requestmanager":28}],18:[function(t,e,n){var r=t("../utils/utils"),o=t("../utils/config"),i=function(t){return r.toBigNumber(t)},a=function(t){return"latest"===t||"pending"===t||"earliest"===t},s=function(t){return void 0===t?o.defaultBlock:u(t)},u=function(t){return void 0===t?void 0:a(t)?t:r.toHex(t)},c=function(t){return t.from=t.from||o.defaultAccount,t.code&&(t.data=t.code,delete t.code),["gasPrice","gas","value","nonce"].filter(function(e){return void 0!==t[e]}).forEach(function(e){t[e]=r.fromDecimal(t[e])}),t},l=function(t){return null!==t.blockNumber&&(t.blockNumber=r.toDecimal(t.blockNumber)),null!==t.transactionIndex&&(t.transactionIndex=r.toDecimal(t.transactionIndex)),t.nonce=r.toDecimal(t.nonce),t.gas=r.toDecimal(t.gas),t.gasPrice=r.toBigNumber(t.gasPrice),t.value=r.toBigNumber(t.value),t},p=function(t){return t.gasLimit=r.toDecimal(t.gasLimit),t.gasUsed=r.toDecimal(t.gasUsed),t.size=r.toDecimal(t.size),t.timestamp=r.toDecimal(t.timestamp),null!==t.number&&(t.number=r.toDecimal(t.number)),t.difficulty=r.toBigNumber(t.difficulty),t.totalDifficulty=r.toBigNumber(t.totalDifficulty),r.isArray(t.transactions)&&t.transactions.forEach(function(t){return r.isString(t)?void 0:l(t)}),t},f=function(t){return null!==t.blockNumber&&(t.blockNumber=r.toDecimal(t.blockNumber)),null!==t.transactionIndex&&(t.transactionIndex=r.toDecimal(t.transactionIndex)),null!==t.logIndex&&(t.logIndex=r.toDecimal(t.logIndex)),t},m=function(t){return t.payload=r.toHex(t.payload),t.ttl=r.fromDecimal(t.ttl),t.workToProve=r.fromDecimal(t.workToProve),t.priority=r.fromDecimal(t.priority),r.isArray(t.topics)||(t.topics=t.topics?[t.topics]:[]),t.topics=t.topics.map(function(t){return r.fromAscii(t)}),t},h=function(t){return t.expiry=r.toDecimal(t.expiry),t.sent=r.toDecimal(t.sent),t.ttl=r.toDecimal(t.ttl),t.workProved=r.toDecimal(t.workProved),t.payloadRaw=t.payload,t.payload=r.toAscii(t.payload),r.isJson(t.payload)&&(t.payload=JSON.parse(t.payload)),t.topics||(t.topics=[]),t.topics=t.topics.map(function(t){return r.toAscii(t)}),t};e.exports={inputDefaultBlockNumberFormatter:s,inputBlockNumberFormatter:u,inputTransactionFormatter:c,inputPostFormatter:m,outputBigNumberFormatter:i,outputTransactionFormatter:l,outputBlockFormatter:p,outputLogFormatter:f,outputPostFormatter:h}},{"../utils/config":5,"../utils/utils":7}],19:[function(t,e,n){var r=t("../web3"),o=t("../solidity/coder"),i=t("../utils/utils"),a=t("./formatters"),s=t("../utils/sha3"),u=function(t,e){this._inputTypes=t.inputs.map(function(t){return t.type}),this._outputTypes=t.outputs.map(function(t){return t.type}),this._constant=t.constant,this._name=i.transformToFullName(t),this._address=e};u.prototype.extractCallback=function(t){return i.isFunction(t[t.length-1])?t.pop():void 0},u.prototype.extractDefaultBlock=function(t){return t.length>this._inputTypes.length&&!i.isObject(t[t.length-1])?a.inputDefaultBlockNumberFormatter(t.pop()):void 0},u.prototype.toPayload=function(t){var e={};return t.length>this._inputTypes.length&&i.isObject(t[t.length-1])&&(e=t[t.length-1]),e.to=this._address,e.data="0x"+this.signature()+o.encodeParams(this._inputTypes,t),e},u.prototype.signature=function(){return s(this._name).slice(0,8)},u.prototype.unpackOutput=function(t){if(t){t=t.length>=2?t.slice(2):t;var e=o.decodeParams(this._outputTypes,t);return 1===e.length?e[0]:e}},u.prototype.call=function(){var t=Array.prototype.slice.call(arguments).filter(function(t){return void 0!==t}),e=this.extractCallback(t),n=this.extractDefaultBlock(t),o=this.toPayload(t);if(!e){var i=r.eth.call(o,n);return this.unpackOutput(i)}var a=this;r.eth.call(o,n,function(t,n){e(t,a.unpackOutput(n))})},u.prototype.sendTransaction=function(){var t=Array.prototype.slice.call(arguments).filter(function(t){return void 0!==t}),e=this.extractCallback(t),n=this.toPayload(t);return e?void r.eth.sendTransaction(n,e):r.eth.sendTransaction(n)},u.prototype.estimateGas=function(){var t=Array.prototype.slice.call(arguments),e=this.extractCallback(t),n=this.toPayload(t);return e?void r.eth.estimateGas(n,e):r.eth.estimateGas(n)},u.prototype.displayName=function(){return i.extractDisplayName(this._name)},u.prototype.typeName=function(){return i.extractTypeName(this._name)},u.prototype.request=function(){var t=Array.prototype.slice.call(arguments),e=this.extractCallback(t),n=this.toPayload(t),r=this.unpackOutput.bind(this);return{method:this._constant?"eth_call":"eth_sendTransaction",callback:e,params:[n],format:r}},u.prototype.execute=function(){var t=!this._constant;return t?this.sendTransaction.apply(this,Array.prototype.slice.call(arguments)):this.call.apply(this,Array.prototype.slice.call(arguments))},u.prototype.attachToContract=function(t){var e=this.execute.bind(this);e.request=this.request.bind(this),e.call=this.call.bind(this),e.sendTransaction=this.sendTransaction.bind(this),e.estimateGas=this.estimateGas.bind(this);var n=this.displayName();t[n]||(t[n]=e),t[n][this.typeName()]=e},e.exports=u},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9,"./formatters":18}],20:[function(t,e,n){"use strict";var r="undefined"!=typeof window&&window.XMLHttpRequest?window.XMLHttpRequest:t("xmlhttprequest").XMLHttpRequest,o=t("./errors"),i=function(t){this.host=t||"http://localhost:8545"};i.prototype.send=function(t){var e=new r;e.open("POST",this.host,!1),e.setRequestHeader("Content-type","application/json");try{e.send(JSON.stringify(t))}catch(n){throw o.InvalidConnection(this.host)}var i=e.responseText;try{i=JSON.parse(i)}catch(a){throw o.InvalidResponse(i)}return i},i.prototype.sendAsync=function(t,e){var n=new r;n.onreadystatechange=function(){if(4===n.readyState){var t=n.responseText,r=null;try{t=JSON.parse(t)}catch(i){r=o.InvalidResponse(t)}e(r,t)}},n.open("POST",this.host,!0),n.setRequestHeader("Content-type","application/json");try{n.send(JSON.stringify(t))}catch(i){e(o.InvalidConnection(this.host))}},e.exports=i},{"./errors":14,xmlhttprequest:4}],21:[function(t,e,n){var r=t("../utils/utils"),o=function(t){this._iban=t};o.prototype.isValid=function(){return r.isIBAN(this._iban)},o.prototype.isDirect=function(){return 34===this._iban.length},o.prototype.isIndirect=function(){return 20===this._iban.length},o.prototype.checksum=function(){return this._iban.substr(2,2)},o.prototype.institution=function(){return this.isIndirect()?this._iban.substr(7,4):""},o.prototype.client=function(){return this.isIndirect()?this._iban.substr(11):""},o.prototype.address=function(){return this.isDirect()?this._iban.substr(4):""},e.exports=o},{"../utils/utils":7}],22:[function(t,e,n){var r=function(){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,void(this.messageId=1))};r.getInstance=function(){var t=new r;return t},r.prototype.toPayload=function(t,e){return t||console.error("jsonrpc method should be specified!"),{jsonrpc:"2.0",method:t,params:e||[],id:this.messageId++ +}},r.prototype.isValidResponse=function(t){return!!t&&!t.error&&"2.0"===t.jsonrpc&&"number"==typeof t.id&&void 0!==t.result},r.prototype.toBatchPayload=function(t){var e=this;return t.map(function(t){return e.toPayload(t.method,t.params)})},e.exports=r},{}],23:[function(t,e,n){var r=t("./requestmanager"),o=t("../utils/utils"),i=t("./errors"),a=function(t){this.name=t.name,this.call=t.call,this.params=t.params||0,this.inputFormatter=t.inputFormatter,this.outputFormatter=t.outputFormatter};a.prototype.getCall=function(t){return o.isFunction(this.call)?this.call(t):this.call},a.prototype.extractCallback=function(t){return o.isFunction(t[t.length-1])?t.pop():void 0},a.prototype.validateArgs=function(t){if(t.length!==this.params)throw i.InvalidNumberOfParams()},a.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter.map(function(e,n){return e?e(t[n]):t[n]}):t},a.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},a.prototype.attachToObject=function(t){var e=this.send.bind(this);e.request=this.request.bind(this),e.call=this.call;var n=this.name.split(".");n.length>1?(t[n[0]]=t[n[0]]||{},t[n[0]][n[1]]=e):t[n[0]]=e},a.prototype.toPayload=function(t){var e=this.getCall(t),n=this.extractCallback(t),r=this.formatInput(t);return this.validateArgs(r),{method:e,params:r,callback:n}},a.prototype.request=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));return t.format=this.formatOutput.bind(this),t},a.prototype.send=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));if(t.callback){var e=this;return r.getInstance().sendAsync(t,function(n,r){t.callback(n,e.formatOutput(r))})}return this.formatOutput(r.getInstance().send(t))},e.exports=a},{"../utils/utils":7,"./errors":14,"./requestmanager":28}],24:[function(t,e,n){var r=t("./contract"),o="0xc6d9d2cd449a754c494264e1809c50e34d64562b",i=[{constant:!0,inputs:[{name:"_owner",type:"address"}],name:"name",outputs:[{name:"o_name",type:"bytes32"}],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"owner",outputs:[{name:"",type:"address"}],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"content",outputs:[{name:"",type:"bytes32"}],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"addr",outputs:[{name:"",type:"address"}],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"}],name:"reserve",outputs:[],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"subRegistrar",outputs:[{name:"o_subRegistrar",type:"address"}],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_newOwner",type:"address"}],name:"transfer",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_registrar",type:"address"}],name:"setSubRegistrar",outputs:[],type:"function"},{constant:!1,inputs:[],name:"Registrar",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_a",type:"address"},{name:"_primary",type:"bool"}],name:"setAddress",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_content",type:"bytes32"}],name:"setContent",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"}],name:"disown",outputs:[],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"register",outputs:[{name:"",type:"address"}],type:"function"},{anonymous:!1,inputs:[{indexed:!0,name:"name",type:"bytes32"}],name:"Changed",type:"event"},{anonymous:!1,inputs:[{indexed:!0,name:"name",type:"bytes32"},{indexed:!0,name:"addr",type:"address"}],name:"PrimaryChanged",type:"event"}];e.exports=r(i).at(o)},{"./contract":12}],25:[function(t,e,n){var r=t("../utils/utils"),o=t("./property"),i=[],a=[new o({name:"listening",getter:"net_listening"}),new o({name:"peerCount",getter:"net_peerCount",outputFormatter:r.toDecimal})];e.exports={methods:i,properties:a}},{"../utils/utils":7,"./property":26}],26:[function(t,e,n){var r=t("./requestmanager"),o=function(t){this.name=t.name,this.getter=t.getter,this.setter=t.setter,this.outputFormatter=t.outputFormatter,this.inputFormatter=t.inputFormatter};o.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter(t):t},o.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},o.prototype.attachToObject=function(t){var e={get:this.get.bind(this)},n=this.name.split("."),r=n[0];n.length>1&&(t[n[0]]=t[n[0]]||{},t=t[n[0]],r=n[1]),Object.defineProperty(t,r,e);var o=function(t,e){return t+e.charAt(0).toUpperCase()+e.slice(1)};t[o("get",r)]=this.getAsync.bind(this)},o.prototype.get=function(){return this.formatOutput(r.getInstance().send({method:this.getter}))},o.prototype.getAsync=function(t){var e=this;r.getInstance().sendAsync({method:this.getter},function(n,r){return n?t(n):void t(n,e.formatOutput(r))})},e.exports=o},{"./requestmanager":28}],27:[function(t,e,n){var r=function(){};r.prototype.send=function(t){var e=navigator.qt.callMethod(JSON.stringify(t));return JSON.parse(e)},e.exports=r},{}],28:[function(t,e,n){var r=t("./jsonrpc"),o=t("../utils/utils"),i=t("../utils/config"),a=t("./errors"),s=function(t){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,this.provider=t,this.polls={},this.timeout=null,void(this.isPolling=!1))};s.getInstance=function(){var t=new s;return t},s.prototype.send=function(t){if(!this.provider)return console.error(a.InvalidProvider()),null;var e=r.getInstance().toPayload(t.method,t.params),n=this.provider.send(e);if(!r.getInstance().isValidResponse(n))throw a.InvalidResponse(n);return n.result},s.prototype.sendAsync=function(t,e){if(!this.provider)return e(a.InvalidProvider());var n=r.getInstance().toPayload(t.method,t.params);this.provider.sendAsync(n,function(t,n){return t?e(t):r.getInstance().isValidResponse(n)?void e(null,n.result):e(a.InvalidResponse(n))})},s.prototype.sendBatch=function(t,e){if(!this.provider)return e(a.InvalidProvider());var n=r.getInstance().toBatchPayload(t);this.provider.sendAsync(n,function(t,n){return t?e(t):o.isArray(n)?void e(t,n):e(a.InvalidResponse(n))})},s.prototype.setProvider=function(t){this.provider=t,this.provider&&!this.isPolling&&(this.poll(),this.isPolling=!0)},s.prototype.startPolling=function(t,e,n,r){this.polls["poll_"+e]={data:t,id:e,callback:n,uninstall:r}},s.prototype.stopPolling=function(t){delete this.polls["poll_"+t]},s.prototype.reset=function(){for(var t in this.polls)this.polls[t].uninstall();this.polls={},this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.poll()},s.prototype.poll=function(){if(this.timeout=setTimeout(this.poll.bind(this),i.ETH_POLLING_TIMEOUT),0!==Object.keys(this.polls).length){if(!this.provider)return void console.error(a.InvalidProvider());var t=[],e=[];for(var n in this.polls)t.push(this.polls[n].data),e.push(n);if(0!==t.length){var s=r.getInstance().toBatchPayload(t),u=this;this.provider.sendAsync(s,function(t,n){if(!t){if(!o.isArray(n))throw a.InvalidResponse(n);n.map(function(t,n){var r=e[n];return u.polls[r]?(t.callback=u.polls[r].callback,t):!1}).filter(function(t){return!!t}).filter(function(t){var e=r.getInstance().isValidResponse(t);return e||t.callback(a.InvalidResponse(t)),e}).filter(function(t){return o.isArray(t.result)&&t.result.length>0}).forEach(function(t){t.callback(null,t.result)})}})}}},e.exports=s},{"../utils/config":5,"../utils/utils":7,"./errors":14,"./jsonrpc":22}],29:[function(t,e,n){var r=t("./method"),o=t("./formatters"),i=new r({name:"post",call:"shh_post",params:1,inputFormatter:[o.inputPostFormatter]}),a=new r({name:"newIdentity",call:"shh_newIdentity",params:0}),s=new r({name:"hasIdentity",call:"shh_hasIdentity",params:1}),u=new r({name:"newGroup",call:"shh_newGroup",params:0}),c=new r({name:"addToGroup",call:"shh_addToGroup",params:0}),l=[i,a,s,u,c];e.exports={methods:l}},{"./formatters":18,"./method":23}],30:[function(t,e,n){var r=t("../web3"),o=t("./icap"),i=t("./namereg"),a=t("./contract"),s=function(t,e,n,r){var a=new o(e);if(!a.isValid())throw new Error("invalid iban address");if(a.isDirect())return u(t,a.address(),n,r);if(!r){var s=i.addr(a.institution());return c(t,s,n,a.client())}i.addr(a.insitution(),function(e,o){return c(t,o,n,a.client(),r)})},u=function(t,e,n,o){return r.eth.sendTransaction({address:e,from:t,value:n},o)},c=function(t,e,n,r,o){var i=[{constant:!1,inputs:[{name:"name",type:"bytes32"}],name:"deposit",outputs:[],type:"function"}];return a(i).at(e).deposit(r,{from:t,value:n},o)};e.exports=s},{"../web3":9,"./contract":12,"./icap":21,"./namereg":24}],31:[function(t,e,n){var r=t("./method"),o=function(){var t=function(t){var e=t[0];switch(e){case"latest":return t.shift(),this.params=0,"eth_newBlockFilter";case"pending":return t.shift(),this.params=0,"eth_newPendingTransactionFilter";default:return"eth_newFilter"}},e=new r({name:"newFilter",call:t,params:1}),n=new r({name:"uninstallFilter",call:"eth_uninstallFilter",params:1}),o=new r({name:"getLogs",call:"eth_getFilterLogs",params:1}),i=new r({name:"poll",call:"eth_getFilterChanges",params:1});return[e,n,o,i]},i=function(){var t=new r({name:"newFilter",call:"shh_newFilter",params:1}),e=new r({name:"uninstallFilter",call:"shh_uninstallFilter",params:1}),n=new r({name:"getLogs",call:"shh_getMessages",params:1}),o=new r({name:"poll",call:"shh_getFilterChanges",params:1});return[t,e,n,o]};e.exports={eth:o,shh:i}},{"./method":23}],32:[function(t,e,n){},{}],33:[function(t,e,n){!function(t,r){"object"==typeof n?e.exports=n=r():"function"==typeof define&&define.amd?define([],r):t.CryptoJS=r()}(this,function(){var t=t||function(t,e){var n={},r=n.lib={},o=r.Base=function(){function t(){}return{extend:function(e){t.prototype=this;var n=new t;return e&&n.mixIn(e),n.hasOwnProperty("init")||(n.init=function(){n.$super.init.apply(this,arguments)}),n.init.prototype=n,n.$super=this,n},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}}}(),i=r.WordArray=o.extend({init:function(t,n){t=this.words=t||[],this.sigBytes=n!=e?n:4*t.length},toString:function(t){return(t||s).stringify(this)},concat:function(t){var e=this.words,n=t.words,r=this.sigBytes,o=t.sigBytes;if(this.clamp(),r%4)for(var i=0;o>i;i++){var a=n[i>>>2]>>>24-i%4*8&255;e[r+i>>>2]|=a<<24-(r+i)%4*8}else for(var i=0;o>i;i+=4)e[r+i>>>2]=n[i>>>2];return this.sigBytes+=o,this},clamp:function(){var e=this.words,n=this.sigBytes;e[n>>>2]&=4294967295<<32-n%4*8,e.length=t.ceil(n/4)},clone:function(){var t=o.clone.call(this);return t.words=this.words.slice(0),t},random:function(e){for(var n,r=[],o=function(e){var e=e,n=987654321,r=4294967295;return function(){n=36969*(65535&n)+(n>>16)&r,e=18e3*(65535&e)+(e>>16)&r;var o=(n<<16)+e&r;return o/=4294967296,o+=.5,o*(t.random()>.5?1:-1)}},a=0;e>a;a+=4){var s=o(4294967296*(n||t.random()));n=987654071*s(),r.push(4294967296*s()|0)}return new i.init(r,e)}}),a=n.enc={},s=a.Hex={stringify:function(t){for(var e=t.words,n=t.sigBytes,r=[],o=0;n>o;o++){var i=e[o>>>2]>>>24-o%4*8&255;r.push((i>>>4).toString(16)),r.push((15&i).toString(16))}return r.join("")},parse:function(t){for(var e=t.length,n=[],r=0;e>r;r+=2)n[r>>>3]|=parseInt(t.substr(r,2),16)<<24-r%8*4;return new i.init(n,e/2)}},u=a.Latin1={stringify:function(t){for(var e=t.words,n=t.sigBytes,r=[],o=0;n>o;o++){var i=e[o>>>2]>>>24-o%4*8&255;r.push(String.fromCharCode(i))}return r.join("")},parse:function(t){for(var e=t.length,n=[],r=0;e>r;r++)n[r>>>2]|=(255&t.charCodeAt(r))<<24-r%4*8;return new i.init(n,e)}},c=a.Utf8={stringify:function(t){try{return decodeURIComponent(escape(u.stringify(t)))}catch(e){throw new Error("Malformed UTF-8 data")}},parse:function(t){return u.parse(unescape(encodeURIComponent(t)))}},l=r.BufferedBlockAlgorithm=o.extend({reset:function(){this._data=new i.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=c.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(e){var n=this._data,r=n.words,o=n.sigBytes,a=this.blockSize,s=4*a,u=o/s;u=e?t.ceil(u):t.max((0|u)-this._minBufferSize,0);var c=u*a,l=t.min(4*c,o);if(c){for(var p=0;c>p;p+=a)this._doProcessBlock(r,p);var f=r.splice(0,c);n.sigBytes-=l}return new i.init(f,l)},clone:function(){var t=o.clone.call(this);return t._data=this._data.clone(),t},_minBufferSize:0}),p=(r.Hasher=l.extend({cfg:o.extend(),init:function(t){this.cfg=this.cfg.extend(t),this.reset()},reset:function(){l.reset.call(this),this._doReset()},update:function(t){return this._append(t),this._process(),this},finalize:function(t){t&&this._append(t);var e=this._doFinalize();return e},blockSize:16,_createHelper:function(t){return function(e,n){return new t.init(n).finalize(e)}},_createHmacHelper:function(t){return function(e,n){return new p.HMAC.init(t,n).finalize(e)}}}),n.algo={});return n}(Math);return t})},{}],34:[function(t,e,n){!function(r,o,i){"object"==typeof n?e.exports=n=o(t("./core"),t("./x64-core")):"function"==typeof define&&define.amd?define(["./core","./x64-core"],o):o(r.CryptoJS)}(this,function(t){return function(e){var n=t,r=n.lib,o=r.WordArray,i=r.Hasher,a=n.x64,s=a.Word,u=n.algo,c=[],l=[],p=[];!function(){for(var t=1,e=0,n=0;24>n;n++){c[t+5*e]=(n+1)*(n+2)/2%64;var r=e%5,o=(2*t+3*e)%5;t=r,e=o}for(var t=0;5>t;t++)for(var e=0;5>e;e++)l[t+5*e]=e+(2*t+3*e)%5*5;for(var i=1,a=0;24>a;a++){for(var u=0,f=0,m=0;7>m;m++){if(1&i){var h=(1<h?f^=1<t;t++)f[t]=s.create()}();var m=u.SHA3=i.extend({cfg:i.cfg.extend({outputLength:512}),_doReset:function(){for(var t=this._state=[],e=0;25>e;e++)t[e]=new s.init;this.blockSize=(1600-2*this.cfg.outputLength)/32},_doProcessBlock:function(t,e){for(var n=this._state,r=this.blockSize/2,o=0;r>o;o++){var i=t[e+2*o],a=t[e+2*o+1];i=16711935&(i<<8|i>>>24)|4278255360&(i<<24|i>>>8),a=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8);var s=n[o];s.high^=a,s.low^=i}for(var u=0;24>u;u++){for(var m=0;5>m;m++){for(var h=0,d=0,y=0;5>y;y++){var s=n[m+5*y];h^=s.high,d^=s.low}var g=f[m];g.high=h,g.low=d}for(var m=0;5>m;m++)for(var v=f[(m+4)%5],b=f[(m+1)%5],w=b.high,_=b.low,h=v.high^(w<<1|_>>>31),d=v.low^(_<<1|w>>>31),y=0;5>y;y++){var s=n[m+5*y];s.high^=h,s.low^=d}for(var x=1;25>x;x++){var s=n[x],F=s.high,B=s.low,I=c[x];if(32>I)var h=F<>>32-I,d=B<>>32-I;else var h=B<>>64-I,d=F<>>64-I;var k=f[l[x]];k.high=h,k.low=d}var N=f[0],P=n[0];N.high=P.high,N.low=P.low;for(var m=0;5>m;m++)for(var y=0;5>y;y++){var x=m+5*y,s=n[x],O=f[x],T=f[(m+1)%5+5*y],A=f[(m+2)%5+5*y];s.high=O.high^~T.high&A.high,s.low=O.low^~T.low&A.low}var s=n[0],D=p[u];s.high^=D.high,s.low^=D.low}},_doFinalize:function(){var t=this._data,n=t.words,r=(8*this._nDataBytes,8*t.sigBytes),i=32*this.blockSize;n[r>>>5]|=1<<24-r%32,n[(e.ceil((r+1)/i)*i>>>5)-1]|=128,t.sigBytes=4*n.length,this._process();for(var a=this._state,s=this.cfg.outputLength/8,u=s/8,c=[],l=0;u>l;l++){var p=a[l],f=p.high,m=p.low;f=16711935&(f<<8|f>>>24)|4278255360&(f<<24|f>>>8),m=16711935&(m<<8|m>>>24)|4278255360&(m<<24|m>>>8),c.push(m),c.push(f)}return new o.init(c,s)},clone:function(){for(var t=i.clone.call(this),e=t._state=this._state.slice(0),n=0;25>n;n++)e[n]=e[n].clone();return t}});n.SHA3=i._createHelper(m),n.HmacSHA3=i._createHmacHelper(m)}(Math),t.SHA3})},{"./core":33,"./x64-core":35}],35:[function(t,e,n){!function(r,o){"object"==typeof n?e.exports=n=o(t("./core")):"function"==typeof define&&define.amd?define(["./core"],o):o(r.CryptoJS)}(this,function(t){return function(e){{var n=t,r=n.lib,o=r.Base,i=r.WordArray,a=n.x64={};a.Word=o.extend({init:function(t,e){this.high=t,this.low=e}}),a.WordArray=o.extend({init:function(t,n){t=this.words=t||[],this.sigBytes=n!=e?n:8*t.length},toX32:function(){for(var t=this.words,e=t.length,n=[],r=0;e>r;r++){var o=t[r];n.push(o.high),n.push(o.low)}return i.create(n,this.sigBytes)},clone:function(){for(var t=o.clone.call(this),e=t.words=this.words.slice(0),n=e.length,r=0;n>r;r++)e[r]=e[r].clone();return t}})}}(),t})},{"./core":33}],"bignumber.js":[function(t,e,n){"use strict";e.exports=BigNumber},{}],web3:[function(t,e,n){var r=t("./lib/web3");r.providers.HttpProvider=t("./lib/web3/httpprovider"),r.providers.QtSyncProvider=t("./lib/web3/qtsync"),r.eth.contract=t("./lib/web3/contract"),r.eth.namereg=t("./lib/web3/namereg"),r.eth.sendIBANTransaction=t("./lib/web3/transfer"),"undefined"!=typeof window&&"undefined"==typeof window.web3&&(window.web3=r),e.exports=r},{"./lib/web3":9,"./lib/web3/contract":12,"./lib/web3/httpprovider":20,"./lib/web3/namereg":24,"./lib/web3/qtsync":27,"./lib/web3/transfer":30}]},{},["web3"]); \ No newline at end of file diff --git a/dist/web3.js b/dist/web3.js index 70b096cf1..402bcd64f 100644 --- a/dist/web3.js +++ b/dist/web3.js @@ -263,6 +263,13 @@ var coder = new SolidityCoder([ inputFormatter: f.formatInputBytes, outputFormatter: f.formatOutputBytes }), + new SolidityType({ + name: 'string', + match: 'strict', + mode: 'bytes', + inputFormatter: f.formatInputString, + outputFormatter: f.formatOutputString + }), new SolidityType({ name: 'real', match: 'prefix', @@ -328,26 +335,43 @@ var formatInputInt = function (value) { }; /** - * Formats input value to byte representation of string + * Formats input bytes * * @method formatInputBytes * @param {String} * @returns {SolidityParam} */ var formatInputBytes = function (value) { - var result = utils.fromAscii(value, c.ETH_PADDING).substr(2); + var result = utils.padRight(utils.toHex(value).substr(2), 64); return new SolidityParam(result); }; /** - * Formats input value to byte representation of string + * Formats input bytes * - * @method formatInputDynamicBytes + * @method formatDynamicInputBytes * @param {String} * @returns {SolidityParam} */ var formatInputDynamicBytes = function (value) { - var result = utils.fromAscii(value, c.ETH_PADDING).substr(2); + value = utils.toHex(value).substr(2); + var l = Math.floor((value.length + 63) / 64); + var result = utils.padRight(value, l * 64); + var length = Math.floor(value.length / 2); + return new SolidityParam(formatInputInt(length).value + result, 32); +}; + +/** + * Formats input value to byte representation of string + * + * @method formatInputString + * @param {String} + * @returns {SolidityParam} + */ +var formatInputString = function (value) { + var result = utils.fromAscii(value).substr(2); + var l = Math.floor((result.length + 63) / 64); + result = utils.padRight(result, l * 64); return new SolidityParam(formatInputInt(value.length).value + result, 32); }; @@ -450,27 +474,38 @@ var formatOutputBool = function (param) { }; /** - * Should be used to format output string + * Should be used to format output bytes * * @method formatOutputBytes * @param {SolidityParam} left-aligned hex representation of string - * @returns {String} ascii string + * @returns {String} hex string */ var formatOutputBytes = function (param) { - // length might also be important! - return utils.toAscii(param.staticPart()); + return '0x' + param.staticPart(); }; /** - * Should be used to format output string + * Should be used to format output bytes * * @method formatOutputDynamicBytes * @param {SolidityParam} left-aligned hex representation of string - * @returns {String} ascii string + * @returns {String} hex string */ var formatOutputDynamicBytes = function (param) { - // length might also be important! - return utils.toAscii(param.dynamicPart().slice(64)); + var length = (new BigNumber(param.dynamicPart().slice(0, 64), 16)).toNumber() * 2; + return '0x' + param.dynamicPart().substr(64, length); +}; + +/** + * Should be used to format output string + * + * @method formatOutputString + * @param {SolidityParam} left-aligned hex representation of string + * @returns {String} ascii string + */ +var formatOutputString = function (param) { + var length = (new BigNumber(param.dynamicPart().slice(0, 64), 16)).toNumber() * 2; + return utils.toAscii(param.dynamicPart().substr(64, length)); }; /** @@ -489,6 +524,7 @@ module.exports = { formatInputInt: formatInputInt, formatInputBytes: formatInputBytes, formatInputDynamicBytes: formatInputDynamicBytes, + formatInputString: formatInputString, formatInputBool: formatInputBool, formatInputReal: formatInputReal, formatOutputInt: formatOutputInt, @@ -498,6 +534,7 @@ module.exports = { formatOutputBool: formatOutputBool, formatOutputBytes: formatOutputBytes, formatOutputDynamicBytes: formatOutputDynamicBytes, + formatOutputString: formatOutputString, formatOutputAddress: formatOutputAddress }; @@ -687,13 +724,14 @@ var getOffset = function (bytes, index) { */ SolidityParam.decodeBytes = function (bytes, index) { index = index || 0; - //TODO add support for strings longer than 32 bytes - //var length = parseInt('0x' + bytes.substr(offset * 64, 64)); var offset = getOffset(bytes, index); - // 2 * , cause we also parse length - return new SolidityParam(bytes.substr(offset * 2, 2 * 64), 0); + var l = parseInt('0x' + bytes.substr(offset * 2, 64)); + l = Math.floor((l + 31) / 32); + + // (1 + l) * , cause we also parse length + return new SolidityParam(bytes.substr(offset * 2, (1 + l) * 64), 0); }; /** @@ -846,7 +884,7 @@ module.exports = function (str, isNew) { }; -},{"./utils":7,"crypto-js/sha3":33}],7:[function(require,module,exports){ +},{"./utils":7,"crypto-js/sha3":34}],7:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -924,6 +962,19 @@ var padLeft = function (string, chars, sign) { return new Array(chars - string.length + 1).join(sign ? sign : "0") + string; }; +/** + * Should be called to pad string to expected length + * + * @method padRight + * @param {String} string to be padded + * @param {Number} characters that result string should have + * @param {String} sign, by default 0 + * @returns {String} right aligned string + */ +var padRight = function (string, chars, sign) { + return string + (new Array(chars - string.length + 1).join(sign ? sign : "0")); +}; + /** * Should be called to get sting from it's hex representation * @@ -940,10 +991,6 @@ var toAscii = function(hex) { } for (; i < l; i+=2) { var code = parseInt(hex.substr(i, 2), 16); - if (code === 0) { - break; - } - str += String.fromCharCode(code); } @@ -1053,7 +1100,7 @@ var fromDecimal = function (value) { * @return {String} */ var toHex = function (val) { - /*jshint maxcomplexity:7 */ + /*jshint maxcomplexity: 8 */ if (isBoolean(val)) return fromDecimal(+val); @@ -1067,9 +1114,11 @@ var toHex = function (val) { // if its a negative number, pass it through fromDecimal if (isString(val)) { if (val.indexOf('-0x') === 0) - return fromDecimal(val); + return fromDecimal(val); else if (!isFinite(val)) return fromAscii(val); + else if(val.indexOf('0x') === 0) + return val; } return fromDecimal(val); @@ -1320,6 +1369,7 @@ var isIBAN = function (iban) { module.exports = { padLeft: padLeft, + padRight: padRight, toHex: toHex, toDecimal: toDecimal, fromDecimal: fromDecimal, @@ -1348,7 +1398,7 @@ module.exports = { },{"bignumber.js":"bignumber.js"}],8:[function(require,module,exports){ module.exports={ - "version": "0.6.0" + "version": "0.7.1" } },{}],9:[function(require,module,exports){ @@ -1434,31 +1484,25 @@ var setupProperties = function (obj, properties) { /// setups web3 object, and it's in-browser executed methods var web3 = {}; web3.providers = {}; +web3.currentProvider = null; web3.version = {}; web3.version.api = version.version; web3.eth = {}; /*jshint maxparams:4 */ -web3.eth.filter = function (fil, eventParams, options, formatter) { - - // if its event, treat it differently - // TODO: simplify and remove - if (fil._isEvent) { - return fil(eventParams, options); - } - - // output logs works for blockFilter and pendingTransaction filters? - return new Filter(fil, watches.eth(), formatter || formatters.outputLogFormatter); +web3.eth.filter = function (fil, callback) { + return new Filter(fil, watches.eth(), formatters.outputLogFormatter, callback); }; /*jshint maxparams:3 */ web3.shh = {}; -web3.shh.filter = function (fil) { - return new Filter(fil, watches.shh(), formatters.outputPostFormatter); +web3.shh.filter = function (fil, callback) { + return new Filter(fil, watches.shh(), formatters.outputPostFormatter, callback); }; web3.net = {}; web3.db = {}; web3.setProvider = function (provider) { + this.currentProvider = provider; RequestManager.getInstance().setProvider(provider); }; web3.reset = function () { @@ -1531,7 +1575,90 @@ setupMethods(web3.shh, shh.methods); module.exports = web3; -},{"./utils/config":5,"./utils/sha3":6,"./utils/utils":7,"./version.json":8,"./web3/batch":10,"./web3/db":12,"./web3/eth":14,"./web3/filter":16,"./web3/formatters":17,"./web3/method":22,"./web3/net":24,"./web3/property":25,"./web3/requestmanager":27,"./web3/shh":28,"./web3/watches":30}],10:[function(require,module,exports){ +},{"./utils/config":5,"./utils/sha3":6,"./utils/utils":7,"./version.json":8,"./web3/batch":11,"./web3/db":13,"./web3/eth":15,"./web3/filter":17,"./web3/formatters":18,"./web3/method":23,"./web3/net":25,"./web3/property":26,"./web3/requestmanager":28,"./web3/shh":29,"./web3/watches":31}],10:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** + * @file allevents.js + * @author Marek Kotewicz + * @date 2014 + */ + +var sha3 = require('../utils/sha3'); +var SolidityEvent = require('./event'); +var formatters = require('./formatters'); +var utils = require('../utils/utils'); +var Filter = require('./filter'); +var watches = require('./watches'); + +var AllSolidityEvents = function (json, address) { + this._json = json; + this._address = address; +}; + +AllSolidityEvents.prototype.encode = function (options) { + options = options || {}; + var result = {}; + + ['fromBlock', 'toBlock'].filter(function (f) { + return options[f] !== undefined; + }).forEach(function (f) { + result[f] = formatters.inputBlockNumberFormatter(options[f]); + }); + + result.topics = [null, null, null, null, null]; // match all topics + result.address = this._address; + + return result; +}; + +AllSolidityEvents.prototype.decode = function (data) { + data.data = data.data || ''; + data.topics = data.topics || []; + + var eventTopic = data.topics[0].slice(2); + var match = this._json.filter(function (j) { + return eventTopic === sha3(utils.transformToFullName(j)); + })[0]; + + if (!match) { // cannot find matching event? + console.warn('cannot find event for log'); + return data; + } + + var event = new SolidityEvent(match, this._address); + return event.decode(data); +}; + +AllSolidityEvents.prototype.execute = function (options, callback) { + var o = this.encode(options); + var formatter = this.decode.bind(this); + return new Filter(o, watches.eth(), formatter, callback); +}; + +AllSolidityEvents.prototype.attachToContract = function (contract) { + var execute = this.execute.bind(this); + contract.allEvents = execute; +}; + +module.exports = AllSolidityEvents; + + +},{"../utils/sha3":6,"../utils/utils":7,"./event":16,"./filter":17,"./formatters":18,"./watches":31}],11:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1594,7 +1721,7 @@ Batch.prototype.execute = function () { module.exports = Batch; -},{"./requestmanager":27}],11:[function(require,module,exports){ +},{"./requestmanager":28}],12:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1622,6 +1749,7 @@ var utils = require('../utils/utils'); var coder = require('../solidity/coder'); var SolidityEvent = require('./event'); var SolidityFunction = require('./function'); +var AllEvents = require('./allevents'); /** * Should be called to encode constructor params @@ -1667,9 +1795,14 @@ var addFunctionsToContract = function (contract, abi) { * @param {Array} abi */ var addEventsToContract = function (contract, abi) { - abi.filter(function (json) { + var events = abi.filter(function (json) { return json.type === 'event'; - }).map(function (json) { + }); + + var All = new AllEvents(events, contract.address); + All.attachToContract(contract); + + events.map(function (json) { return new SolidityEvent(json, contract.address); }).forEach(function (e) { e.attachToContract(contract); @@ -1776,7 +1909,7 @@ var Contract = function (abi, address) { module.exports = contract; -},{"../solidity/coder":1,"../utils/utils":7,"../web3":9,"./event":15,"./function":18}],12:[function(require,module,exports){ +},{"../solidity/coder":1,"../utils/utils":7,"../web3":9,"./allevents":10,"./event":16,"./function":19}],13:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1834,7 +1967,7 @@ module.exports = { methods: methods }; -},{"./method":22}],13:[function(require,module,exports){ +},{"./method":23}],14:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1874,7 +2007,7 @@ module.exports = { }; -},{}],14:[function(require,module,exports){ +},{}],15:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2159,7 +2292,7 @@ module.exports = { }; -},{"../utils/utils":7,"./formatters":17,"./method":22,"./property":25}],15:[function(require,module,exports){ +},{"../utils/utils":7,"./formatters":18,"./method":23,"./property":26}],16:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2184,9 +2317,10 @@ module.exports = { var utils = require('../utils/utils'); var coder = require('../solidity/coder'); -var web3 = require('../web3'); var formatters = require('./formatters'); var sha3 = require('../utils/sha3'); +var Filter = require('./filter'); +var watches = require('./watches'); /** * This prototype should be used to create event filters @@ -2332,10 +2466,21 @@ SolidityEvent.prototype.decode = function (data) { * @param {Object} options * @return {Object} filter object */ -SolidityEvent.prototype.execute = function (indexed, options) { +SolidityEvent.prototype.execute = function (indexed, options, callback) { + + if (utils.isFunction(arguments[arguments.length - 1])) { + callback = arguments[arguments.length - 1]; + if(arguments.length === 2) + options = null; + if(arguments.length === 1) { + options = null; + indexed = {}; + } + } + var o = this.encode(indexed, options); var formatter = this.decode.bind(this); - return web3.eth.filter(o, undefined, undefined, formatter); + return new Filter(o, watches.eth(), formatter, callback); }; /** @@ -2356,7 +2501,7 @@ SolidityEvent.prototype.attachToContract = function (contract) { module.exports = SolidityEvent; -},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9,"./formatters":17}],16:[function(require,module,exports){ +},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"./filter":17,"./formatters":18,"./watches":31}],17:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2486,7 +2631,7 @@ var pollFilter = function(self) { }; -var Filter = function (options, methods, formatter) { +var Filter = function (options, methods, formatter, callback) { var self = this; var implementation = {}; methods.forEach(function (method) { @@ -2494,23 +2639,32 @@ var Filter = function (options, methods, formatter) { }); this.options = getOptions(options); this.implementation = implementation; + this.filterId = null; this.callbacks = []; this.pollFilters = []; this.formatter = formatter; this.implementation.newFilter(this.options, function(error, id){ if(error) { - self.callbacks.forEach(function(callback){ - callback(error); + self.callbacks.forEach(function(cb){ + cb(error); }); } else { self.filterId = id; - // get filter logs at start - self.callbacks.forEach(function(callback){ - getLogsAtStart(self, callback); + + // get filter logs for the already existing watch calls + self.callbacks.forEach(function(cb){ + getLogsAtStart(self, cb); }); - pollFilter(self); + if(self.callbacks.length > 0) + pollFilter(self); + + // start to watch immediately + if(callback) { + return self.watch(callback); + } } }); + }; Filter.prototype.watch = function (callback) { @@ -2556,7 +2710,7 @@ Filter.prototype.get = function (callback) { module.exports = Filter; -},{"../utils/utils":7,"./formatters":17,"./requestmanager":27}],17:[function(require,module,exports){ +},{"../utils/utils":7,"./formatters":18,"./requestmanager":28}],18:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2778,7 +2932,7 @@ module.exports = { }; -},{"../utils/config":5,"../utils/utils":7}],18:[function(require,module,exports){ +},{"../utils/config":5,"../utils/utils":7}],19:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2969,8 +3123,9 @@ SolidityFunction.prototype.request = function () { var format = this.unpackOutput.bind(this); return { + method: this._constant ? 'eth_call' : 'eth_sendTransaction', callback: callback, - payload: payload, + params: [payload], format: format }; }; @@ -3014,7 +3169,7 @@ SolidityFunction.prototype.attachToContract = function (contract) { module.exports = SolidityFunction; -},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9,"./formatters":17}],19:[function(require,module,exports){ +},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9,"./formatters":18}],20:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3041,7 +3196,8 @@ module.exports = SolidityFunction; "use strict"; -var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line +// resolves the problem for electron/atom shell environments, which use node integration, but have no process variable available +var XMLHttpRequest = (typeof window !== 'undefined' && window.XMLHttpRequest) ? window.XMLHttpRequest : require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line var errors = require('./errors'); var HttpProvider = function (host) { @@ -3108,7 +3264,7 @@ HttpProvider.prototype.sendAsync = function (payload, callback) { module.exports = HttpProvider; -},{"./errors":13,"xmlhttprequest":4}],20:[function(require,module,exports){ +},{"./errors":14,"xmlhttprequest":4}],21:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3218,7 +3374,7 @@ ICAP.prototype.address = function () { module.exports = ICAP; -},{"../utils/utils":7}],21:[function(require,module,exports){ +},{"../utils/utils":7}],22:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3311,7 +3467,7 @@ Jsonrpc.prototype.toBatchPayload = function (messages) { module.exports = Jsonrpc; -},{}],22:[function(require,module,exports){ +},{}],23:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3485,7 +3641,7 @@ Method.prototype.send = function () { module.exports = Method; -},{"../utils/utils":7,"./errors":13,"./requestmanager":27}],23:[function(require,module,exports){ +},{"../utils/utils":7,"./errors":14,"./requestmanager":28}],24:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3533,7 +3689,7 @@ var abi = [ module.exports = contract(abi).at(address); -},{"./contract":11}],24:[function(require,module,exports){ +},{"./contract":12}],25:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3583,7 +3739,7 @@ module.exports = { }; -},{"../utils/utils":7,"./property":25}],25:[function(require,module,exports){ +},{"../utils/utils":7,"./property":26}],26:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3701,7 +3857,7 @@ Property.prototype.getAsync = function (callback) { module.exports = Property; -},{"./requestmanager":27}],26:[function(require,module,exports){ +},{"./requestmanager":28}],27:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3736,7 +3892,7 @@ QtSyncProvider.prototype.send = function (payload) { module.exports = QtSyncProvider; -},{}],27:[function(require,module,exports){ +},{}],28:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -4001,7 +4157,7 @@ RequestManager.prototype.poll = function () { module.exports = RequestManager; -},{"../utils/config":5,"../utils/utils":7,"./errors":13,"./jsonrpc":21}],28:[function(require,module,exports){ +},{"../utils/config":5,"../utils/utils":7,"./errors":14,"./jsonrpc":22}],29:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -4071,7 +4227,7 @@ module.exports = { }; -},{"./formatters":17,"./method":22}],29:[function(require,module,exports){ +},{"./formatters":18,"./method":23}],30:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -4167,7 +4323,7 @@ var deposit = function (from, address, value, client, callback) { module.exports = transfer; -},{"../web3":9,"./contract":11,"./icap":20,"./namereg":23}],30:[function(require,module,exports){ +},{"../web3":9,"./contract":12,"./icap":21,"./namereg":24}],31:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -4283,9 +4439,9 @@ module.exports = { }; -},{"./method":22}],31:[function(require,module,exports){ +},{"./method":23}],32:[function(require,module,exports){ -},{}],32:[function(require,module,exports){ +},{}],33:[function(require,module,exports){ ;(function (root, factory) { if (typeof exports === "object") { // CommonJS @@ -5028,7 +5184,7 @@ module.exports = { return CryptoJS; })); -},{}],33:[function(require,module,exports){ +},{}],34:[function(require,module,exports){ ;(function (root, factory, undef) { if (typeof exports === "object") { // CommonJS @@ -5352,7 +5508,7 @@ module.exports = { return CryptoJS.SHA3; })); -},{"./core":32,"./x64-core":34}],34:[function(require,module,exports){ +},{"./core":33,"./x64-core":35}],35:[function(require,module,exports){ ;(function (root, factory) { if (typeof exports === "object") { // CommonJS @@ -5657,7 +5813,7 @@ module.exports = { return CryptoJS; })); -},{"./core":32}],"bignumber.js":[function(require,module,exports){ +},{"./core":33}],"bignumber.js":[function(require,module,exports){ /*! bignumber.js v2.0.7 https://github.com/MikeMcl/bignumber.js/LICENCE */ ;(function (global) { @@ -8342,7 +8498,7 @@ module.exports = { } })(this); -},{"crypto":31}],"web3":[function(require,module,exports){ +},{"crypto":32}],"web3":[function(require,module,exports){ var web3 = require('./lib/web3'); web3.providers.HttpProvider = require('./lib/web3/httpprovider'); web3.providers.QtSyncProvider = require('./lib/web3/qtsync'); @@ -8358,5 +8514,5 @@ if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') { module.exports = web3; -},{"./lib/web3":9,"./lib/web3/contract":11,"./lib/web3/httpprovider":19,"./lib/web3/namereg":23,"./lib/web3/qtsync":26,"./lib/web3/transfer":29}]},{},["web3"]) +},{"./lib/web3":9,"./lib/web3/contract":12,"./lib/web3/httpprovider":20,"./lib/web3/namereg":24,"./lib/web3/qtsync":27,"./lib/web3/transfer":30}]},{},["web3"]) //# sourceMappingURL=web3.js.map diff --git a/dist/web3.js.map b/dist/web3.js.map index b000cdd4b..f67aad1c2 100644 --- a/dist/web3.js.map +++ b/dist/web3.js.map @@ -11,6 +11,7 @@ "lib/utils/utils.js", "lib/version.json", "lib/web3.js", + "lib/web3/allevents.js", "lib/web3/batch.js", "lib/web3/contract.js", "lib/web3/db.js", @@ -40,30 +41,31 @@ "index.js" ], "names": [], - "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClfA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClHA;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACruBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/SA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3nFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", + "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9fA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1LA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClHA;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACruBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/SA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3nFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", "file": "generated.js", "sourceRoot": "", "sourcesContent": [ "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o.\n*/\n/** \n * @file coder.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar BigNumber = require('bignumber.js');\nvar utils = require('../utils/utils');\nvar f = require('./formatters');\nvar SolidityParam = require('./param');\n\n/**\n * Should be used to check if a type is an array type\n *\n * @method isArrayType\n * @param {String} type\n * @return {Bool} true is the type is an array, otherwise false\n */\nvar isArrayType = function (type) {\n return type.slice(-2) === '[]';\n};\n\n/**\n * SolidityType prototype is used to encode/decode solidity params of certain type\n */\nvar SolidityType = function (config) {\n this._name = config.name;\n this._match = config.match;\n this._mode = config.mode;\n this._inputFormatter = config.inputFormatter;\n this._outputFormatter = config.outputFormatter;\n};\n\n/**\n * Should be used to determine if this SolidityType do match given type\n *\n * @method isType\n * @param {String} name\n * @return {Bool} true if type match this SolidityType, otherwise false\n */\nSolidityType.prototype.isType = function (name) {\n if (this._match === 'strict') {\n return this._name === name || (name.indexOf(this._name) === 0 && name.slice(this._name.length) === '[]');\n } else if (this._match === 'prefix') {\n // TODO better type detection!\n return name.indexOf(this._name) === 0;\n }\n};\n\n/**\n * Should be used to transform plain param to SolidityParam object\n *\n * @method formatInput\n * @param {Object} param - plain object, or an array of objects\n * @param {Bool} arrayType - true if a param should be encoded as an array\n * @return {SolidityParam} encoded param wrapped in SolidityParam object \n */\nSolidityType.prototype.formatInput = function (param, arrayType) {\n if (utils.isArray(param) && arrayType) { // TODO: should fail if this two are not the same\n var self = this;\n return param.map(function (p) {\n return self._inputFormatter(p);\n }).reduce(function (acc, current) {\n return acc.combine(current);\n }, f.formatInputInt(param.length)).withOffset(32);\n } \n return this._inputFormatter(param);\n};\n\n/**\n * Should be used to transoform SolidityParam to plain param\n *\n * @method formatOutput\n * @param {SolidityParam} byteArray\n * @param {Bool} arrayType - true if a param should be decoded as an array\n * @return {Object} plain decoded param\n */\nSolidityType.prototype.formatOutput = function (param, arrayType) {\n if (arrayType) {\n // let's assume, that we solidity will never return long arrays :P \n var result = [];\n var length = new BigNumber(param.dynamicPart().slice(0, 64), 16);\n for (var i = 0; i < length * 64; i += 64) {\n result.push(this._outputFormatter(new SolidityParam(param.dynamicPart().substr(i + 64, 64))));\n }\n return result;\n }\n return this._outputFormatter(param);\n};\n\n/**\n * Should be used to slice single param from bytes\n *\n * @method sliceParam\n * @param {String} bytes\n * @param {Number} index of param to slice\n * @param {String} type\n * @returns {SolidityParam} param\n */\nSolidityType.prototype.sliceParam = function (bytes, index, type) {\n if (this._mode === 'bytes') {\n return SolidityParam.decodeBytes(bytes, index);\n } else if (isArrayType(type)) {\n return SolidityParam.decodeArray(bytes, index);\n }\n return SolidityParam.decodeParam(bytes, index);\n};\n\n/**\n * SolidityCoder prototype should be used to encode/decode solidity params of any type\n */\nvar SolidityCoder = function (types) {\n this._types = types;\n};\n\n/**\n * This method should be used to transform type to SolidityType\n *\n * @method _requireType\n * @param {String} type\n * @returns {SolidityType} \n * @throws {Error} throws if no matching type is found\n */\nSolidityCoder.prototype._requireType = function (type) {\n var solidityType = this._types.filter(function (t) {\n return t.isType(type);\n })[0];\n\n if (!solidityType) {\n throw Error('invalid solidity type!: ' + type);\n }\n\n return solidityType;\n};\n\n/**\n * Should be used to transform plain param of given type to SolidityParam\n *\n * @method _formatInput\n * @param {String} type of param\n * @param {Object} plain param\n * @return {SolidityParam}\n */\nSolidityCoder.prototype._formatInput = function (type, param) {\n return this._requireType(type).formatInput(param, isArrayType(type));\n};\n\n/**\n * Should be used to encode plain param\n *\n * @method encodeParam\n * @param {String} type\n * @param {Object} plain param\n * @return {String} encoded plain param\n */\nSolidityCoder.prototype.encodeParam = function (type, param) {\n return this._formatInput(type, param).encode();\n};\n\n/**\n * Should be used to encode list of params\n *\n * @method encodeParams\n * @param {Array} types\n * @param {Array} params\n * @return {String} encoded list of params\n */\nSolidityCoder.prototype.encodeParams = function (types, params) {\n var self = this;\n var solidityParams = types.map(function (type, index) {\n return self._formatInput(type, params[index]);\n });\n\n return SolidityParam.encodeList(solidityParams);\n};\n\n/**\n * Should be used to decode bytes to plain param\n *\n * @method decodeParam\n * @param {String} type\n * @param {String} bytes\n * @return {Object} plain param\n */\nSolidityCoder.prototype.decodeParam = function (type, bytes) {\n return this.decodeParams([type], bytes)[0];\n};\n\n/**\n * Should be used to decode list of params\n *\n * @method decodeParam\n * @param {Array} types\n * @param {String} bytes\n * @return {Array} array of plain params\n */\nSolidityCoder.prototype.decodeParams = function (types, bytes) {\n var self = this;\n return types.map(function (type, index) {\n var solidityType = self._requireType(type);\n var p = solidityType.sliceParam(bytes, index, type);\n return solidityType.formatOutput(p, isArrayType(type));\n });\n};\n\nvar coder = new SolidityCoder([\n new SolidityType({\n name: 'address',\n match: 'strict',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputAddress\n }),\n new SolidityType({\n name: 'bool',\n match: 'strict',\n mode: 'value',\n inputFormatter: f.formatInputBool,\n outputFormatter: f.formatOutputBool\n }),\n new SolidityType({\n name: 'int',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputInt,\n }),\n new SolidityType({\n name: 'uint',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputUInt\n }),\n new SolidityType({\n name: 'bytes',\n match: 'strict',\n mode: 'bytes',\n inputFormatter: f.formatInputDynamicBytes,\n outputFormatter: f.formatOutputDynamicBytes\n }),\n new SolidityType({\n name: 'bytes',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputBytes,\n outputFormatter: f.formatOutputBytes\n }),\n new SolidityType({\n name: 'real',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputReal,\n outputFormatter: f.formatOutputReal\n }),\n new SolidityType({\n name: 'ureal',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputReal,\n outputFormatter: f.formatOutputUReal\n })\n]);\n\nmodule.exports = coder;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file formatters.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar BigNumber = require('bignumber.js');\nvar utils = require('../utils/utils');\nvar c = require('../utils/config');\nvar SolidityParam = require('./param');\n\n\n/**\n * Formats input value to byte representation of int\n * If value is negative, return it's two's complement\n * If the value is floating point, round it down\n *\n * @method formatInputInt\n * @param {String|Number|BigNumber} value that needs to be formatted\n * @returns {SolidityParam}\n */\nvar formatInputInt = function (value) {\n var padding = c.ETH_PADDING * 2;\n BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE);\n var result = utils.padLeft(utils.toTwosComplement(value).round().toString(16), padding);\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of string\n *\n * @method formatInputBytes\n * @param {String}\n * @returns {SolidityParam}\n */\nvar formatInputBytes = function (value) {\n var result = utils.fromAscii(value, c.ETH_PADDING).substr(2);\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of string\n *\n * @method formatInputDynamicBytes\n * @param {String}\n * @returns {SolidityParam}\n */\nvar formatInputDynamicBytes = function (value) {\n var result = utils.fromAscii(value, c.ETH_PADDING).substr(2);\n return new SolidityParam(formatInputInt(value.length).value + result, 32);\n};\n\n/**\n * Formats input value to byte representation of bool\n *\n * @method formatInputBool\n * @param {Boolean}\n * @returns {SolidityParam}\n */\nvar formatInputBool = function (value) {\n var result = '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of real\n * Values are multiplied by 2^m and encoded as integers\n *\n * @method formatInputReal\n * @param {String|Number|BigNumber}\n * @returns {SolidityParam}\n */\nvar formatInputReal = function (value) {\n return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128)));\n};\n\n/**\n * Check if input value is negative\n *\n * @method signedIsNegative\n * @param {String} value is hex format\n * @returns {Boolean} true if it is negative, otherwise false\n */\nvar signedIsNegative = function (value) {\n return (new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1)) === '1';\n};\n\n/**\n * Formats right-aligned output bytes to int\n *\n * @method formatOutputInt\n * @param {SolidityParam} param\n * @returns {BigNumber} right-aligned output bytes formatted to big number\n */\nvar formatOutputInt = function (param) {\n var value = param.staticPart() || \"0\";\n\n // check if it's negative number\n // it it is, return two's complement\n if (signedIsNegative(value)) {\n return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1);\n }\n return new BigNumber(value, 16);\n};\n\n/**\n * Formats right-aligned output bytes to uint\n *\n * @method formatOutputUInt\n * @param {SolidityParam}\n * @returns {BigNumeber} right-aligned output bytes formatted to uint\n */\nvar formatOutputUInt = function (param) {\n var value = param.staticPart() || \"0\";\n return new BigNumber(value, 16);\n};\n\n/**\n * Formats right-aligned output bytes to real\n *\n * @method formatOutputReal\n * @param {SolidityParam}\n * @returns {BigNumber} input bytes formatted to real\n */\nvar formatOutputReal = function (param) {\n return formatOutputInt(param).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/**\n * Formats right-aligned output bytes to ureal\n *\n * @method formatOutputUReal\n * @param {SolidityParam}\n * @returns {BigNumber} input bytes formatted to ureal\n */\nvar formatOutputUReal = function (param) {\n return formatOutputUInt(param).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/**\n * Should be used to format output bool\n *\n * @method formatOutputBool\n * @param {SolidityParam}\n * @returns {Boolean} right-aligned input bytes formatted to bool\n */\nvar formatOutputBool = function (param) {\n return param.staticPart() === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;\n};\n\n/**\n * Should be used to format output string\n *\n * @method formatOutputBytes\n * @param {SolidityParam} left-aligned hex representation of string\n * @returns {String} ascii string\n */\nvar formatOutputBytes = function (param) {\n // length might also be important!\n return utils.toAscii(param.staticPart());\n};\n\n/**\n * Should be used to format output string\n *\n * @method formatOutputDynamicBytes\n * @param {SolidityParam} left-aligned hex representation of string\n * @returns {String} ascii string\n */\nvar formatOutputDynamicBytes = function (param) {\n // length might also be important!\n return utils.toAscii(param.dynamicPart().slice(64));\n};\n\n/**\n * Should be used to format output address\n *\n * @method formatOutputAddress\n * @param {SolidityParam} right-aligned input bytes\n * @returns {String} address\n */\nvar formatOutputAddress = function (param) {\n var value = param.staticPart();\n return \"0x\" + value.slice(value.length - 40, value.length);\n};\n\nmodule.exports = {\n formatInputInt: formatInputInt,\n formatInputBytes: formatInputBytes,\n formatInputDynamicBytes: formatInputDynamicBytes,\n formatInputBool: formatInputBool,\n formatInputReal: formatInputReal,\n formatOutputInt: formatOutputInt,\n formatOutputUInt: formatOutputUInt,\n formatOutputReal: formatOutputReal,\n formatOutputUReal: formatOutputUReal,\n formatOutputBool: formatOutputBool,\n formatOutputBytes: formatOutputBytes,\n formatOutputDynamicBytes: formatOutputDynamicBytes,\n formatOutputAddress: formatOutputAddress\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file param.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar utils = require('../utils/utils');\n\n/**\n * SolidityParam object prototype.\n * Should be used when encoding, decoding solidity bytes\n */\nvar SolidityParam = function (value, offset) {\n this.value = value || '';\n this.offset = offset; // offset in bytes\n};\n\n/**\n * This method should be used to get length of params's dynamic part\n * \n * @method dynamicPartLength\n * @returns {Number} length of dynamic part (in bytes)\n */\nSolidityParam.prototype.dynamicPartLength = function () {\n return this.dynamicPart().length / 2;\n};\n\n/**\n * This method should be used to create copy of solidity param with different offset\n *\n * @method withOffset\n * @param {Number} offset length in bytes\n * @returns {SolidityParam} new solidity param with applied offset\n */\nSolidityParam.prototype.withOffset = function (offset) {\n return new SolidityParam(this.value, offset);\n};\n\n/**\n * This method should be used to combine solidity params together\n * eg. when appending an array\n *\n * @method combine\n * @param {SolidityParam} param with which we should combine\n * @param {SolidityParam} result of combination\n */\nSolidityParam.prototype.combine = function (param) {\n return new SolidityParam(this.value + param.value); \n};\n\n/**\n * This method should be called to check if param has dynamic size.\n * If it has, it returns true, otherwise false\n *\n * @method isDynamic\n * @returns {Boolean}\n */\nSolidityParam.prototype.isDynamic = function () {\n return this.value.length > 64 || this.offset !== undefined;\n};\n\n/**\n * This method should be called to transform offset to bytes\n *\n * @method offsetAsBytes\n * @returns {String} bytes representation of offset\n */\nSolidityParam.prototype.offsetAsBytes = function () {\n return !this.isDynamic() ? '' : utils.padLeft(utils.toTwosComplement(this.offset).toString(16), 64);\n};\n\n/**\n * This method should be called to get static part of param\n *\n * @method staticPart\n * @returns {String} offset if it is a dynamic param, otherwise value\n */\nSolidityParam.prototype.staticPart = function () {\n if (!this.isDynamic()) {\n return this.value; \n } \n return this.offsetAsBytes();\n};\n\n/**\n * This method should be called to get dynamic part of param\n *\n * @method dynamicPart\n * @returns {String} returns a value if it is a dynamic param, otherwise empty string\n */\nSolidityParam.prototype.dynamicPart = function () {\n return this.isDynamic() ? this.value : '';\n};\n\n/**\n * This method should be called to encode param\n *\n * @method encode\n * @returns {String}\n */\nSolidityParam.prototype.encode = function () {\n return this.staticPart() + this.dynamicPart();\n};\n\n/**\n * This method should be called to encode array of params\n *\n * @method encodeList\n * @param {Array[SolidityParam]} params\n * @returns {String}\n */\nSolidityParam.encodeList = function (params) {\n \n // updating offsets\n var totalOffset = params.length * 32;\n var offsetParams = params.map(function (param) {\n if (!param.isDynamic()) {\n return param;\n }\n var offset = totalOffset;\n totalOffset += param.dynamicPartLength();\n return param.withOffset(offset);\n });\n\n // encode everything!\n return offsetParams.reduce(function (result, param) {\n return result + param.dynamicPart();\n }, offsetParams.reduce(function (result, param) {\n return result + param.staticPart();\n }, ''));\n};\n\n/**\n * This method should be used to decode plain (static) solidity param at given index\n *\n * @method decodeParam\n * @param {String} bytes\n * @param {Number} index\n * @returns {SolidityParam}\n */\nSolidityParam.decodeParam = function (bytes, index) {\n index = index || 0;\n return new SolidityParam(bytes.substr(index * 64, 64)); \n};\n\n/**\n * This method should be called to get offset value from bytes at given index\n *\n * @method getOffset\n * @param {String} bytes\n * @param {Number} index\n * @returns {Number} offset as number\n */\nvar getOffset = function (bytes, index) {\n // we can do this cause offset is rather small\n return parseInt('0x' + bytes.substr(index * 64, 64));\n};\n\n/**\n * This method should be called to decode solidity bytes param at given index\n *\n * @method decodeBytes\n * @param {String} bytes\n * @param {Number} index\n * @returns {SolidityParam}\n */\nSolidityParam.decodeBytes = function (bytes, index) {\n index = index || 0;\n //TODO add support for strings longer than 32 bytes\n //var length = parseInt('0x' + bytes.substr(offset * 64, 64));\n\n var offset = getOffset(bytes, index);\n\n // 2 * , cause we also parse length\n return new SolidityParam(bytes.substr(offset * 2, 2 * 64), 0);\n};\n\n/**\n * This method should be used to decode solidity array at given index\n *\n * @method decodeArray\n * @param {String} bytes\n * @param {Number} index\n * @returns {SolidityParam}\n */\nSolidityParam.decodeArray = function (bytes, index) {\n index = index || 0;\n var offset = getOffset(bytes, index);\n var length = parseInt('0x' + bytes.substr(offset * 2, 64));\n return new SolidityParam(bytes.substr(offset * 2, (length + 1) * 64), 0);\n};\n\nmodule.exports = SolidityParam;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file coder.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar BigNumber = require('bignumber.js');\nvar utils = require('../utils/utils');\nvar f = require('./formatters');\nvar SolidityParam = require('./param');\n\n/**\n * Should be used to check if a type is an array type\n *\n * @method isArrayType\n * @param {String} type\n * @return {Bool} true is the type is an array, otherwise false\n */\nvar isArrayType = function (type) {\n return type.slice(-2) === '[]';\n};\n\n/**\n * SolidityType prototype is used to encode/decode solidity params of certain type\n */\nvar SolidityType = function (config) {\n this._name = config.name;\n this._match = config.match;\n this._mode = config.mode;\n this._inputFormatter = config.inputFormatter;\n this._outputFormatter = config.outputFormatter;\n};\n\n/**\n * Should be used to determine if this SolidityType do match given type\n *\n * @method isType\n * @param {String} name\n * @return {Bool} true if type match this SolidityType, otherwise false\n */\nSolidityType.prototype.isType = function (name) {\n if (this._match === 'strict') {\n return this._name === name || (name.indexOf(this._name) === 0 && name.slice(this._name.length) === '[]');\n } else if (this._match === 'prefix') {\n // TODO better type detection!\n return name.indexOf(this._name) === 0;\n }\n};\n\n/**\n * Should be used to transform plain param to SolidityParam object\n *\n * @method formatInput\n * @param {Object} param - plain object, or an array of objects\n * @param {Bool} arrayType - true if a param should be encoded as an array\n * @return {SolidityParam} encoded param wrapped in SolidityParam object \n */\nSolidityType.prototype.formatInput = function (param, arrayType) {\n if (utils.isArray(param) && arrayType) { // TODO: should fail if this two are not the same\n var self = this;\n return param.map(function (p) {\n return self._inputFormatter(p);\n }).reduce(function (acc, current) {\n return acc.combine(current);\n }, f.formatInputInt(param.length)).withOffset(32);\n } \n return this._inputFormatter(param);\n};\n\n/**\n * Should be used to transoform SolidityParam to plain param\n *\n * @method formatOutput\n * @param {SolidityParam} byteArray\n * @param {Bool} arrayType - true if a param should be decoded as an array\n * @return {Object} plain decoded param\n */\nSolidityType.prototype.formatOutput = function (param, arrayType) {\n if (arrayType) {\n // let's assume, that we solidity will never return long arrays :P \n var result = [];\n var length = new BigNumber(param.dynamicPart().slice(0, 64), 16);\n for (var i = 0; i < length * 64; i += 64) {\n result.push(this._outputFormatter(new SolidityParam(param.dynamicPart().substr(i + 64, 64))));\n }\n return result;\n }\n return this._outputFormatter(param);\n};\n\n/**\n * Should be used to slice single param from bytes\n *\n * @method sliceParam\n * @param {String} bytes\n * @param {Number} index of param to slice\n * @param {String} type\n * @returns {SolidityParam} param\n */\nSolidityType.prototype.sliceParam = function (bytes, index, type) {\n if (this._mode === 'bytes') {\n return SolidityParam.decodeBytes(bytes, index);\n } else if (isArrayType(type)) {\n return SolidityParam.decodeArray(bytes, index);\n }\n return SolidityParam.decodeParam(bytes, index);\n};\n\n/**\n * SolidityCoder prototype should be used to encode/decode solidity params of any type\n */\nvar SolidityCoder = function (types) {\n this._types = types;\n};\n\n/**\n * This method should be used to transform type to SolidityType\n *\n * @method _requireType\n * @param {String} type\n * @returns {SolidityType} \n * @throws {Error} throws if no matching type is found\n */\nSolidityCoder.prototype._requireType = function (type) {\n var solidityType = this._types.filter(function (t) {\n return t.isType(type);\n })[0];\n\n if (!solidityType) {\n throw Error('invalid solidity type!: ' + type);\n }\n\n return solidityType;\n};\n\n/**\n * Should be used to transform plain param of given type to SolidityParam\n *\n * @method _formatInput\n * @param {String} type of param\n * @param {Object} plain param\n * @return {SolidityParam}\n */\nSolidityCoder.prototype._formatInput = function (type, param) {\n return this._requireType(type).formatInput(param, isArrayType(type));\n};\n\n/**\n * Should be used to encode plain param\n *\n * @method encodeParam\n * @param {String} type\n * @param {Object} plain param\n * @return {String} encoded plain param\n */\nSolidityCoder.prototype.encodeParam = function (type, param) {\n return this._formatInput(type, param).encode();\n};\n\n/**\n * Should be used to encode list of params\n *\n * @method encodeParams\n * @param {Array} types\n * @param {Array} params\n * @return {String} encoded list of params\n */\nSolidityCoder.prototype.encodeParams = function (types, params) {\n var self = this;\n var solidityParams = types.map(function (type, index) {\n return self._formatInput(type, params[index]);\n });\n\n return SolidityParam.encodeList(solidityParams);\n};\n\n/**\n * Should be used to decode bytes to plain param\n *\n * @method decodeParam\n * @param {String} type\n * @param {String} bytes\n * @return {Object} plain param\n */\nSolidityCoder.prototype.decodeParam = function (type, bytes) {\n return this.decodeParams([type], bytes)[0];\n};\n\n/**\n * Should be used to decode list of params\n *\n * @method decodeParam\n * @param {Array} types\n * @param {String} bytes\n * @return {Array} array of plain params\n */\nSolidityCoder.prototype.decodeParams = function (types, bytes) {\n var self = this;\n return types.map(function (type, index) {\n var solidityType = self._requireType(type);\n var p = solidityType.sliceParam(bytes, index, type);\n return solidityType.formatOutput(p, isArrayType(type));\n });\n};\n\nvar coder = new SolidityCoder([\n new SolidityType({\n name: 'address',\n match: 'strict',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputAddress\n }),\n new SolidityType({\n name: 'bool',\n match: 'strict',\n mode: 'value',\n inputFormatter: f.formatInputBool,\n outputFormatter: f.formatOutputBool\n }),\n new SolidityType({\n name: 'int',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputInt,\n }),\n new SolidityType({\n name: 'uint',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputUInt\n }),\n new SolidityType({\n name: 'bytes',\n match: 'strict',\n mode: 'bytes',\n inputFormatter: f.formatInputDynamicBytes,\n outputFormatter: f.formatOutputDynamicBytes\n }),\n new SolidityType({\n name: 'bytes',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputBytes,\n outputFormatter: f.formatOutputBytes\n }),\n new SolidityType({\n name: 'string',\n match: 'strict',\n mode: 'bytes',\n inputFormatter: f.formatInputString,\n outputFormatter: f.formatOutputString\n }),\n new SolidityType({\n name: 'real',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputReal,\n outputFormatter: f.formatOutputReal\n }),\n new SolidityType({\n name: 'ureal',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputReal,\n outputFormatter: f.formatOutputUReal\n })\n]);\n\nmodule.exports = coder;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file formatters.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar BigNumber = require('bignumber.js');\nvar utils = require('../utils/utils');\nvar c = require('../utils/config');\nvar SolidityParam = require('./param');\n\n\n/**\n * Formats input value to byte representation of int\n * If value is negative, return it's two's complement\n * If the value is floating point, round it down\n *\n * @method formatInputInt\n * @param {String|Number|BigNumber} value that needs to be formatted\n * @returns {SolidityParam}\n */\nvar formatInputInt = function (value) {\n var padding = c.ETH_PADDING * 2;\n BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE);\n var result = utils.padLeft(utils.toTwosComplement(value).round().toString(16), padding);\n return new SolidityParam(result);\n};\n\n/**\n * Formats input bytes\n *\n * @method formatInputBytes\n * @param {String}\n * @returns {SolidityParam}\n */\nvar formatInputBytes = function (value) {\n var result = utils.padRight(utils.toHex(value).substr(2), 64);\n return new SolidityParam(result);\n};\n\n/**\n * Formats input bytes\n *\n * @method formatDynamicInputBytes\n * @param {String}\n * @returns {SolidityParam}\n */\nvar formatInputDynamicBytes = function (value) {\n value = utils.toHex(value).substr(2);\n var l = Math.floor((value.length + 63) / 64);\n var result = utils.padRight(value, l * 64);\n var length = Math.floor(value.length / 2);\n return new SolidityParam(formatInputInt(length).value + result, 32);\n};\n\n/**\n * Formats input value to byte representation of string\n *\n * @method formatInputString\n * @param {String}\n * @returns {SolidityParam}\n */\nvar formatInputString = function (value) {\n var result = utils.fromAscii(value).substr(2);\n var l = Math.floor((result.length + 63) / 64);\n result = utils.padRight(result, l * 64);\n return new SolidityParam(formatInputInt(value.length).value + result, 32);\n};\n\n/**\n * Formats input value to byte representation of bool\n *\n * @method formatInputBool\n * @param {Boolean}\n * @returns {SolidityParam}\n */\nvar formatInputBool = function (value) {\n var result = '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of real\n * Values are multiplied by 2^m and encoded as integers\n *\n * @method formatInputReal\n * @param {String|Number|BigNumber}\n * @returns {SolidityParam}\n */\nvar formatInputReal = function (value) {\n return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128)));\n};\n\n/**\n * Check if input value is negative\n *\n * @method signedIsNegative\n * @param {String} value is hex format\n * @returns {Boolean} true if it is negative, otherwise false\n */\nvar signedIsNegative = function (value) {\n return (new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1)) === '1';\n};\n\n/**\n * Formats right-aligned output bytes to int\n *\n * @method formatOutputInt\n * @param {SolidityParam} param\n * @returns {BigNumber} right-aligned output bytes formatted to big number\n */\nvar formatOutputInt = function (param) {\n var value = param.staticPart() || \"0\";\n\n // check if it's negative number\n // it it is, return two's complement\n if (signedIsNegative(value)) {\n return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1);\n }\n return new BigNumber(value, 16);\n};\n\n/**\n * Formats right-aligned output bytes to uint\n *\n * @method formatOutputUInt\n * @param {SolidityParam}\n * @returns {BigNumeber} right-aligned output bytes formatted to uint\n */\nvar formatOutputUInt = function (param) {\n var value = param.staticPart() || \"0\";\n return new BigNumber(value, 16);\n};\n\n/**\n * Formats right-aligned output bytes to real\n *\n * @method formatOutputReal\n * @param {SolidityParam}\n * @returns {BigNumber} input bytes formatted to real\n */\nvar formatOutputReal = function (param) {\n return formatOutputInt(param).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/**\n * Formats right-aligned output bytes to ureal\n *\n * @method formatOutputUReal\n * @param {SolidityParam}\n * @returns {BigNumber} input bytes formatted to ureal\n */\nvar formatOutputUReal = function (param) {\n return formatOutputUInt(param).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/**\n * Should be used to format output bool\n *\n * @method formatOutputBool\n * @param {SolidityParam}\n * @returns {Boolean} right-aligned input bytes formatted to bool\n */\nvar formatOutputBool = function (param) {\n return param.staticPart() === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;\n};\n\n/**\n * Should be used to format output bytes\n *\n * @method formatOutputBytes\n * @param {SolidityParam} left-aligned hex representation of string\n * @returns {String} hex string\n */\nvar formatOutputBytes = function (param) {\n return '0x' + param.staticPart();\n};\n\n/**\n * Should be used to format output bytes\n *\n * @method formatOutputDynamicBytes\n * @param {SolidityParam} left-aligned hex representation of string\n * @returns {String} hex string\n */\nvar formatOutputDynamicBytes = function (param) {\n var length = (new BigNumber(param.dynamicPart().slice(0, 64), 16)).toNumber() * 2;\n return '0x' + param.dynamicPart().substr(64, length);\n};\n\n/**\n * Should be used to format output string\n *\n * @method formatOutputString\n * @param {SolidityParam} left-aligned hex representation of string\n * @returns {String} ascii string\n */\nvar formatOutputString = function (param) {\n var length = (new BigNumber(param.dynamicPart().slice(0, 64), 16)).toNumber() * 2;\n return utils.toAscii(param.dynamicPart().substr(64, length));\n};\n\n/**\n * Should be used to format output address\n *\n * @method formatOutputAddress\n * @param {SolidityParam} right-aligned input bytes\n * @returns {String} address\n */\nvar formatOutputAddress = function (param) {\n var value = param.staticPart();\n return \"0x\" + value.slice(value.length - 40, value.length);\n};\n\nmodule.exports = {\n formatInputInt: formatInputInt,\n formatInputBytes: formatInputBytes,\n formatInputDynamicBytes: formatInputDynamicBytes,\n formatInputString: formatInputString,\n formatInputBool: formatInputBool,\n formatInputReal: formatInputReal,\n formatOutputInt: formatOutputInt,\n formatOutputUInt: formatOutputUInt,\n formatOutputReal: formatOutputReal,\n formatOutputUReal: formatOutputUReal,\n formatOutputBool: formatOutputBool,\n formatOutputBytes: formatOutputBytes,\n formatOutputDynamicBytes: formatOutputDynamicBytes,\n formatOutputString: formatOutputString,\n formatOutputAddress: formatOutputAddress\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file param.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar utils = require('../utils/utils');\n\n/**\n * SolidityParam object prototype.\n * Should be used when encoding, decoding solidity bytes\n */\nvar SolidityParam = function (value, offset) {\n this.value = value || '';\n this.offset = offset; // offset in bytes\n};\n\n/**\n * This method should be used to get length of params's dynamic part\n * \n * @method dynamicPartLength\n * @returns {Number} length of dynamic part (in bytes)\n */\nSolidityParam.prototype.dynamicPartLength = function () {\n return this.dynamicPart().length / 2;\n};\n\n/**\n * This method should be used to create copy of solidity param with different offset\n *\n * @method withOffset\n * @param {Number} offset length in bytes\n * @returns {SolidityParam} new solidity param with applied offset\n */\nSolidityParam.prototype.withOffset = function (offset) {\n return new SolidityParam(this.value, offset);\n};\n\n/**\n * This method should be used to combine solidity params together\n * eg. when appending an array\n *\n * @method combine\n * @param {SolidityParam} param with which we should combine\n * @param {SolidityParam} result of combination\n */\nSolidityParam.prototype.combine = function (param) {\n return new SolidityParam(this.value + param.value); \n};\n\n/**\n * This method should be called to check if param has dynamic size.\n * If it has, it returns true, otherwise false\n *\n * @method isDynamic\n * @returns {Boolean}\n */\nSolidityParam.prototype.isDynamic = function () {\n return this.value.length > 64 || this.offset !== undefined;\n};\n\n/**\n * This method should be called to transform offset to bytes\n *\n * @method offsetAsBytes\n * @returns {String} bytes representation of offset\n */\nSolidityParam.prototype.offsetAsBytes = function () {\n return !this.isDynamic() ? '' : utils.padLeft(utils.toTwosComplement(this.offset).toString(16), 64);\n};\n\n/**\n * This method should be called to get static part of param\n *\n * @method staticPart\n * @returns {String} offset if it is a dynamic param, otherwise value\n */\nSolidityParam.prototype.staticPart = function () {\n if (!this.isDynamic()) {\n return this.value; \n } \n return this.offsetAsBytes();\n};\n\n/**\n * This method should be called to get dynamic part of param\n *\n * @method dynamicPart\n * @returns {String} returns a value if it is a dynamic param, otherwise empty string\n */\nSolidityParam.prototype.dynamicPart = function () {\n return this.isDynamic() ? this.value : '';\n};\n\n/**\n * This method should be called to encode param\n *\n * @method encode\n * @returns {String}\n */\nSolidityParam.prototype.encode = function () {\n return this.staticPart() + this.dynamicPart();\n};\n\n/**\n * This method should be called to encode array of params\n *\n * @method encodeList\n * @param {Array[SolidityParam]} params\n * @returns {String}\n */\nSolidityParam.encodeList = function (params) {\n \n // updating offsets\n var totalOffset = params.length * 32;\n var offsetParams = params.map(function (param) {\n if (!param.isDynamic()) {\n return param;\n }\n var offset = totalOffset;\n totalOffset += param.dynamicPartLength();\n return param.withOffset(offset);\n });\n\n // encode everything!\n return offsetParams.reduce(function (result, param) {\n return result + param.dynamicPart();\n }, offsetParams.reduce(function (result, param) {\n return result + param.staticPart();\n }, ''));\n};\n\n/**\n * This method should be used to decode plain (static) solidity param at given index\n *\n * @method decodeParam\n * @param {String} bytes\n * @param {Number} index\n * @returns {SolidityParam}\n */\nSolidityParam.decodeParam = function (bytes, index) {\n index = index || 0;\n return new SolidityParam(bytes.substr(index * 64, 64)); \n};\n\n/**\n * This method should be called to get offset value from bytes at given index\n *\n * @method getOffset\n * @param {String} bytes\n * @param {Number} index\n * @returns {Number} offset as number\n */\nvar getOffset = function (bytes, index) {\n // we can do this cause offset is rather small\n return parseInt('0x' + bytes.substr(index * 64, 64));\n};\n\n/**\n * This method should be called to decode solidity bytes param at given index\n *\n * @method decodeBytes\n * @param {String} bytes\n * @param {Number} index\n * @returns {SolidityParam}\n */\nSolidityParam.decodeBytes = function (bytes, index) {\n index = index || 0;\n\n var offset = getOffset(bytes, index);\n\n var l = parseInt('0x' + bytes.substr(offset * 2, 64));\n l = Math.floor((l + 31) / 32);\n\n // (1 + l) * , cause we also parse length\n return new SolidityParam(bytes.substr(offset * 2, (1 + l) * 64), 0);\n};\n\n/**\n * This method should be used to decode solidity array at given index\n *\n * @method decodeArray\n * @param {String} bytes\n * @param {Number} index\n * @returns {SolidityParam}\n */\nSolidityParam.decodeArray = function (bytes, index) {\n index = index || 0;\n var offset = getOffset(bytes, index);\n var length = parseInt('0x' + bytes.substr(offset * 2, 64));\n return new SolidityParam(bytes.substr(offset * 2, (length + 1) * 64), 0);\n};\n\nmodule.exports = SolidityParam;\n\n", "'use strict';\n\n// go env doesn't have and need XMLHttpRequest\nif (typeof XMLHttpRequest === 'undefined') {\n exports.XMLHttpRequest = {};\n} else {\n exports.XMLHttpRequest = XMLHttpRequest; // jshint ignore:line\n}\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file config.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\n/**\n * Utils\n * \n * @module utils\n */\n\n/**\n * Utility functions\n * \n * @class [utils] config\n * @constructor\n */\n\n/// required to define ETH_BIGNUMBER_ROUNDING_MODE\nvar BigNumber = require('bignumber.js');\n\nvar ETH_UNITS = [\n 'wei',\n 'kwei',\n 'Mwei',\n 'Gwei',\n 'szabo',\n 'finney',\n 'femtoether',\n 'picoether',\n 'nanoether',\n 'microether',\n 'milliether',\n 'nano',\n 'micro',\n 'milli',\n 'ether',\n 'grand',\n 'Mether',\n 'Gether',\n 'Tether',\n 'Pether',\n 'Eether',\n 'Zether',\n 'Yether',\n 'Nether',\n 'Dether',\n 'Vether',\n 'Uether'\n];\n\nmodule.exports = {\n ETH_PADDING: 32,\n ETH_SIGNATURE_LENGTH: 4,\n ETH_UNITS: ETH_UNITS,\n ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN },\n ETH_POLLING_TIMEOUT: 1000/2,\n defaultBlock: 'latest',\n defaultAccount: undefined\n};\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file sha3.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar utils = require('./utils');\nvar sha3 = require('crypto-js/sha3');\n\nmodule.exports = function (str, isNew) {\n if (str.substr(0, 2) === '0x' && !isNew) {\n console.warn('requirement of using web3.fromAscii before sha3 is deprecated');\n console.warn('new usage: \\'web3.sha3(\"hello\")\\'');\n console.warn('see https://github.com/ethereum/web3.js/pull/205');\n console.warn('if you need to hash hex value, you can do \\'sha3(\"0xfff\", true)\\'');\n str = utils.toAscii(str);\n }\n\n return sha3(str, {\n outputLength: 256\n }).toString();\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file utils.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\n/**\n * Utils\n * \n * @module utils\n */\n\n/**\n * Utility functions\n * \n * @class [utils] utils\n * @constructor\n */\n\nvar BigNumber = require('bignumber.js');\n\nvar unitMap = {\n 'wei': '1',\n 'kwei': '1000',\n 'ada': '1000',\n 'femtoether': '1000',\n 'mwei': '1000000',\n 'babbage': '1000000',\n 'picoether': '1000000',\n 'gwei': '1000000000',\n 'shannon': '1000000000',\n 'nanoether': '1000000000',\n 'nano': '1000000000',\n 'szabo': '1000000000000',\n 'microether': '1000000000000',\n 'micro': '1000000000000',\n 'finney': '1000000000000000',\n 'milliether': '1000000000000000',\n 'milli': '1000000000000000',\n 'ether': '1000000000000000000',\n 'kether': '1000000000000000000000',\n 'grand': '1000000000000000000000',\n 'einstein': '1000000000000000000000',\n 'mether': '1000000000000000000000000',\n 'gether': '1000000000000000000000000000',\n 'tether': '1000000000000000000000000000000'\n};\n\n/**\n * Should be called to pad string to expected length\n *\n * @method padLeft\n * @param {String} string to be padded\n * @param {Number} characters that result string should have\n * @param {String} sign, by default 0\n * @returns {String} right aligned string\n */\nvar padLeft = function (string, chars, sign) {\n return new Array(chars - string.length + 1).join(sign ? sign : \"0\") + string;\n};\n\n/** \n * Should be called to get sting from it's hex representation\n *\n * @method toAscii\n * @param {String} string in hex\n * @returns {String} ascii string representation of hex value\n */\nvar toAscii = function(hex) {\n// Find termination\n var str = \"\";\n var i = 0, l = hex.length;\n if (hex.substring(0, 2) === '0x') {\n i = 2;\n }\n for (; i < l; i+=2) {\n var code = parseInt(hex.substr(i, 2), 16);\n if (code === 0) {\n break;\n }\n\n str += String.fromCharCode(code);\n }\n\n return str;\n};\n \n/**\n * Shold be called to get hex representation (prefixed by 0x) of ascii string \n *\n * @method toHexNative\n * @param {String} string\n * @returns {String} hex representation of input string\n */\nvar toHexNative = function(str) {\n var hex = \"\";\n for(var i = 0; i < str.length; i++) {\n var n = str.charCodeAt(i).toString(16);\n hex += n.length < 2 ? '0' + n : n;\n }\n\n return hex;\n};\n\n/**\n * Shold be called to get hex representation (prefixed by 0x) of ascii string \n *\n * @method fromAscii\n * @param {String} string\n * @param {Number} optional padding\n * @returns {String} hex representation of input string\n */\nvar fromAscii = function(str, pad) {\n pad = pad === undefined ? 0 : pad;\n var hex = toHexNative(str);\n while (hex.length < pad*2)\n hex += \"00\";\n return \"0x\" + hex;\n};\n\n/**\n * Should be used to create full function/event name from json abi\n *\n * @method transformToFullName\n * @param {Object} json-abi\n * @return {String} full fnction/event name\n */\nvar transformToFullName = function (json) {\n if (json.name.indexOf('(') !== -1) {\n return json.name;\n }\n\n var typeName = json.inputs.map(function(i){return i.type; }).join();\n return json.name + '(' + typeName + ')';\n};\n\n/**\n * Should be called to get display name of contract function\n * \n * @method extractDisplayName\n * @param {String} name of function/event\n * @returns {String} display name for function/event eg. multiply(uint256) -> multiply\n */\nvar extractDisplayName = function (name) {\n var length = name.indexOf('('); \n return length !== -1 ? name.substr(0, length) : name;\n};\n\n/// @returns overloaded part of function/event name\nvar extractTypeName = function (name) {\n /// TODO: make it invulnerable\n var length = name.indexOf('(');\n return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)).replace(' ', '') : \"\";\n};\n\n/**\n * Converts value to it's decimal representation in string\n *\n * @method toDecimal\n * @param {String|Number|BigNumber}\n * @return {String}\n */\nvar toDecimal = function (value) {\n return toBigNumber(value).toNumber();\n};\n\n/**\n * Converts value to it's hex representation\n *\n * @method fromDecimal\n * @param {String|Number|BigNumber}\n * @return {String}\n */\nvar fromDecimal = function (value) {\n var number = toBigNumber(value);\n var result = number.toString(16);\n\n return number.lessThan(0) ? '-0x' + result.substr(1) : '0x' + result;\n};\n\n/**\n * Auto converts any given value into it's hex representation.\n *\n * And even stringifys objects before.\n *\n * @method toHex\n * @param {String|Number|BigNumber|Object}\n * @return {String}\n */\nvar toHex = function (val) {\n /*jshint maxcomplexity:7 */\n\n if (isBoolean(val))\n return fromDecimal(+val);\n\n if (isBigNumber(val))\n return fromDecimal(val);\n\n if (isObject(val))\n return fromAscii(JSON.stringify(val));\n\n // if its a negative number, pass it through fromDecimal\n if (isString(val)) {\n if (val.indexOf('-0x') === 0)\n return fromDecimal(val);\n else if (!isFinite(val))\n return fromAscii(val);\n }\n\n return fromDecimal(val);\n};\n\n/**\n * Returns value of unit in Wei\n *\n * @method getValueOfUnit\n * @param {String} unit the unit to convert to, default ether\n * @returns {BigNumber} value of the unit (in Wei)\n * @throws error if the unit is not correct:w\n */\nvar getValueOfUnit = function (unit) {\n unit = unit ? unit.toLowerCase() : 'ether';\n var unitValue = unitMap[unit];\n if (unitValue === undefined) {\n throw new Error('This unit doesn\\'t exists, please use the one of the following units' + JSON.stringify(unitMap, null, 2));\n }\n return new BigNumber(unitValue, 10);\n};\n\n/**\n * Takes a number of wei and converts it to any other ether unit.\n *\n * Possible units are:\n * SI Short SI Full Effigy Other\n * - kwei femtoether ada\n * - mwei picoether babbage\n * - gwei nanoether shannon nano\n * - -- microether szabo micro\n * - -- milliether finney milli\n * - ether -- --\n * - kether einstein grand \n * - mether\n * - gether\n * - tether\n *\n * @method fromWei\n * @param {Number|String} number can be a number, number string or a HEX of a decimal\n * @param {String} unit the unit to convert to, default ether\n * @return {String|Object} When given a BigNumber object it returns one as well, otherwise a number\n*/\nvar fromWei = function(number, unit) {\n var returnValue = toBigNumber(number).dividedBy(getValueOfUnit(unit));\n\n return isBigNumber(number) ? returnValue : returnValue.toString(10); \n};\n\n/**\n * Takes a number of a unit and converts it to wei.\n *\n * Possible units are:\n * SI Short SI Full Effigy Other\n * - kwei femtoether ada\n * - mwei picoether babbage \n * - gwei nanoether shannon nano\n * - -- microether szabo micro\n * - -- milliether finney milli\n * - ether -- --\n * - kether einstein grand \n * - mether\n * - gether\n * - tether\n *\n * @method toWei\n * @param {Number|String|BigNumber} number can be a number, number string or a HEX of a decimal\n * @param {String} unit the unit to convert from, default ether\n * @return {String|Object} When given a BigNumber object it returns one as well, otherwise a number\n*/\nvar toWei = function(number, unit) {\n var returnValue = toBigNumber(number).times(getValueOfUnit(unit));\n\n return isBigNumber(number) ? returnValue : returnValue.toString(10); \n};\n\n/**\n * Takes an input and transforms it into an bignumber\n *\n * @method toBigNumber\n * @param {Number|String|BigNumber} a number, string, HEX string or BigNumber\n * @return {BigNumber} BigNumber\n*/\nvar toBigNumber = function(number) {\n /*jshint maxcomplexity:5 */\n number = number || 0;\n if (isBigNumber(number))\n return number;\n\n if (isString(number) && (number.indexOf('0x') === 0 || number.indexOf('-0x') === 0)) {\n return new BigNumber(number.replace('0x',''), 16);\n }\n \n return new BigNumber(number.toString(10), 10);\n};\n\n/**\n * Takes and input transforms it into bignumber and if it is negative value, into two's complement\n *\n * @method toTwosComplement\n * @param {Number|String|BigNumber}\n * @return {BigNumber}\n */\nvar toTwosComplement = function (number) {\n var bigNumber = toBigNumber(number);\n if (bigNumber.lessThan(0)) {\n return new BigNumber(\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\", 16).plus(bigNumber).plus(1);\n }\n return bigNumber;\n};\n\n/**\n * Checks if the given string is strictly an address\n *\n * @method isStrictAddress\n * @param {String} address the given HEX adress\n * @return {Boolean}\n*/\nvar isStrictAddress = function (address) {\n return /^0x[0-9a-f]{40}$/.test(address);\n};\n\n/**\n * Checks if the given string is an address\n *\n * @method isAddress\n * @param {String} address the given HEX adress\n * @return {Boolean}\n*/\nvar isAddress = function (address) {\n return /^(0x)?[0-9a-f]{40}$/.test(address);\n};\n\n/**\n * Transforms given string to valid 20 bytes-length addres with 0x prefix\n *\n * @method toAddress\n * @param {String} address\n * @return {String} formatted address\n */\nvar toAddress = function (address) {\n if (isStrictAddress(address)) {\n return address;\n }\n \n if (/^[0-9a-f]{40}$/.test(address)) {\n return '0x' + address;\n }\n\n return '0x' + padLeft(toHex(address).substr(2), 40);\n};\n\n\n/**\n * Returns true if object is BigNumber, otherwise false\n *\n * @method isBigNumber\n * @param {Object}\n * @return {Boolean} \n */\nvar isBigNumber = function (object) {\n return object instanceof BigNumber ||\n (object && object.constructor && object.constructor.name === 'BigNumber');\n};\n\n/**\n * Returns true if object is string, otherwise false\n * \n * @method isString\n * @param {Object}\n * @return {Boolean}\n */\nvar isString = function (object) {\n return typeof object === 'string' ||\n (object && object.constructor && object.constructor.name === 'String');\n};\n\n/**\n * Returns true if object is function, otherwise false\n *\n * @method isFunction\n * @param {Object}\n * @return {Boolean}\n */\nvar isFunction = function (object) {\n return typeof object === 'function';\n};\n\n/**\n * Returns true if object is Objet, otherwise false\n *\n * @method isObject\n * @param {Object}\n * @return {Boolean}\n */\nvar isObject = function (object) {\n return typeof object === 'object';\n};\n\n/**\n * Returns true if object is boolean, otherwise false\n *\n * @method isBoolean\n * @param {Object}\n * @return {Boolean}\n */\nvar isBoolean = function (object) {\n return typeof object === 'boolean';\n};\n\n/**\n * Returns true if object is array, otherwise false\n *\n * @method isArray\n * @param {Object}\n * @return {Boolean}\n */\nvar isArray = function (object) {\n return object instanceof Array; \n};\n\n/**\n * Returns true if given string is valid json object\n * \n * @method isJson\n * @param {String}\n * @return {Boolean}\n */\nvar isJson = function (str) {\n try {\n return !!JSON.parse(str);\n } catch (e) {\n return false;\n }\n};\n\n/**\n * This method should be called to check if string is valid ethereum IBAN number\n * Supports direct and indirect IBANs\n *\n * @method isIBAN\n * @param {String}\n * @return {Boolean}\n */\nvar isIBAN = function (iban) {\n return /^XE[0-9]{2}(ETH[0-9A-Z]{13}|[0-9A-Z]{30})$/.test(iban);\n};\n\nmodule.exports = {\n padLeft: padLeft,\n toHex: toHex,\n toDecimal: toDecimal,\n fromDecimal: fromDecimal,\n toAscii: toAscii,\n fromAscii: fromAscii,\n transformToFullName: transformToFullName,\n extractDisplayName: extractDisplayName,\n extractTypeName: extractTypeName,\n toWei: toWei,\n fromWei: fromWei,\n toBigNumber: toBigNumber,\n toTwosComplement: toTwosComplement,\n toAddress: toAddress,\n isBigNumber: isBigNumber,\n isStrictAddress: isStrictAddress,\n isAddress: isAddress,\n isFunction: isFunction,\n isString: isString,\n isObject: isObject,\n isBoolean: isBoolean,\n isArray: isArray,\n isJson: isJson,\n isIBAN: isIBAN\n};\n\n", - "module.exports={\n \"version\": \"0.6.0\"\n}\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file web3.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * Gav Wood \n * @date 2014\n */\n\nvar version = require('./version.json');\nvar net = require('./web3/net');\nvar eth = require('./web3/eth');\nvar db = require('./web3/db');\nvar shh = require('./web3/shh');\nvar watches = require('./web3/watches');\nvar Filter = require('./web3/filter');\nvar utils = require('./utils/utils');\nvar formatters = require('./web3/formatters');\nvar RequestManager = require('./web3/requestmanager');\nvar c = require('./utils/config');\nvar Property = require('./web3/property');\nvar Batch = require('./web3/batch');\nvar sha3 = require('./utils/sha3');\n\nvar web3Properties = [\n new Property({\n name: 'version.client',\n getter: 'web3_clientVersion'\n }),\n new Property({\n name: 'version.network',\n getter: 'net_version',\n inputFormatter: utils.toDecimal\n }),\n new Property({\n name: 'version.ethereum',\n getter: 'eth_protocolVersion',\n inputFormatter: utils.toDecimal\n }),\n new Property({\n name: 'version.whisper',\n getter: 'shh_version',\n inputFormatter: utils.toDecimal\n })\n];\n\n/// creates methods in a given object based on method description on input\n/// setups api calls for these methods\nvar setupMethods = function (obj, methods) {\n methods.forEach(function (method) {\n method.attachToObject(obj);\n });\n};\n\n/// creates properties in a given object based on properties description on input\n/// setups api calls for these properties\nvar setupProperties = function (obj, properties) {\n properties.forEach(function (property) {\n property.attachToObject(obj);\n });\n};\n\n/// setups web3 object, and it's in-browser executed methods\nvar web3 = {};\nweb3.providers = {};\nweb3.version = {};\nweb3.version.api = version.version;\nweb3.eth = {};\n\n/*jshint maxparams:4 */\nweb3.eth.filter = function (fil, eventParams, options, formatter) {\n\n // if its event, treat it differently\n // TODO: simplify and remove\n if (fil._isEvent) {\n return fil(eventParams, options);\n }\n\n // output logs works for blockFilter and pendingTransaction filters?\n return new Filter(fil, watches.eth(), formatter || formatters.outputLogFormatter);\n};\n/*jshint maxparams:3 */\n\nweb3.shh = {};\nweb3.shh.filter = function (fil) {\n return new Filter(fil, watches.shh(), formatters.outputPostFormatter);\n};\nweb3.net = {};\nweb3.db = {};\nweb3.setProvider = function (provider) {\n RequestManager.getInstance().setProvider(provider);\n};\nweb3.reset = function () {\n RequestManager.getInstance().reset();\n c.defaultBlock = 'latest';\n c.defaultAccount = undefined;\n};\nweb3.toHex = utils.toHex;\nweb3.toAscii = utils.toAscii;\nweb3.fromAscii = utils.fromAscii;\nweb3.toDecimal = utils.toDecimal;\nweb3.fromDecimal = utils.fromDecimal;\nweb3.toBigNumber = utils.toBigNumber;\nweb3.toWei = utils.toWei;\nweb3.fromWei = utils.fromWei;\nweb3.isAddress = utils.isAddress;\nweb3.isIBAN = utils.isIBAN;\nweb3.sha3 = sha3;\nweb3.createBatch = function () {\n return new Batch();\n};\n\n// ADD defaultblock\nObject.defineProperty(web3.eth, 'defaultBlock', {\n get: function () {\n return c.defaultBlock;\n },\n set: function (val) {\n c.defaultBlock = val;\n return val;\n }\n});\n\nObject.defineProperty(web3.eth, 'defaultAccount', {\n get: function () {\n return c.defaultAccount;\n },\n set: function (val) {\n c.defaultAccount = val;\n return val;\n }\n});\n\n\n// EXTEND\nweb3._extend = function(extension){\n /*jshint maxcomplexity: 6 */\n\n if(extension.property && !web3[extension.property])\n web3[extension.property] = {};\n\n setupMethods(web3[extension.property] || web3, extension.methods || []);\n setupProperties(web3[extension.property] || web3, extension.properties || []);\n};\nweb3._extend.formatters = formatters;\nweb3._extend.utils = utils;\nweb3._extend.Method = require('./web3/method');\nweb3._extend.Property = require('./web3/property');\n\n\n/// setups all api methods\nsetupProperties(web3, web3Properties);\nsetupMethods(web3.net, net.methods);\nsetupProperties(web3.net, net.properties);\nsetupMethods(web3.eth, eth.methods);\nsetupProperties(web3.eth, eth.properties);\nsetupMethods(web3.db, db.methods);\nsetupMethods(web3.shh, shh.methods);\n\nmodule.exports = web3;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file utils.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\n/**\n * Utils\n * \n * @module utils\n */\n\n/**\n * Utility functions\n * \n * @class [utils] utils\n * @constructor\n */\n\nvar BigNumber = require('bignumber.js');\n\nvar unitMap = {\n 'wei': '1',\n 'kwei': '1000',\n 'ada': '1000',\n 'femtoether': '1000',\n 'mwei': '1000000',\n 'babbage': '1000000',\n 'picoether': '1000000',\n 'gwei': '1000000000',\n 'shannon': '1000000000',\n 'nanoether': '1000000000',\n 'nano': '1000000000',\n 'szabo': '1000000000000',\n 'microether': '1000000000000',\n 'micro': '1000000000000',\n 'finney': '1000000000000000',\n 'milliether': '1000000000000000',\n 'milli': '1000000000000000',\n 'ether': '1000000000000000000',\n 'kether': '1000000000000000000000',\n 'grand': '1000000000000000000000',\n 'einstein': '1000000000000000000000',\n 'mether': '1000000000000000000000000',\n 'gether': '1000000000000000000000000000',\n 'tether': '1000000000000000000000000000000'\n};\n\n/**\n * Should be called to pad string to expected length\n *\n * @method padLeft\n * @param {String} string to be padded\n * @param {Number} characters that result string should have\n * @param {String} sign, by default 0\n * @returns {String} right aligned string\n */\nvar padLeft = function (string, chars, sign) {\n return new Array(chars - string.length + 1).join(sign ? sign : \"0\") + string;\n};\n\n/**\n * Should be called to pad string to expected length\n *\n * @method padRight\n * @param {String} string to be padded\n * @param {Number} characters that result string should have\n * @param {String} sign, by default 0\n * @returns {String} right aligned string\n */\nvar padRight = function (string, chars, sign) {\n return string + (new Array(chars - string.length + 1).join(sign ? sign : \"0\"));\n};\n\n/** \n * Should be called to get sting from it's hex representation\n *\n * @method toAscii\n * @param {String} string in hex\n * @returns {String} ascii string representation of hex value\n */\nvar toAscii = function(hex) {\n// Find termination\n var str = \"\";\n var i = 0, l = hex.length;\n if (hex.substring(0, 2) === '0x') {\n i = 2;\n }\n for (; i < l; i+=2) {\n var code = parseInt(hex.substr(i, 2), 16);\n str += String.fromCharCode(code);\n }\n\n return str;\n};\n \n/**\n * Shold be called to get hex representation (prefixed by 0x) of ascii string \n *\n * @method toHexNative\n * @param {String} string\n * @returns {String} hex representation of input string\n */\nvar toHexNative = function(str) {\n var hex = \"\";\n for(var i = 0; i < str.length; i++) {\n var n = str.charCodeAt(i).toString(16);\n hex += n.length < 2 ? '0' + n : n;\n }\n\n return hex;\n};\n\n/**\n * Shold be called to get hex representation (prefixed by 0x) of ascii string \n *\n * @method fromAscii\n * @param {String} string\n * @param {Number} optional padding\n * @returns {String} hex representation of input string\n */\nvar fromAscii = function(str, pad) {\n pad = pad === undefined ? 0 : pad;\n var hex = toHexNative(str);\n while (hex.length < pad*2)\n hex += \"00\";\n return \"0x\" + hex;\n};\n\n/**\n * Should be used to create full function/event name from json abi\n *\n * @method transformToFullName\n * @param {Object} json-abi\n * @return {String} full fnction/event name\n */\nvar transformToFullName = function (json) {\n if (json.name.indexOf('(') !== -1) {\n return json.name;\n }\n\n var typeName = json.inputs.map(function(i){return i.type; }).join();\n return json.name + '(' + typeName + ')';\n};\n\n/**\n * Should be called to get display name of contract function\n * \n * @method extractDisplayName\n * @param {String} name of function/event\n * @returns {String} display name for function/event eg. multiply(uint256) -> multiply\n */\nvar extractDisplayName = function (name) {\n var length = name.indexOf('('); \n return length !== -1 ? name.substr(0, length) : name;\n};\n\n/// @returns overloaded part of function/event name\nvar extractTypeName = function (name) {\n /// TODO: make it invulnerable\n var length = name.indexOf('(');\n return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)).replace(' ', '') : \"\";\n};\n\n/**\n * Converts value to it's decimal representation in string\n *\n * @method toDecimal\n * @param {String|Number|BigNumber}\n * @return {String}\n */\nvar toDecimal = function (value) {\n return toBigNumber(value).toNumber();\n};\n\n/**\n * Converts value to it's hex representation\n *\n * @method fromDecimal\n * @param {String|Number|BigNumber}\n * @return {String}\n */\nvar fromDecimal = function (value) {\n var number = toBigNumber(value);\n var result = number.toString(16);\n\n return number.lessThan(0) ? '-0x' + result.substr(1) : '0x' + result;\n};\n\n/**\n * Auto converts any given value into it's hex representation.\n *\n * And even stringifys objects before.\n *\n * @method toHex\n * @param {String|Number|BigNumber|Object}\n * @return {String}\n */\nvar toHex = function (val) {\n /*jshint maxcomplexity: 8 */\n\n if (isBoolean(val))\n return fromDecimal(+val);\n\n if (isBigNumber(val))\n return fromDecimal(val);\n\n if (isObject(val))\n return fromAscii(JSON.stringify(val));\n\n // if its a negative number, pass it through fromDecimal\n if (isString(val)) {\n if (val.indexOf('-0x') === 0)\n return fromDecimal(val);\n else if (!isFinite(val))\n return fromAscii(val);\n else if(val.indexOf('0x') === 0)\n return val;\n }\n\n return fromDecimal(val);\n};\n\n/**\n * Returns value of unit in Wei\n *\n * @method getValueOfUnit\n * @param {String} unit the unit to convert to, default ether\n * @returns {BigNumber} value of the unit (in Wei)\n * @throws error if the unit is not correct:w\n */\nvar getValueOfUnit = function (unit) {\n unit = unit ? unit.toLowerCase() : 'ether';\n var unitValue = unitMap[unit];\n if (unitValue === undefined) {\n throw new Error('This unit doesn\\'t exists, please use the one of the following units' + JSON.stringify(unitMap, null, 2));\n }\n return new BigNumber(unitValue, 10);\n};\n\n/**\n * Takes a number of wei and converts it to any other ether unit.\n *\n * Possible units are:\n * SI Short SI Full Effigy Other\n * - kwei femtoether ada\n * - mwei picoether babbage\n * - gwei nanoether shannon nano\n * - -- microether szabo micro\n * - -- milliether finney milli\n * - ether -- --\n * - kether einstein grand \n * - mether\n * - gether\n * - tether\n *\n * @method fromWei\n * @param {Number|String} number can be a number, number string or a HEX of a decimal\n * @param {String} unit the unit to convert to, default ether\n * @return {String|Object} When given a BigNumber object it returns one as well, otherwise a number\n*/\nvar fromWei = function(number, unit) {\n var returnValue = toBigNumber(number).dividedBy(getValueOfUnit(unit));\n\n return isBigNumber(number) ? returnValue : returnValue.toString(10); \n};\n\n/**\n * Takes a number of a unit and converts it to wei.\n *\n * Possible units are:\n * SI Short SI Full Effigy Other\n * - kwei femtoether ada\n * - mwei picoether babbage \n * - gwei nanoether shannon nano\n * - -- microether szabo micro\n * - -- milliether finney milli\n * - ether -- --\n * - kether einstein grand \n * - mether\n * - gether\n * - tether\n *\n * @method toWei\n * @param {Number|String|BigNumber} number can be a number, number string or a HEX of a decimal\n * @param {String} unit the unit to convert from, default ether\n * @return {String|Object} When given a BigNumber object it returns one as well, otherwise a number\n*/\nvar toWei = function(number, unit) {\n var returnValue = toBigNumber(number).times(getValueOfUnit(unit));\n\n return isBigNumber(number) ? returnValue : returnValue.toString(10); \n};\n\n/**\n * Takes an input and transforms it into an bignumber\n *\n * @method toBigNumber\n * @param {Number|String|BigNumber} a number, string, HEX string or BigNumber\n * @return {BigNumber} BigNumber\n*/\nvar toBigNumber = function(number) {\n /*jshint maxcomplexity:5 */\n number = number || 0;\n if (isBigNumber(number))\n return number;\n\n if (isString(number) && (number.indexOf('0x') === 0 || number.indexOf('-0x') === 0)) {\n return new BigNumber(number.replace('0x',''), 16);\n }\n \n return new BigNumber(number.toString(10), 10);\n};\n\n/**\n * Takes and input transforms it into bignumber and if it is negative value, into two's complement\n *\n * @method toTwosComplement\n * @param {Number|String|BigNumber}\n * @return {BigNumber}\n */\nvar toTwosComplement = function (number) {\n var bigNumber = toBigNumber(number);\n if (bigNumber.lessThan(0)) {\n return new BigNumber(\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\", 16).plus(bigNumber).plus(1);\n }\n return bigNumber;\n};\n\n/**\n * Checks if the given string is strictly an address\n *\n * @method isStrictAddress\n * @param {String} address the given HEX adress\n * @return {Boolean}\n*/\nvar isStrictAddress = function (address) {\n return /^0x[0-9a-f]{40}$/.test(address);\n};\n\n/**\n * Checks if the given string is an address\n *\n * @method isAddress\n * @param {String} address the given HEX adress\n * @return {Boolean}\n*/\nvar isAddress = function (address) {\n return /^(0x)?[0-9a-f]{40}$/.test(address);\n};\n\n/**\n * Transforms given string to valid 20 bytes-length addres with 0x prefix\n *\n * @method toAddress\n * @param {String} address\n * @return {String} formatted address\n */\nvar toAddress = function (address) {\n if (isStrictAddress(address)) {\n return address;\n }\n \n if (/^[0-9a-f]{40}$/.test(address)) {\n return '0x' + address;\n }\n\n return '0x' + padLeft(toHex(address).substr(2), 40);\n};\n\n\n/**\n * Returns true if object is BigNumber, otherwise false\n *\n * @method isBigNumber\n * @param {Object}\n * @return {Boolean} \n */\nvar isBigNumber = function (object) {\n return object instanceof BigNumber ||\n (object && object.constructor && object.constructor.name === 'BigNumber');\n};\n\n/**\n * Returns true if object is string, otherwise false\n * \n * @method isString\n * @param {Object}\n * @return {Boolean}\n */\nvar isString = function (object) {\n return typeof object === 'string' ||\n (object && object.constructor && object.constructor.name === 'String');\n};\n\n/**\n * Returns true if object is function, otherwise false\n *\n * @method isFunction\n * @param {Object}\n * @return {Boolean}\n */\nvar isFunction = function (object) {\n return typeof object === 'function';\n};\n\n/**\n * Returns true if object is Objet, otherwise false\n *\n * @method isObject\n * @param {Object}\n * @return {Boolean}\n */\nvar isObject = function (object) {\n return typeof object === 'object';\n};\n\n/**\n * Returns true if object is boolean, otherwise false\n *\n * @method isBoolean\n * @param {Object}\n * @return {Boolean}\n */\nvar isBoolean = function (object) {\n return typeof object === 'boolean';\n};\n\n/**\n * Returns true if object is array, otherwise false\n *\n * @method isArray\n * @param {Object}\n * @return {Boolean}\n */\nvar isArray = function (object) {\n return object instanceof Array; \n};\n\n/**\n * Returns true if given string is valid json object\n * \n * @method isJson\n * @param {String}\n * @return {Boolean}\n */\nvar isJson = function (str) {\n try {\n return !!JSON.parse(str);\n } catch (e) {\n return false;\n }\n};\n\n/**\n * This method should be called to check if string is valid ethereum IBAN number\n * Supports direct and indirect IBANs\n *\n * @method isIBAN\n * @param {String}\n * @return {Boolean}\n */\nvar isIBAN = function (iban) {\n return /^XE[0-9]{2}(ETH[0-9A-Z]{13}|[0-9A-Z]{30})$/.test(iban);\n};\n\nmodule.exports = {\n padLeft: padLeft,\n padRight: padRight,\n toHex: toHex,\n toDecimal: toDecimal,\n fromDecimal: fromDecimal,\n toAscii: toAscii,\n fromAscii: fromAscii,\n transformToFullName: transformToFullName,\n extractDisplayName: extractDisplayName,\n extractTypeName: extractTypeName,\n toWei: toWei,\n fromWei: fromWei,\n toBigNumber: toBigNumber,\n toTwosComplement: toTwosComplement,\n toAddress: toAddress,\n isBigNumber: isBigNumber,\n isStrictAddress: isStrictAddress,\n isAddress: isAddress,\n isFunction: isFunction,\n isString: isString,\n isObject: isObject,\n isBoolean: isBoolean,\n isArray: isArray,\n isJson: isJson,\n isIBAN: isIBAN\n};\n\n", + "module.exports={\n \"version\": \"0.7.1\"\n}\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file web3.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * Gav Wood \n * @date 2014\n */\n\nvar version = require('./version.json');\nvar net = require('./web3/net');\nvar eth = require('./web3/eth');\nvar db = require('./web3/db');\nvar shh = require('./web3/shh');\nvar watches = require('./web3/watches');\nvar Filter = require('./web3/filter');\nvar utils = require('./utils/utils');\nvar formatters = require('./web3/formatters');\nvar RequestManager = require('./web3/requestmanager');\nvar c = require('./utils/config');\nvar Property = require('./web3/property');\nvar Batch = require('./web3/batch');\nvar sha3 = require('./utils/sha3');\n\nvar web3Properties = [\n new Property({\n name: 'version.client',\n getter: 'web3_clientVersion'\n }),\n new Property({\n name: 'version.network',\n getter: 'net_version',\n inputFormatter: utils.toDecimal\n }),\n new Property({\n name: 'version.ethereum',\n getter: 'eth_protocolVersion',\n inputFormatter: utils.toDecimal\n }),\n new Property({\n name: 'version.whisper',\n getter: 'shh_version',\n inputFormatter: utils.toDecimal\n })\n];\n\n/// creates methods in a given object based on method description on input\n/// setups api calls for these methods\nvar setupMethods = function (obj, methods) {\n methods.forEach(function (method) {\n method.attachToObject(obj);\n });\n};\n\n/// creates properties in a given object based on properties description on input\n/// setups api calls for these properties\nvar setupProperties = function (obj, properties) {\n properties.forEach(function (property) {\n property.attachToObject(obj);\n });\n};\n\n/// setups web3 object, and it's in-browser executed methods\nvar web3 = {};\nweb3.providers = {};\nweb3.currentProvider = null;\nweb3.version = {};\nweb3.version.api = version.version;\nweb3.eth = {};\n\n/*jshint maxparams:4 */\nweb3.eth.filter = function (fil, callback) {\n return new Filter(fil, watches.eth(), formatters.outputLogFormatter, callback);\n};\n/*jshint maxparams:3 */\n\nweb3.shh = {};\nweb3.shh.filter = function (fil, callback) {\n return new Filter(fil, watches.shh(), formatters.outputPostFormatter, callback);\n};\nweb3.net = {};\nweb3.db = {};\nweb3.setProvider = function (provider) {\n this.currentProvider = provider;\n RequestManager.getInstance().setProvider(provider);\n};\nweb3.reset = function () {\n RequestManager.getInstance().reset();\n c.defaultBlock = 'latest';\n c.defaultAccount = undefined;\n};\nweb3.toHex = utils.toHex;\nweb3.toAscii = utils.toAscii;\nweb3.fromAscii = utils.fromAscii;\nweb3.toDecimal = utils.toDecimal;\nweb3.fromDecimal = utils.fromDecimal;\nweb3.toBigNumber = utils.toBigNumber;\nweb3.toWei = utils.toWei;\nweb3.fromWei = utils.fromWei;\nweb3.isAddress = utils.isAddress;\nweb3.isIBAN = utils.isIBAN;\nweb3.sha3 = sha3;\nweb3.createBatch = function () {\n return new Batch();\n};\n\n// ADD defaultblock\nObject.defineProperty(web3.eth, 'defaultBlock', {\n get: function () {\n return c.defaultBlock;\n },\n set: function (val) {\n c.defaultBlock = val;\n return val;\n }\n});\n\nObject.defineProperty(web3.eth, 'defaultAccount', {\n get: function () {\n return c.defaultAccount;\n },\n set: function (val) {\n c.defaultAccount = val;\n return val;\n }\n});\n\n\n// EXTEND\nweb3._extend = function(extension){\n /*jshint maxcomplexity: 6 */\n\n if(extension.property && !web3[extension.property])\n web3[extension.property] = {};\n\n setupMethods(web3[extension.property] || web3, extension.methods || []);\n setupProperties(web3[extension.property] || web3, extension.properties || []);\n};\nweb3._extend.formatters = formatters;\nweb3._extend.utils = utils;\nweb3._extend.Method = require('./web3/method');\nweb3._extend.Property = require('./web3/property');\n\n\n/// setups all api methods\nsetupProperties(web3, web3Properties);\nsetupMethods(web3.net, net.methods);\nsetupProperties(web3.net, net.properties);\nsetupMethods(web3.eth, eth.methods);\nsetupProperties(web3.eth, eth.properties);\nsetupMethods(web3.db, db.methods);\nsetupMethods(web3.shh, shh.methods);\n\nmodule.exports = web3;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file allevents.js\n * @author Marek Kotewicz \n * @date 2014\n */\n\nvar sha3 = require('../utils/sha3');\nvar SolidityEvent = require('./event');\nvar formatters = require('./formatters');\nvar utils = require('../utils/utils');\nvar Filter = require('./filter');\nvar watches = require('./watches');\n\nvar AllSolidityEvents = function (json, address) {\n this._json = json;\n this._address = address;\n};\n\nAllSolidityEvents.prototype.encode = function (options) {\n options = options || {};\n var result = {};\n\n ['fromBlock', 'toBlock'].filter(function (f) {\n return options[f] !== undefined;\n }).forEach(function (f) {\n result[f] = formatters.inputBlockNumberFormatter(options[f]);\n });\n\n result.topics = [null, null, null, null, null]; // match all topics\n result.address = this._address;\n\n return result;\n};\n\nAllSolidityEvents.prototype.decode = function (data) {\n data.data = data.data || '';\n data.topics = data.topics || [];\n\n var eventTopic = data.topics[0].slice(2);\n var match = this._json.filter(function (j) {\n return eventTopic === sha3(utils.transformToFullName(j));\n })[0];\n\n if (!match) { // cannot find matching event?\n console.warn('cannot find event for log');\n return data;\n }\n\n var event = new SolidityEvent(match, this._address);\n return event.decode(data);\n};\n\nAllSolidityEvents.prototype.execute = function (options, callback) {\n var o = this.encode(options);\n var formatter = this.decode.bind(this);\n return new Filter(o, watches.eth(), formatter, callback);\n};\n\nAllSolidityEvents.prototype.attachToContract = function (contract) {\n var execute = this.execute.bind(this);\n contract.allEvents = execute;\n};\n\nmodule.exports = AllSolidityEvents;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file batch.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar RequestManager = require('./requestmanager');\n\nvar Batch = function () {\n this.requests = [];\n};\n\n/**\n * Should be called to add create new request to batch request\n *\n * @method add\n * @param {Object} jsonrpc requet object\n */\nBatch.prototype.add = function (request) {\n this.requests.push(request);\n};\n\n/**\n * Should be called to execute batch request\n *\n * @method execute\n */\nBatch.prototype.execute = function () {\n var requests = this.requests;\n RequestManager.getInstance().sendBatch(requests, function (err, results) {\n results = results || [];\n requests.map(function (request, index) {\n return results[index] || {};\n }).map(function (result, index) {\n return requests[index].format ? requests[index].format(result.result) : result.result;\n }).forEach(function (result, index) {\n if (requests[index].callback) {\n requests[index].callback(err, result);\n }\n });\n }); \n};\n\nmodule.exports = Batch;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file contract.js\n * @author Marek Kotewicz \n * @date 2014\n */\n\nvar web3 = require('../web3'); \nvar utils = require('../utils/utils');\nvar coder = require('../solidity/coder');\nvar SolidityEvent = require('./event');\nvar SolidityFunction = require('./function');\n\n/**\n * Should be called to encode constructor params\n *\n * @method encodeConstructorParams\n * @param {Array} abi\n * @param {Array} constructor params\n */\nvar encodeConstructorParams = function (abi, params) {\n return abi.filter(function (json) {\n return json.type === 'constructor' && json.inputs.length === params.length;\n }).map(function (json) {\n return json.inputs.map(function (input) {\n return input.type;\n });\n }).map(function (types) {\n return coder.encodeParams(types, params);\n })[0] || '';\n};\n\n/**\n * Should be called to add functions to contract object\n *\n * @method addFunctionsToContract\n * @param {Contract} contract\n * @param {Array} abi\n */\nvar addFunctionsToContract = function (contract, abi) {\n abi.filter(function (json) {\n return json.type === 'function';\n }).map(function (json) {\n return new SolidityFunction(json, contract.address);\n }).forEach(function (f) {\n f.attachToContract(contract);\n });\n};\n\n/**\n * Should be called to add events to contract object\n *\n * @method addEventsToContract\n * @param {Contract} contract\n * @param {Array} abi\n */\nvar addEventsToContract = function (contract, abi) {\n abi.filter(function (json) {\n return json.type === 'event';\n }).map(function (json) {\n return new SolidityEvent(json, contract.address);\n }).forEach(function (e) {\n e.attachToContract(contract);\n });\n};\n\n/**\n * Should be called to create new ContractFactory\n *\n * @method contract\n * @param {Array} abi\n * @returns {ContractFactory} new contract factory\n */\nvar contract = function (abi) {\n return new ContractFactory(abi);\n};\n\n/**\n * Should be called to create new ContractFactory instance\n *\n * @method ContractFactory\n * @param {Array} abi\n */\nvar ContractFactory = function (abi) {\n this.abi = abi;\n};\n\n/**\n * Should be called to create new contract on a blockchain\n * \n * @method new\n * @param {Any} contract constructor param1 (optional)\n * @param {Any} contract constructor param2 (optional)\n * @param {Object} contract transaction object (required)\n * @param {Function} callback\n * @returns {Contract} returns contract if no callback was passed,\n * otherwise calls callback function (err, contract)\n */\nContractFactory.prototype.new = function () {\n // parse arguments\n var options = {}; // required!\n var callback;\n\n var args = Array.prototype.slice.call(arguments);\n if (utils.isFunction(args[args.length - 1])) {\n callback = args.pop();\n }\n\n var last = args[args.length - 1];\n if (utils.isObject(last) && !utils.isArray(last)) {\n options = args.pop();\n }\n\n // throw an error if there are no options\n\n var bytes = encodeConstructorParams(this.abi, args);\n options.data += bytes;\n\n if (!callback) {\n var address = web3.eth.sendTransaction(options);\n return this.at(address);\n }\n \n var self = this;\n web3.eth.sendTransaction(options, function (err, address) {\n if (err) {\n callback(err);\n }\n self.at(address, callback); \n }); \n};\n\n/**\n * Should be called to get access to existing contract on a blockchain\n *\n * @method at\n * @param {Address} contract address (required)\n * @param {Function} callback {optional)\n * @returns {Contract} returns contract if no callback was passed,\n * otherwise calls callback function (err, contract)\n */\nContractFactory.prototype.at = function (address, callback) {\n // TODO: address is required\n \n if (callback) {\n callback(null, new Contract(this.abi, address));\n } \n return new Contract(this.abi, address);\n};\n\n/**\n * Should be called to create new contract instance\n *\n * @method Contract\n * @param {Array} abi\n * @param {Address} contract address\n */\nvar Contract = function (abi, address) {\n this.address = address;\n addFunctionsToContract(this, abi);\n addEventsToContract(this, abi);\n};\n\nmodule.exports = contract;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file contract.js\n * @author Marek Kotewicz \n * @date 2014\n */\n\nvar web3 = require('../web3'); \nvar utils = require('../utils/utils');\nvar coder = require('../solidity/coder');\nvar SolidityEvent = require('./event');\nvar SolidityFunction = require('./function');\nvar AllEvents = require('./allevents');\n\n/**\n * Should be called to encode constructor params\n *\n * @method encodeConstructorParams\n * @param {Array} abi\n * @param {Array} constructor params\n */\nvar encodeConstructorParams = function (abi, params) {\n return abi.filter(function (json) {\n return json.type === 'constructor' && json.inputs.length === params.length;\n }).map(function (json) {\n return json.inputs.map(function (input) {\n return input.type;\n });\n }).map(function (types) {\n return coder.encodeParams(types, params);\n })[0] || '';\n};\n\n/**\n * Should be called to add functions to contract object\n *\n * @method addFunctionsToContract\n * @param {Contract} contract\n * @param {Array} abi\n */\nvar addFunctionsToContract = function (contract, abi) {\n abi.filter(function (json) {\n return json.type === 'function';\n }).map(function (json) {\n return new SolidityFunction(json, contract.address);\n }).forEach(function (f) {\n f.attachToContract(contract);\n });\n};\n\n/**\n * Should be called to add events to contract object\n *\n * @method addEventsToContract\n * @param {Contract} contract\n * @param {Array} abi\n */\nvar addEventsToContract = function (contract, abi) {\n var events = abi.filter(function (json) {\n return json.type === 'event';\n });\n\n var All = new AllEvents(events, contract.address);\n All.attachToContract(contract);\n \n events.map(function (json) {\n return new SolidityEvent(json, contract.address);\n }).forEach(function (e) {\n e.attachToContract(contract);\n });\n};\n\n/**\n * Should be called to create new ContractFactory\n *\n * @method contract\n * @param {Array} abi\n * @returns {ContractFactory} new contract factory\n */\nvar contract = function (abi) {\n return new ContractFactory(abi);\n};\n\n/**\n * Should be called to create new ContractFactory instance\n *\n * @method ContractFactory\n * @param {Array} abi\n */\nvar ContractFactory = function (abi) {\n this.abi = abi;\n};\n\n/**\n * Should be called to create new contract on a blockchain\n * \n * @method new\n * @param {Any} contract constructor param1 (optional)\n * @param {Any} contract constructor param2 (optional)\n * @param {Object} contract transaction object (required)\n * @param {Function} callback\n * @returns {Contract} returns contract if no callback was passed,\n * otherwise calls callback function (err, contract)\n */\nContractFactory.prototype.new = function () {\n // parse arguments\n var options = {}; // required!\n var callback;\n\n var args = Array.prototype.slice.call(arguments);\n if (utils.isFunction(args[args.length - 1])) {\n callback = args.pop();\n }\n\n var last = args[args.length - 1];\n if (utils.isObject(last) && !utils.isArray(last)) {\n options = args.pop();\n }\n\n // throw an error if there are no options\n\n var bytes = encodeConstructorParams(this.abi, args);\n options.data += bytes;\n\n if (!callback) {\n var address = web3.eth.sendTransaction(options);\n return this.at(address);\n }\n \n var self = this;\n web3.eth.sendTransaction(options, function (err, address) {\n if (err) {\n callback(err);\n }\n self.at(address, callback); \n }); \n};\n\n/**\n * Should be called to get access to existing contract on a blockchain\n *\n * @method at\n * @param {Address} contract address (required)\n * @param {Function} callback {optional)\n * @returns {Contract} returns contract if no callback was passed,\n * otherwise calls callback function (err, contract)\n */\nContractFactory.prototype.at = function (address, callback) {\n // TODO: address is required\n \n if (callback) {\n callback(null, new Contract(this.abi, address));\n } \n return new Contract(this.abi, address);\n};\n\n/**\n * Should be called to create new contract instance\n *\n * @method Contract\n * @param {Array} abi\n * @param {Address} contract address\n */\nvar Contract = function (abi, address) {\n this.address = address;\n addFunctionsToContract(this, abi);\n addEventsToContract(this, abi);\n};\n\nmodule.exports = contract;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file db.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar Method = require('./method');\n\nvar putString = new Method({\n name: 'putString',\n call: 'db_putString',\n params: 3\n});\n\n\nvar getString = new Method({\n name: 'getString',\n call: 'db_getString',\n params: 2\n});\n\nvar putHex = new Method({\n name: 'putHex',\n call: 'db_putHex',\n params: 3\n});\n\nvar getHex = new Method({\n name: 'getHex',\n call: 'db_getHex',\n params: 2\n});\n\nvar methods = [\n putString, getString, putHex, getHex\n];\n\nmodule.exports = {\n methods: methods\n};\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file errors.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nmodule.exports = {\n InvalidNumberOfParams: function () {\n return new Error('Invalid number of input parameters');\n },\n InvalidConnection: function (host){\n return new Error('CONNECTION ERROR: Couldn\\'t connect to node '+ host +', is it running?');\n },\n InvalidProvider: function () {\n return new Error('Providor not set or invalid');\n },\n InvalidResponse: function (result){\n var message = !!result && !!result.error && !!result.error.message ? result.error.message : 'Invalid JSON RPC response';\n return new Error(message);\n }\n};\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/**\n * @file eth.js\n * @author Marek Kotewicz \n * @author Fabian Vogelsteller \n * @date 2015\n */\n\n/**\n * Web3\n *\n * @module web3\n */\n\n/**\n * Eth methods and properties\n *\n * An example method object can look as follows:\n *\n * {\n * name: 'getBlock',\n * call: blockCall,\n * params: 2,\n * outputFormatter: formatters.outputBlockFormatter,\n * inputFormatter: [ // can be a formatter funciton or an array of functions. Where each item in the array will be used for one parameter\n * utils.toHex, // formats paramter 1\n * function(param){ return !!param; } // formats paramter 2\n * ]\n * },\n *\n * @class [web3] eth\n * @constructor\n */\n\n\"use strict\";\n\nvar formatters = require('./formatters');\nvar utils = require('../utils/utils');\nvar Method = require('./method');\nvar Property = require('./property');\n\nvar blockCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? \"eth_getBlockByHash\" : \"eth_getBlockByNumber\";\n};\n\nvar transactionFromBlockCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getTransactionByBlockHashAndIndex' : 'eth_getTransactionByBlockNumberAndIndex';\n};\n\nvar uncleCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getUncleByBlockHashAndIndex' : 'eth_getUncleByBlockNumberAndIndex';\n};\n\nvar getBlockTransactionCountCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getBlockTransactionCountByHash' : 'eth_getBlockTransactionCountByNumber';\n};\n\nvar uncleCountCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getUncleCountByBlockHash' : 'eth_getUncleCountByBlockNumber';\n};\n\n/// @returns an array of objects describing web3.eth api methods\n\nvar getBalance = new Method({\n name: 'getBalance',\n call: 'eth_getBalance',\n params: 2,\n inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter],\n outputFormatter: formatters.outputBigNumberFormatter\n});\n\nvar getStorageAt = new Method({\n name: 'getStorageAt',\n call: 'eth_getStorageAt',\n params: 3,\n inputFormatter: [null, utils.toHex, formatters.inputDefaultBlockNumberFormatter]\n});\n\nvar getCode = new Method({\n name: 'getCode',\n call: 'eth_getCode',\n params: 2,\n inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter]\n});\n\nvar getBlock = new Method({\n name: 'getBlock',\n call: blockCall,\n params: 2,\n inputFormatter: [formatters.inputBlockNumberFormatter, function (val) { return !!val; }],\n outputFormatter: formatters.outputBlockFormatter\n});\n\nvar getUncle = new Method({\n name: 'getUncle',\n call: uncleCall,\n params: 2,\n inputFormatter: [formatters.inputBlockNumberFormatter, utils.toHex],\n outputFormatter: formatters.outputBlockFormatter,\n\n});\n\nvar getCompilers = new Method({\n name: 'getCompilers',\n call: 'eth_getCompilers',\n params: 0\n});\n\nvar getBlockTransactionCount = new Method({\n name: 'getBlockTransactionCount',\n call: getBlockTransactionCountCall,\n params: 1,\n inputFormatter: [formatters.inputBlockNumberFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar getBlockUncleCount = new Method({\n name: 'getBlockUncleCount',\n call: uncleCountCall,\n params: 1,\n inputFormatter: [formatters.inputBlockNumberFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar getTransaction = new Method({\n name: 'getTransaction',\n call: 'eth_getTransactionByHash',\n params: 1,\n outputFormatter: formatters.outputTransactionFormatter\n});\n\nvar getTransactionFromBlock = new Method({\n name: 'getTransactionFromBlock',\n call: transactionFromBlockCall,\n params: 2,\n inputFormatter: [formatters.inputBlockNumberFormatter, utils.toHex],\n outputFormatter: formatters.outputTransactionFormatter\n});\n\nvar getTransactionCount = new Method({\n name: 'getTransactionCount',\n call: 'eth_getTransactionCount',\n params: 2,\n inputFormatter: [null, formatters.inputDefaultBlockNumberFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar sendRawTransaction = new Method({\n name: 'sendRawTransaction',\n call: 'eth_sendRawTransaction',\n params: 1,\n inputFormatter: []\n});\n\nvar sendTransaction = new Method({\n name: 'sendTransaction',\n call: 'eth_sendTransaction',\n params: 1,\n inputFormatter: [formatters.inputTransactionFormatter]\n});\n\nvar call = new Method({\n name: 'call',\n call: 'eth_call',\n params: 2,\n inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter]\n});\n\nvar estimateGas = new Method({\n name: 'estimateGas',\n call: 'eth_estimateGas',\n params: 1,\n inputFormatter: [formatters.inputTransactionFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar compileSolidity = new Method({\n name: 'compile.solidity',\n call: 'eth_compileSolidity',\n params: 1\n});\n\nvar compileLLL = new Method({\n name: 'compile.lll',\n call: 'eth_compileLLL',\n params: 1\n});\n\nvar compileSerpent = new Method({\n name: 'compile.serpent',\n call: 'eth_compileSerpent',\n params: 1\n});\n\nvar submitWork = new Method({\n name: 'submitWork',\n call: 'eth_submitWork',\n params: 3\n});\n\nvar getWork = new Method({\n name: 'getWork',\n call: 'eth_getWork',\n params: 0\n});\n\nvar methods = [\n getBalance,\n getStorageAt,\n getCode,\n getBlock,\n getUncle,\n getCompilers,\n getBlockTransactionCount,\n getBlockUncleCount,\n getTransaction,\n getTransactionFromBlock,\n getTransactionCount,\n call,\n estimateGas,\n sendRawTransaction,\n sendTransaction,\n compileSolidity,\n compileLLL,\n compileSerpent,\n submitWork,\n getWork\n];\n\n/// @returns an array of objects describing web3.eth api properties\n\n\n\nvar properties = [\n new Property({\n name: 'coinbase',\n getter: 'eth_coinbase'\n }),\n new Property({\n name: 'mining',\n getter: 'eth_mining'\n }),\n new Property({\n name: 'hashrate',\n getter: 'eth_hashrate',\n outputFormatter: utils.toDecimal\n }),\n new Property({\n name: 'gasPrice',\n getter: 'eth_gasPrice',\n outputFormatter: formatters.outputBigNumberFormatter\n }),\n new Property({\n name: 'accounts',\n getter: 'eth_accounts'\n }),\n new Property({\n name: 'blockNumber',\n getter: 'eth_blockNumber',\n outputFormatter: utils.toDecimal\n })\n];\n\nmodule.exports = {\n methods: methods,\n properties: properties\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file event.js\n * @author Marek Kotewicz \n * @date 2014\n */\n\nvar utils = require('../utils/utils');\nvar coder = require('../solidity/coder');\nvar web3 = require('../web3');\nvar formatters = require('./formatters');\nvar sha3 = require('../utils/sha3');\n\n/**\n * This prototype should be used to create event filters\n */\nvar SolidityEvent = function (json, address) {\n this._params = json.inputs;\n this._name = utils.transformToFullName(json);\n this._address = address;\n this._anonymous = json.anonymous;\n};\n\n/**\n * Should be used to get filtered param types\n *\n * @method types\n * @param {Bool} decide if returned typed should be indexed\n * @return {Array} array of types\n */\nSolidityEvent.prototype.types = function (indexed) {\n return this._params.filter(function (i) {\n return i.indexed === indexed;\n }).map(function (i) {\n return i.type;\n });\n};\n\n/**\n * Should be used to get event display name\n *\n * @method displayName\n * @return {String} event display name\n */\nSolidityEvent.prototype.displayName = function () {\n return utils.extractDisplayName(this._name);\n};\n\n/**\n * Should be used to get event type name\n *\n * @method typeName\n * @return {String} event type name\n */\nSolidityEvent.prototype.typeName = function () {\n return utils.extractTypeName(this._name);\n};\n\n/**\n * Should be used to get event signature\n *\n * @method signature\n * @return {String} event signature\n */\nSolidityEvent.prototype.signature = function () {\n return sha3(this._name);\n};\n\n/**\n * Should be used to encode indexed params and options to one final object\n * \n * @method encode\n * @param {Object} indexed\n * @param {Object} options\n * @return {Object} everything combined together and encoded\n */\nSolidityEvent.prototype.encode = function (indexed, options) {\n indexed = indexed || {};\n options = options || {};\n var result = {};\n\n ['fromBlock', 'toBlock'].filter(function (f) {\n return options[f] !== undefined;\n }).forEach(function (f) {\n result[f] = formatters.inputBlockNumberFormatter(options[f]);\n });\n\n result.topics = [];\n\n if (!this._anonymous) {\n result.address = this._address;\n result.topics.push('0x' + this.signature());\n }\n\n var indexedTopics = this._params.filter(function (i) {\n return i.indexed === true;\n }).map(function (i) {\n var value = indexed[i.name];\n if (value === undefined || value === null) {\n return null;\n }\n \n if (utils.isArray(value)) {\n return value.map(function (v) {\n return '0x' + coder.encodeParam(i.type, v);\n });\n }\n return '0x' + coder.encodeParam(i.type, value);\n });\n\n result.topics = result.topics.concat(indexedTopics);\n\n return result;\n};\n\n/**\n * Should be used to decode indexed params and options\n *\n * @method decode\n * @param {Object} data\n * @return {Object} result object with decoded indexed && not indexed params\n */\nSolidityEvent.prototype.decode = function (data) {\n \n data.data = data.data || '';\n data.topics = data.topics || [];\n\n var argTopics = this._anonymous ? data.topics : data.topics.slice(1);\n var indexedData = argTopics.map(function (topics) { return topics.slice(2); }).join(\"\");\n var indexedParams = coder.decodeParams(this.types(true), indexedData); \n\n var notIndexedData = data.data.slice(2);\n var notIndexedParams = coder.decodeParams(this.types(false), notIndexedData);\n \n var result = formatters.outputLogFormatter(data);\n result.event = this.displayName();\n result.address = data.address;\n\n result.args = this._params.reduce(function (acc, current) {\n acc[current.name] = current.indexed ? indexedParams.shift() : notIndexedParams.shift();\n return acc;\n }, {});\n\n delete result.data;\n delete result.topics;\n\n return result;\n};\n\n/**\n * Should be used to create new filter object from event\n *\n * @method execute\n * @param {Object} indexed\n * @param {Object} options\n * @return {Object} filter object\n */\nSolidityEvent.prototype.execute = function (indexed, options) {\n var o = this.encode(indexed, options);\n var formatter = this.decode.bind(this);\n return web3.eth.filter(o, undefined, undefined, formatter);\n};\n\n/**\n * Should be used to attach event to contract object\n *\n * @method attachToContract\n * @param {Contract}\n */\nSolidityEvent.prototype.attachToContract = function (contract) {\n var execute = this.execute.bind(this);\n var displayName = this.displayName();\n if (!contract[displayName]) {\n contract[displayName] = execute;\n }\n contract[displayName][this.typeName()] = this.execute.bind(this, contract);\n};\n\nmodule.exports = SolidityEvent;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file filter.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * Gav Wood \n * @date 2014\n */\n\nvar RequestManager = require('./requestmanager');\nvar formatters = require('./formatters');\nvar utils = require('../utils/utils');\n\n/**\n* Converts a given topic to a hex string, but also allows null values.\n*\n* @param {Mixed} value\n* @return {String}\n*/\nvar toTopic = function(value){\n\n if(value === null || typeof value === 'undefined')\n return null;\n\n value = String(value);\n\n if(value.indexOf('0x') === 0)\n return value;\n else\n return utils.fromAscii(value);\n};\n\n/// This method should be called on options object, to verify deprecated properties && lazy load dynamic ones\n/// @param should be string or object\n/// @returns options string or object\nvar getOptions = function (options) {\n\n if (utils.isString(options)) {\n return options;\n } \n\n options = options || {};\n\n // make sure topics, get converted to hex\n options.topics = options.topics || [];\n options.topics = options.topics.map(function(topic){\n return (utils.isArray(topic)) ? topic.map(toTopic) : toTopic(topic);\n });\n\n // lazy load\n return {\n topics: options.topics,\n to: options.to,\n address: options.address,\n fromBlock: formatters.inputBlockNumberFormatter(options.fromBlock),\n toBlock: formatters.inputBlockNumberFormatter(options.toBlock) \n }; \n};\n\n/**\nAdds the callback and sets up the methods, to iterate over the results.\n\n@method getLogsAtStart\n@param {Object} self\n@param {funciton} \n*/\nvar getLogsAtStart = function(self, callback){\n // call getFilterLogs for the first watch callback start\n if (!utils.isString(self.options)) {\n self.get(function (err, messages) {\n // don't send all the responses to all the watches again... just to self one\n if (err) {\n callback(err);\n }\n\n messages.forEach(function (message) {\n callback(null, message);\n });\n });\n }\n};\n\n/**\nAdds the callback and sets up the methods, to iterate over the results.\n\n@method pollFilter\n@param {Object} self\n*/\nvar pollFilter = function(self) {\n\n var onMessage = function (error, messages) {\n if (error) {\n return self.callbacks.forEach(function (callback) {\n callback(error);\n });\n }\n\n messages.forEach(function (message) {\n message = self.formatter ? self.formatter(message) : message;\n self.callbacks.forEach(function (callback) {\n callback(null, message);\n });\n });\n };\n\n RequestManager.getInstance().startPolling({\n method: self.implementation.poll.call,\n params: [self.filterId],\n }, self.filterId, onMessage, self.stopWatching.bind(self));\n\n};\n\nvar Filter = function (options, methods, formatter) {\n var self = this;\n var implementation = {};\n methods.forEach(function (method) {\n method.attachToObject(implementation);\n });\n this.options = getOptions(options);\n this.implementation = implementation;\n this.callbacks = [];\n this.pollFilters = [];\n this.formatter = formatter;\n this.implementation.newFilter(this.options, function(error, id){\n if(error) {\n self.callbacks.forEach(function(callback){\n callback(error);\n });\n } else {\n self.filterId = id;\n // get filter logs at start\n self.callbacks.forEach(function(callback){\n getLogsAtStart(self, callback);\n });\n pollFilter(self);\n }\n });\n};\n\nFilter.prototype.watch = function (callback) {\n this.callbacks.push(callback);\n\n if(this.filterId) {\n getLogsAtStart(this, callback);\n pollFilter(this);\n }\n\n return this;\n};\n\nFilter.prototype.stopWatching = function () {\n RequestManager.getInstance().stopPolling(this.filterId);\n // remove filter async\n this.implementation.uninstallFilter(this.filterId, function(){});\n this.callbacks = [];\n};\n\nFilter.prototype.get = function (callback) {\n var self = this;\n if (utils.isFunction(callback)) {\n this.implementation.getLogs(this.filterId, function(err, res){\n if (err) {\n callback(err);\n } else {\n callback(null, res.map(function (log) {\n return self.formatter ? self.formatter(log) : log;\n }));\n }\n });\n } else {\n var logs = this.implementation.getLogs(this.filterId);\n return logs.map(function (log) {\n return self.formatter ? self.formatter(log) : log;\n });\n }\n\n return this;\n};\n\nmodule.exports = Filter;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file event.js\n * @author Marek Kotewicz \n * @date 2014\n */\n\nvar utils = require('../utils/utils');\nvar coder = require('../solidity/coder');\nvar formatters = require('./formatters');\nvar sha3 = require('../utils/sha3');\nvar Filter = require('./filter');\nvar watches = require('./watches');\n\n/**\n * This prototype should be used to create event filters\n */\nvar SolidityEvent = function (json, address) {\n this._params = json.inputs;\n this._name = utils.transformToFullName(json);\n this._address = address;\n this._anonymous = json.anonymous;\n};\n\n/**\n * Should be used to get filtered param types\n *\n * @method types\n * @param {Bool} decide if returned typed should be indexed\n * @return {Array} array of types\n */\nSolidityEvent.prototype.types = function (indexed) {\n return this._params.filter(function (i) {\n return i.indexed === indexed;\n }).map(function (i) {\n return i.type;\n });\n};\n\n/**\n * Should be used to get event display name\n *\n * @method displayName\n * @return {String} event display name\n */\nSolidityEvent.prototype.displayName = function () {\n return utils.extractDisplayName(this._name);\n};\n\n/**\n * Should be used to get event type name\n *\n * @method typeName\n * @return {String} event type name\n */\nSolidityEvent.prototype.typeName = function () {\n return utils.extractTypeName(this._name);\n};\n\n/**\n * Should be used to get event signature\n *\n * @method signature\n * @return {String} event signature\n */\nSolidityEvent.prototype.signature = function () {\n return sha3(this._name);\n};\n\n/**\n * Should be used to encode indexed params and options to one final object\n * \n * @method encode\n * @param {Object} indexed\n * @param {Object} options\n * @return {Object} everything combined together and encoded\n */\nSolidityEvent.prototype.encode = function (indexed, options) {\n indexed = indexed || {};\n options = options || {};\n var result = {};\n\n ['fromBlock', 'toBlock'].filter(function (f) {\n return options[f] !== undefined;\n }).forEach(function (f) {\n result[f] = formatters.inputBlockNumberFormatter(options[f]);\n });\n\n result.topics = [];\n\n if (!this._anonymous) {\n result.address = this._address;\n result.topics.push('0x' + this.signature());\n }\n\n var indexedTopics = this._params.filter(function (i) {\n return i.indexed === true;\n }).map(function (i) {\n var value = indexed[i.name];\n if (value === undefined || value === null) {\n return null;\n }\n \n if (utils.isArray(value)) {\n return value.map(function (v) {\n return '0x' + coder.encodeParam(i.type, v);\n });\n }\n return '0x' + coder.encodeParam(i.type, value);\n });\n\n result.topics = result.topics.concat(indexedTopics);\n\n return result;\n};\n\n/**\n * Should be used to decode indexed params and options\n *\n * @method decode\n * @param {Object} data\n * @return {Object} result object with decoded indexed && not indexed params\n */\nSolidityEvent.prototype.decode = function (data) {\n \n data.data = data.data || '';\n data.topics = data.topics || [];\n\n var argTopics = this._anonymous ? data.topics : data.topics.slice(1);\n var indexedData = argTopics.map(function (topics) { return topics.slice(2); }).join(\"\");\n var indexedParams = coder.decodeParams(this.types(true), indexedData); \n\n var notIndexedData = data.data.slice(2);\n var notIndexedParams = coder.decodeParams(this.types(false), notIndexedData);\n \n var result = formatters.outputLogFormatter(data);\n result.event = this.displayName();\n result.address = data.address;\n\n result.args = this._params.reduce(function (acc, current) {\n acc[current.name] = current.indexed ? indexedParams.shift() : notIndexedParams.shift();\n return acc;\n }, {});\n\n delete result.data;\n delete result.topics;\n\n return result;\n};\n\n/**\n * Should be used to create new filter object from event\n *\n * @method execute\n * @param {Object} indexed\n * @param {Object} options\n * @return {Object} filter object\n */\nSolidityEvent.prototype.execute = function (indexed, options, callback) {\n\n if (utils.isFunction(arguments[arguments.length - 1])) {\n callback = arguments[arguments.length - 1];\n if(arguments.length === 2)\n options = null;\n if(arguments.length === 1) {\n options = null;\n indexed = {};\n }\n }\n \n var o = this.encode(indexed, options);\n var formatter = this.decode.bind(this);\n return new Filter(o, watches.eth(), formatter, callback);\n};\n\n/**\n * Should be used to attach event to contract object\n *\n * @method attachToContract\n * @param {Contract}\n */\nSolidityEvent.prototype.attachToContract = function (contract) {\n var execute = this.execute.bind(this);\n var displayName = this.displayName();\n if (!contract[displayName]) {\n contract[displayName] = execute;\n }\n contract[displayName][this.typeName()] = this.execute.bind(this, contract);\n};\n\nmodule.exports = SolidityEvent;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file filter.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * Gav Wood \n * @date 2014\n */\n\nvar RequestManager = require('./requestmanager');\nvar formatters = require('./formatters');\nvar utils = require('../utils/utils');\n\n/**\n* Converts a given topic to a hex string, but also allows null values.\n*\n* @param {Mixed} value\n* @return {String}\n*/\nvar toTopic = function(value){\n\n if(value === null || typeof value === 'undefined')\n return null;\n\n value = String(value);\n\n if(value.indexOf('0x') === 0)\n return value;\n else\n return utils.fromAscii(value);\n};\n\n/// This method should be called on options object, to verify deprecated properties && lazy load dynamic ones\n/// @param should be string or object\n/// @returns options string or object\nvar getOptions = function (options) {\n\n if (utils.isString(options)) {\n return options;\n } \n\n options = options || {};\n\n // make sure topics, get converted to hex\n options.topics = options.topics || [];\n options.topics = options.topics.map(function(topic){\n return (utils.isArray(topic)) ? topic.map(toTopic) : toTopic(topic);\n });\n\n // lazy load\n return {\n topics: options.topics,\n to: options.to,\n address: options.address,\n fromBlock: formatters.inputBlockNumberFormatter(options.fromBlock),\n toBlock: formatters.inputBlockNumberFormatter(options.toBlock) \n }; \n};\n\n/**\nAdds the callback and sets up the methods, to iterate over the results.\n\n@method getLogsAtStart\n@param {Object} self\n@param {funciton} \n*/\nvar getLogsAtStart = function(self, callback){\n // call getFilterLogs for the first watch callback start\n if (!utils.isString(self.options)) {\n self.get(function (err, messages) {\n // don't send all the responses to all the watches again... just to self one\n if (err) {\n callback(err);\n }\n\n messages.forEach(function (message) {\n callback(null, message);\n });\n });\n }\n};\n\n/**\nAdds the callback and sets up the methods, to iterate over the results.\n\n@method pollFilter\n@param {Object} self\n*/\nvar pollFilter = function(self) {\n\n var onMessage = function (error, messages) {\n if (error) {\n return self.callbacks.forEach(function (callback) {\n callback(error);\n });\n }\n\n messages.forEach(function (message) {\n message = self.formatter ? self.formatter(message) : message;\n self.callbacks.forEach(function (callback) {\n callback(null, message);\n });\n });\n };\n\n RequestManager.getInstance().startPolling({\n method: self.implementation.poll.call,\n params: [self.filterId],\n }, self.filterId, onMessage, self.stopWatching.bind(self));\n\n};\n\nvar Filter = function (options, methods, formatter, callback) {\n var self = this;\n var implementation = {};\n methods.forEach(function (method) {\n method.attachToObject(implementation);\n });\n this.options = getOptions(options);\n this.implementation = implementation;\n this.filterId = null;\n this.callbacks = [];\n this.pollFilters = [];\n this.formatter = formatter;\n this.implementation.newFilter(this.options, function(error, id){\n if(error) {\n self.callbacks.forEach(function(cb){\n cb(error);\n });\n } else {\n self.filterId = id;\n\n // get filter logs for the already existing watch calls\n self.callbacks.forEach(function(cb){\n getLogsAtStart(self, cb);\n });\n if(self.callbacks.length > 0)\n pollFilter(self);\n\n // start to watch immediately\n if(callback) {\n return self.watch(callback);\n }\n }\n });\n\n};\n\nFilter.prototype.watch = function (callback) {\n this.callbacks.push(callback);\n\n if(this.filterId) {\n getLogsAtStart(this, callback);\n pollFilter(this);\n }\n\n return this;\n};\n\nFilter.prototype.stopWatching = function () {\n RequestManager.getInstance().stopPolling(this.filterId);\n // remove filter async\n this.implementation.uninstallFilter(this.filterId, function(){});\n this.callbacks = [];\n};\n\nFilter.prototype.get = function (callback) {\n var self = this;\n if (utils.isFunction(callback)) {\n this.implementation.getLogs(this.filterId, function(err, res){\n if (err) {\n callback(err);\n } else {\n callback(null, res.map(function (log) {\n return self.formatter ? self.formatter(log) : log;\n }));\n }\n });\n } else {\n var logs = this.implementation.getLogs(this.filterId);\n return logs.map(function (log) {\n return self.formatter ? self.formatter(log) : log;\n });\n }\n\n return this;\n};\n\nmodule.exports = Filter;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file formatters.js\n * @author Marek Kotewicz \n * @author Fabian Vogelsteller \n * @date 2015\n */\n\nvar utils = require('../utils/utils');\nvar config = require('../utils/config');\n\n/**\n * Should the format output to a big number\n *\n * @method outputBigNumberFormatter\n * @param {String|Number|BigNumber}\n * @returns {BigNumber} object\n */\nvar outputBigNumberFormatter = function (number) {\n return utils.toBigNumber(number);\n};\n\nvar isPredefinedBlockNumber = function (blockNumber) {\n return blockNumber === 'latest' || blockNumber === 'pending' || blockNumber === 'earliest';\n};\n\nvar inputDefaultBlockNumberFormatter = function (blockNumber) {\n if (blockNumber === undefined) {\n return config.defaultBlock;\n }\n return inputBlockNumberFormatter(blockNumber);\n};\n\nvar inputBlockNumberFormatter = function (blockNumber) {\n if (blockNumber === undefined) {\n return undefined;\n } else if (isPredefinedBlockNumber(blockNumber)) {\n return blockNumber;\n }\n return utils.toHex(blockNumber);\n};\n\n/**\n * Formats the input of a transaction and converts all values to HEX\n *\n * @method inputTransactionFormatter\n * @param {Object} transaction options\n * @returns object\n*/\nvar inputTransactionFormatter = function (options){\n\n options.from = options.from || config.defaultAccount;\n\n // make code -> data\n if (options.code) {\n options.data = options.code;\n delete options.code;\n }\n\n ['gasPrice', 'gas', 'value', 'nonce'].filter(function (key) {\n return options[key] !== undefined;\n }).forEach(function(key){\n options[key] = utils.fromDecimal(options[key]);\n });\n\n return options; \n};\n\n/**\n * Formats the output of a transaction to its proper values\n * \n * @method outputTransactionFormatter\n * @param {Object} transaction\n * @returns {Object} transaction\n*/\nvar outputTransactionFormatter = function (tx){\n if(tx.blockNumber !== null)\n tx.blockNumber = utils.toDecimal(tx.blockNumber);\n if(tx.transactionIndex !== null)\n tx.transactionIndex = utils.toDecimal(tx.transactionIndex);\n tx.nonce = utils.toDecimal(tx.nonce);\n tx.gas = utils.toDecimal(tx.gas);\n tx.gasPrice = utils.toBigNumber(tx.gasPrice);\n tx.value = utils.toBigNumber(tx.value);\n return tx;\n};\n\n/**\n * Formats the output of a block to its proper values\n *\n * @method outputBlockFormatter\n * @param {Object} block object \n * @returns {Object} block object\n*/\nvar outputBlockFormatter = function(block) {\n\n // transform to number\n block.gasLimit = utils.toDecimal(block.gasLimit);\n block.gasUsed = utils.toDecimal(block.gasUsed);\n block.size = utils.toDecimal(block.size);\n block.timestamp = utils.toDecimal(block.timestamp);\n if(block.number !== null)\n block.number = utils.toDecimal(block.number);\n\n block.difficulty = utils.toBigNumber(block.difficulty);\n block.totalDifficulty = utils.toBigNumber(block.totalDifficulty);\n\n if (utils.isArray(block.transactions)) {\n block.transactions.forEach(function(item){\n if(!utils.isString(item))\n return outputTransactionFormatter(item);\n });\n }\n\n return block;\n};\n\n/**\n * Formats the output of a log\n * \n * @method outputLogFormatter\n * @param {Object} log object\n * @returns {Object} log\n*/\nvar outputLogFormatter = function(log) {\n if(log.blockNumber !== null)\n log.blockNumber = utils.toDecimal(log.blockNumber);\n if(log.transactionIndex !== null)\n log.transactionIndex = utils.toDecimal(log.transactionIndex);\n if(log.logIndex !== null)\n log.logIndex = utils.toDecimal(log.logIndex);\n\n return log;\n};\n\n/**\n * Formats the input of a whisper post and converts all values to HEX\n *\n * @method inputPostFormatter\n * @param {Object} transaction object\n * @returns {Object}\n*/\nvar inputPostFormatter = function(post) {\n\n post.payload = utils.toHex(post.payload);\n post.ttl = utils.fromDecimal(post.ttl);\n post.workToProve = utils.fromDecimal(post.workToProve);\n post.priority = utils.fromDecimal(post.priority);\n\n // fallback\n if (!utils.isArray(post.topics)) {\n post.topics = post.topics ? [post.topics] : [];\n }\n\n // format the following options\n post.topics = post.topics.map(function(topic){\n return utils.fromAscii(topic);\n });\n\n return post; \n};\n\n/**\n * Formats the output of a received post message\n *\n * @method outputPostFormatter\n * @param {Object}\n * @returns {Object}\n */\nvar outputPostFormatter = function(post){\n\n post.expiry = utils.toDecimal(post.expiry);\n post.sent = utils.toDecimal(post.sent);\n post.ttl = utils.toDecimal(post.ttl);\n post.workProved = utils.toDecimal(post.workProved);\n post.payloadRaw = post.payload;\n post.payload = utils.toAscii(post.payload);\n\n if (utils.isJson(post.payload)) {\n post.payload = JSON.parse(post.payload);\n }\n\n // format the following options\n if (!post.topics) {\n post.topics = [];\n }\n post.topics = post.topics.map(function(topic){\n return utils.toAscii(topic);\n });\n\n return post;\n};\n\nmodule.exports = {\n inputDefaultBlockNumberFormatter: inputDefaultBlockNumberFormatter,\n inputBlockNumberFormatter: inputBlockNumberFormatter,\n inputTransactionFormatter: inputTransactionFormatter,\n inputPostFormatter: inputPostFormatter,\n outputBigNumberFormatter: outputBigNumberFormatter,\n outputTransactionFormatter: outputTransactionFormatter,\n outputBlockFormatter: outputBlockFormatter,\n outputLogFormatter: outputLogFormatter,\n outputPostFormatter: outputPostFormatter\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/**\n * @file function.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar web3 = require('../web3');\nvar coder = require('../solidity/coder');\nvar utils = require('../utils/utils');\nvar formatters = require('./formatters');\nvar sha3 = require('../utils/sha3');\n\n/**\n * This prototype should be used to call/sendTransaction to solidity functions\n */\nvar SolidityFunction = function (json, address) {\n this._inputTypes = json.inputs.map(function (i) {\n return i.type;\n });\n this._outputTypes = json.outputs.map(function (i) {\n return i.type;\n });\n this._constant = json.constant;\n this._name = utils.transformToFullName(json);\n this._address = address;\n};\n\nSolidityFunction.prototype.extractCallback = function (args) {\n if (utils.isFunction(args[args.length - 1])) {\n return args.pop(); // modify the args array!\n }\n};\n\nSolidityFunction.prototype.extractDefaultBlock = function (args) {\n if (args.length > this._inputTypes.length && !utils.isObject(args[args.length -1])) {\n return formatters.inputDefaultBlockNumberFormatter(args.pop()); // modify the args array!\n }\n};\n\n/**\n * Should be used to create payload from arguments\n *\n * @method toPayload\n * @param {Array} solidity function params\n * @param {Object} optional payload options\n */\nSolidityFunction.prototype.toPayload = function (args) {\n var options = {};\n if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) {\n options = args[args.length - 1];\n }\n options.to = this._address;\n options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args);\n return options;\n};\n\n/**\n * Should be used to get function signature\n *\n * @method signature\n * @return {String} function signature\n */\nSolidityFunction.prototype.signature = function () {\n return sha3(this._name).slice(0, 8);\n};\n\n\nSolidityFunction.prototype.unpackOutput = function (output) {\n if (!output) {\n return;\n }\n\n output = output.length >= 2 ? output.slice(2) : output;\n var result = coder.decodeParams(this._outputTypes, output);\n return result.length === 1 ? result[0] : result;\n};\n\n/**\n * Calls a contract function.\n *\n * @method call\n * @param {...Object} Contract function arguments\n * @param {function} If the last argument is a function, the contract function\n * call will be asynchronous, and the callback will be passed the\n * error and result.\n * @return {String} output bytes\n */\nSolidityFunction.prototype.call = function () {\n var args = Array.prototype.slice.call(arguments).filter(function (a) {return a !== undefined; });\n var callback = this.extractCallback(args);\n var defaultBlock = this.extractDefaultBlock(args);\n var payload = this.toPayload(args);\n\n\n if (!callback) {\n var output = web3.eth.call(payload, defaultBlock);\n return this.unpackOutput(output);\n } \n \n var self = this;\n web3.eth.call(payload, defaultBlock, function (error, output) {\n callback(error, self.unpackOutput(output));\n });\n};\n\n/**\n * Should be used to sendTransaction to solidity function\n *\n * @method sendTransaction\n * @param {Object} options\n */\nSolidityFunction.prototype.sendTransaction = function () {\n var args = Array.prototype.slice.call(arguments).filter(function (a) {return a !== undefined; });\n var callback = this.extractCallback(args);\n var payload = this.toPayload(args);\n\n if (!callback) {\n return web3.eth.sendTransaction(payload);\n }\n\n web3.eth.sendTransaction(payload, callback);\n};\n\n/**\n * Should be used to estimateGas of solidity function\n *\n * @method estimateGas\n * @param {Object} options\n */\nSolidityFunction.prototype.estimateGas = function () {\n var args = Array.prototype.slice.call(arguments);\n var callback = this.extractCallback(args);\n var payload = this.toPayload(args);\n\n if (!callback) {\n return web3.eth.estimateGas(payload);\n }\n\n web3.eth.estimateGas(payload, callback);\n};\n\n/**\n * Should be used to get function display name\n *\n * @method displayName\n * @return {String} display name of the function\n */\nSolidityFunction.prototype.displayName = function () {\n return utils.extractDisplayName(this._name);\n};\n\n/**\n * Should be used to get function type name\n *\n * @method typeName\n * @return {String} type name of the function\n */\nSolidityFunction.prototype.typeName = function () {\n return utils.extractTypeName(this._name);\n};\n\n/**\n * Should be called to get rpc requests from solidity function\n *\n * @method request\n * @returns {Object}\n */\nSolidityFunction.prototype.request = function () {\n var args = Array.prototype.slice.call(arguments);\n var callback = this.extractCallback(args);\n var payload = this.toPayload(args);\n var format = this.unpackOutput.bind(this);\n \n return {\n callback: callback,\n payload: payload, \n format: format\n };\n};\n\n/**\n * Should be called to execute function\n *\n * @method execute\n */\nSolidityFunction.prototype.execute = function () {\n var transaction = !this._constant;\n\n // send transaction\n if (transaction) {\n return this.sendTransaction.apply(this, Array.prototype.slice.call(arguments));\n }\n\n // call\n return this.call.apply(this, Array.prototype.slice.call(arguments));\n};\n\n/**\n * Should be called to attach function to contract\n *\n * @method attachToContract\n * @param {Contract}\n */\nSolidityFunction.prototype.attachToContract = function (contract) {\n var execute = this.execute.bind(this);\n execute.request = this.request.bind(this);\n execute.call = this.call.bind(this);\n execute.sendTransaction = this.sendTransaction.bind(this);\n execute.estimateGas = this.estimateGas.bind(this);\n var displayName = this.displayName();\n if (!contract[displayName]) {\n contract[displayName] = execute;\n }\n contract[displayName][this.typeName()] = execute; // circular!!!!\n};\n\nmodule.exports = SolidityFunction;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file httpprovider.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * @date 2014\n */\n\n\"use strict\";\n\nvar XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\nvar errors = require('./errors');\n\nvar HttpProvider = function (host) {\n this.host = host || 'http://localhost:8545';\n};\n\nHttpProvider.prototype.send = function (payload) {\n var request = new XMLHttpRequest();\n\n request.open('POST', this.host, false);\n request.setRequestHeader('Content-type','application/json');\n \n try {\n request.send(JSON.stringify(payload));\n } catch(error) {\n throw errors.InvalidConnection(this.host);\n }\n\n\n // check request.status\n // TODO: throw an error here! it cannot silently fail!!!\n //if (request.status !== 200) {\n //return;\n //}\n\n var result = request.responseText;\n\n try {\n result = JSON.parse(result);\n } catch(e) {\n throw errors.InvalidResponse(result); \n }\n\n return result;\n};\n\nHttpProvider.prototype.sendAsync = function (payload, callback) {\n var request = new XMLHttpRequest();\n request.onreadystatechange = function() {\n if (request.readyState === 4) {\n var result = request.responseText;\n var error = null;\n\n try {\n result = JSON.parse(result);\n } catch(e) {\n error = errors.InvalidResponse(result); \n }\n\n callback(error, result);\n }\n };\n\n request.open('POST', this.host, true);\n request.setRequestHeader('Content-type','application/json');\n \n try {\n request.send(JSON.stringify(payload));\n } catch(error) {\n callback(errors.InvalidConnection(this.host));\n }\n};\n\nmodule.exports = HttpProvider;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/**\n * @file function.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar web3 = require('../web3');\nvar coder = require('../solidity/coder');\nvar utils = require('../utils/utils');\nvar formatters = require('./formatters');\nvar sha3 = require('../utils/sha3');\n\n/**\n * This prototype should be used to call/sendTransaction to solidity functions\n */\nvar SolidityFunction = function (json, address) {\n this._inputTypes = json.inputs.map(function (i) {\n return i.type;\n });\n this._outputTypes = json.outputs.map(function (i) {\n return i.type;\n });\n this._constant = json.constant;\n this._name = utils.transformToFullName(json);\n this._address = address;\n};\n\nSolidityFunction.prototype.extractCallback = function (args) {\n if (utils.isFunction(args[args.length - 1])) {\n return args.pop(); // modify the args array!\n }\n};\n\nSolidityFunction.prototype.extractDefaultBlock = function (args) {\n if (args.length > this._inputTypes.length && !utils.isObject(args[args.length -1])) {\n return formatters.inputDefaultBlockNumberFormatter(args.pop()); // modify the args array!\n }\n};\n\n/**\n * Should be used to create payload from arguments\n *\n * @method toPayload\n * @param {Array} solidity function params\n * @param {Object} optional payload options\n */\nSolidityFunction.prototype.toPayload = function (args) {\n var options = {};\n if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) {\n options = args[args.length - 1];\n }\n options.to = this._address;\n options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args);\n return options;\n};\n\n/**\n * Should be used to get function signature\n *\n * @method signature\n * @return {String} function signature\n */\nSolidityFunction.prototype.signature = function () {\n return sha3(this._name).slice(0, 8);\n};\n\n\nSolidityFunction.prototype.unpackOutput = function (output) {\n if (!output) {\n return;\n }\n\n output = output.length >= 2 ? output.slice(2) : output;\n var result = coder.decodeParams(this._outputTypes, output);\n return result.length === 1 ? result[0] : result;\n};\n\n/**\n * Calls a contract function.\n *\n * @method call\n * @param {...Object} Contract function arguments\n * @param {function} If the last argument is a function, the contract function\n * call will be asynchronous, and the callback will be passed the\n * error and result.\n * @return {String} output bytes\n */\nSolidityFunction.prototype.call = function () {\n var args = Array.prototype.slice.call(arguments).filter(function (a) {return a !== undefined; });\n var callback = this.extractCallback(args);\n var defaultBlock = this.extractDefaultBlock(args);\n var payload = this.toPayload(args);\n\n\n if (!callback) {\n var output = web3.eth.call(payload, defaultBlock);\n return this.unpackOutput(output);\n } \n \n var self = this;\n web3.eth.call(payload, defaultBlock, function (error, output) {\n callback(error, self.unpackOutput(output));\n });\n};\n\n/**\n * Should be used to sendTransaction to solidity function\n *\n * @method sendTransaction\n * @param {Object} options\n */\nSolidityFunction.prototype.sendTransaction = function () {\n var args = Array.prototype.slice.call(arguments).filter(function (a) {return a !== undefined; });\n var callback = this.extractCallback(args);\n var payload = this.toPayload(args);\n\n if (!callback) {\n return web3.eth.sendTransaction(payload);\n }\n\n web3.eth.sendTransaction(payload, callback);\n};\n\n/**\n * Should be used to estimateGas of solidity function\n *\n * @method estimateGas\n * @param {Object} options\n */\nSolidityFunction.prototype.estimateGas = function () {\n var args = Array.prototype.slice.call(arguments);\n var callback = this.extractCallback(args);\n var payload = this.toPayload(args);\n\n if (!callback) {\n return web3.eth.estimateGas(payload);\n }\n\n web3.eth.estimateGas(payload, callback);\n};\n\n/**\n * Should be used to get function display name\n *\n * @method displayName\n * @return {String} display name of the function\n */\nSolidityFunction.prototype.displayName = function () {\n return utils.extractDisplayName(this._name);\n};\n\n/**\n * Should be used to get function type name\n *\n * @method typeName\n * @return {String} type name of the function\n */\nSolidityFunction.prototype.typeName = function () {\n return utils.extractTypeName(this._name);\n};\n\n/**\n * Should be called to get rpc requests from solidity function\n *\n * @method request\n * @returns {Object}\n */\nSolidityFunction.prototype.request = function () {\n var args = Array.prototype.slice.call(arguments);\n var callback = this.extractCallback(args);\n var payload = this.toPayload(args);\n var format = this.unpackOutput.bind(this);\n \n return {\n method: this._constant ? 'eth_call' : 'eth_sendTransaction',\n callback: callback,\n params: [payload], \n format: format\n };\n};\n\n/**\n * Should be called to execute function\n *\n * @method execute\n */\nSolidityFunction.prototype.execute = function () {\n var transaction = !this._constant;\n\n // send transaction\n if (transaction) {\n return this.sendTransaction.apply(this, Array.prototype.slice.call(arguments));\n }\n\n // call\n return this.call.apply(this, Array.prototype.slice.call(arguments));\n};\n\n/**\n * Should be called to attach function to contract\n *\n * @method attachToContract\n * @param {Contract}\n */\nSolidityFunction.prototype.attachToContract = function (contract) {\n var execute = this.execute.bind(this);\n execute.request = this.request.bind(this);\n execute.call = this.call.bind(this);\n execute.sendTransaction = this.sendTransaction.bind(this);\n execute.estimateGas = this.estimateGas.bind(this);\n var displayName = this.displayName();\n if (!contract[displayName]) {\n contract[displayName] = execute;\n }\n contract[displayName][this.typeName()] = execute; // circular!!!!\n};\n\nmodule.exports = SolidityFunction;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file httpprovider.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * @date 2014\n */\n\n\"use strict\";\n\n// resolves the problem for electron/atom shell environments, which use node integration, but have no process variable available\nvar XMLHttpRequest = (typeof window !== 'undefined' && window.XMLHttpRequest) ? window.XMLHttpRequest : require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\nvar errors = require('./errors');\n\nvar HttpProvider = function (host) {\n this.host = host || 'http://localhost:8545';\n};\n\nHttpProvider.prototype.send = function (payload) {\n var request = new XMLHttpRequest();\n\n request.open('POST', this.host, false);\n request.setRequestHeader('Content-type','application/json');\n \n try {\n request.send(JSON.stringify(payload));\n } catch(error) {\n throw errors.InvalidConnection(this.host);\n }\n\n\n // check request.status\n // TODO: throw an error here! it cannot silently fail!!!\n //if (request.status !== 200) {\n //return;\n //}\n\n var result = request.responseText;\n\n try {\n result = JSON.parse(result);\n } catch(e) {\n throw errors.InvalidResponse(result); \n }\n\n return result;\n};\n\nHttpProvider.prototype.sendAsync = function (payload, callback) {\n var request = new XMLHttpRequest();\n request.onreadystatechange = function() {\n if (request.readyState === 4) {\n var result = request.responseText;\n var error = null;\n\n try {\n result = JSON.parse(result);\n } catch(e) {\n error = errors.InvalidResponse(result); \n }\n\n callback(error, result);\n }\n };\n\n request.open('POST', this.host, true);\n request.setRequestHeader('Content-type','application/json');\n \n try {\n request.send(JSON.stringify(payload));\n } catch(error) {\n callback(errors.InvalidConnection(this.host));\n }\n};\n\nmodule.exports = HttpProvider;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file icap.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar utils = require('../utils/utils');\n\n/**\n * This prototype should be used to extract necessary information from iban address\n *\n * @param {String} iban\n */\nvar ICAP = function (iban) {\n this._iban = iban;\n};\n\n/**\n * Should be called to check if icap is correct\n *\n * @method isValid\n * @returns {Boolean} true if it is, otherwise false\n */\nICAP.prototype.isValid = function () {\n return utils.isIBAN(this._iban);\n};\n\n/**\n * Should be called to check if iban number is direct\n *\n * @method isDirect\n * @returns {Boolean} true if it is, otherwise false\n */\nICAP.prototype.isDirect = function () {\n return this._iban.length === 34;\n};\n\n/**\n * Should be called to check if iban number if indirect\n *\n * @method isIndirect\n * @returns {Boolean} true if it is, otherwise false\n */\nICAP.prototype.isIndirect = function () {\n return this._iban.length === 20;\n};\n\n/**\n * Should be called to get iban checksum\n * Uses the mod-97-10 checksumming protocol (ISO/IEC 7064:2003)\n *\n * @method checksum\n * @returns {String} checksum\n */\nICAP.prototype.checksum = function () {\n return this._iban.substr(2, 2);\n};\n\n/**\n * Should be called to get institution identifier\n * eg. XREG\n *\n * @method institution\n * @returns {String} institution identifier\n */\nICAP.prototype.institution = function () {\n return this.isIndirect() ? this._iban.substr(7, 4) : '';\n};\n\n/**\n * Should be called to get client identifier within institution\n * eg. GAVOFYORK\n *\n * @method client\n * @returns {String} client identifier\n */\nICAP.prototype.client = function () {\n return this.isIndirect() ? this._iban.substr(11) : '';\n};\n\n/**\n * Should be called to get client direct address\n *\n * @method address\n * @returns {String} client direct address\n */\nICAP.prototype.address = function () {\n return this.isDirect() ? this._iban.substr(4) : '';\n};\n\nmodule.exports = ICAP;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file jsonrpc.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar Jsonrpc = function () {\n // singleton pattern\n if (arguments.callee._singletonInstance) {\n return arguments.callee._singletonInstance;\n }\n arguments.callee._singletonInstance = this;\n\n this.messageId = 1;\n};\n\n/**\n * @return {Jsonrpc} singleton\n */\nJsonrpc.getInstance = function () {\n var instance = new Jsonrpc();\n return instance;\n};\n\n/**\n * Should be called to valid json create payload object\n *\n * @method toPayload\n * @param {Function} method of jsonrpc call, required\n * @param {Array} params, an array of method params, optional\n * @returns {Object} valid jsonrpc payload object\n */\nJsonrpc.prototype.toPayload = function (method, params) {\n if (!method)\n console.error('jsonrpc method should be specified!');\n\n return {\n jsonrpc: '2.0',\n method: method,\n params: params || [],\n id: this.messageId++\n };\n};\n\n/**\n * Should be called to check if jsonrpc response is valid\n *\n * @method isValidResponse\n * @param {Object}\n * @returns {Boolean} true if response is valid, otherwise false\n */\nJsonrpc.prototype.isValidResponse = function (response) {\n return !!response &&\n !response.error &&\n response.jsonrpc === '2.0' &&\n typeof response.id === 'number' &&\n response.result !== undefined; // only undefined is not valid json object\n};\n\n/**\n * Should be called to create batch payload object\n *\n * @method toBatchPayload\n * @param {Array} messages, an array of objects with method (required) and params (optional) fields\n * @returns {Array} batch payload\n */\nJsonrpc.prototype.toBatchPayload = function (messages) {\n var self = this;\n return messages.map(function (message) {\n return self.toPayload(message.method, message.params);\n });\n};\n\nmodule.exports = Jsonrpc;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/**\n * @file method.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar RequestManager = require('./requestmanager');\nvar utils = require('../utils/utils');\nvar errors = require('./errors');\n\nvar Method = function (options) {\n this.name = options.name;\n this.call = options.call;\n this.params = options.params || 0;\n this.inputFormatter = options.inputFormatter;\n this.outputFormatter = options.outputFormatter;\n};\n\n/**\n * Should be used to determine name of the jsonrpc method based on arguments\n *\n * @method getCall\n * @param {Array} arguments\n * @return {String} name of jsonrpc method\n */\nMethod.prototype.getCall = function (args) {\n return utils.isFunction(this.call) ? this.call(args) : this.call;\n};\n\n/**\n * Should be used to extract callback from array of arguments. Modifies input param\n *\n * @method extractCallback\n * @param {Array} arguments\n * @return {Function|Null} callback, if exists\n */\nMethod.prototype.extractCallback = function (args) {\n if (utils.isFunction(args[args.length - 1])) {\n return args.pop(); // modify the args array!\n }\n};\n\n/**\n * Should be called to check if the number of arguments is correct\n * \n * @method validateArgs\n * @param {Array} arguments\n * @throws {Error} if it is not\n */\nMethod.prototype.validateArgs = function (args) {\n if (args.length !== this.params) {\n throw errors.InvalidNumberOfParams();\n }\n};\n\n/**\n * Should be called to format input args of method\n * \n * @method formatInput\n * @param {Array}\n * @return {Array}\n */\nMethod.prototype.formatInput = function (args) {\n if (!this.inputFormatter) {\n return args;\n }\n\n return this.inputFormatter.map(function (formatter, index) {\n return formatter ? formatter(args[index]) : args[index];\n });\n};\n\n/**\n * Should be called to format output(result) of method\n *\n * @method formatOutput\n * @param {Object}\n * @return {Object}\n */\nMethod.prototype.formatOutput = function (result) {\n return this.outputFormatter && result !== null ? this.outputFormatter(result) : result;\n};\n\n/**\n * Should attach function to method\n * \n * @method attachToObject\n * @param {Object}\n * @param {Function}\n */\nMethod.prototype.attachToObject = function (obj) {\n var func = this.send.bind(this);\n func.request = this.request.bind(this);\n func.call = this.call; // that's ugly. filter.js uses it\n var name = this.name.split('.');\n if (name.length > 1) {\n obj[name[0]] = obj[name[0]] || {};\n obj[name[0]][name[1]] = func;\n } else {\n obj[name[0]] = func; \n }\n};\n\n/**\n * Should create payload from given input args\n *\n * @method toPayload\n * @param {Array} args\n * @return {Object}\n */\nMethod.prototype.toPayload = function (args) {\n var call = this.getCall(args);\n var callback = this.extractCallback(args);\n var params = this.formatInput(args);\n this.validateArgs(params);\n\n return {\n method: call,\n params: params,\n callback: callback\n };\n};\n\n/**\n * Should be called to create pure JSONRPC request which can be used in batch request\n *\n * @method request\n * @param {...} params\n * @return {Object} jsonrpc request\n */\nMethod.prototype.request = function () {\n var payload = this.toPayload(Array.prototype.slice.call(arguments));\n payload.format = this.formatOutput.bind(this);\n return payload;\n};\n\n/**\n * Should send request to the API\n *\n * @method send\n * @param list of params\n * @return result\n */\nMethod.prototype.send = function () {\n var payload = this.toPayload(Array.prototype.slice.call(arguments));\n if (payload.callback) {\n var self = this;\n return RequestManager.getInstance().sendAsync(payload, function (err, result) {\n payload.callback(err, self.formatOutput(result));\n });\n }\n return this.formatOutput(RequestManager.getInstance().send(payload));\n};\n\nmodule.exports = Method;\n\n", diff --git a/dist/web3.min.js b/dist/web3.min.js index a73cde830..3d9c300e8 100644 --- a/dist/web3.min.js +++ b/dist/web3.min.js @@ -1,2 +1,4 @@ -require=function t(e,n,r){function i(a,s){if(!n[a]){if(!e[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(o)return o(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return i(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;ao;o+=64)n.push(this._outputFormatter(new a(t.dynamicPart().substr(o+64,64))));return n}return this._outputFormatter(t)},u.prototype.sliceParam=function(t,e,n){return"bytes"===this._mode?a.decodeBytes(t,e):s(n)?a.decodeArray(t,e):a.decodeParam(t,e)};var c=function(t){this._types=t};c.prototype._requireType=function(t){var e=this._types.filter(function(e){return e.isType(t)})[0];if(!e)throw Error("invalid solidity type!: "+t);return e},c.prototype._formatInput=function(t,e){return this._requireType(t).formatInput(e,s(t))},c.prototype.encodeParam=function(t,e){return this._formatInput(t,e).encode()},c.prototype.encodeParams=function(t,e){var n=this,r=t.map(function(t,r){return n._formatInput(t,e[r])});return a.encodeList(r)},c.prototype.decodeParam=function(t,e){return this.decodeParams([t],e)[0]},c.prototype.decodeParams=function(t,e){var n=this;return t.map(function(t,r){var i=n._requireType(t),o=i.sliceParam(e,r,t);return i.formatOutput(o,s(t))})};var l=new c([new u({name:"address",match:"strict",mode:"value",inputFormatter:o.formatInputInt,outputFormatter:o.formatOutputAddress}),new u({name:"bool",match:"strict",mode:"value",inputFormatter:o.formatInputBool,outputFormatter:o.formatOutputBool}),new u({name:"int",match:"prefix",mode:"value",inputFormatter:o.formatInputInt,outputFormatter:o.formatOutputInt}),new u({name:"uint",match:"prefix",mode:"value",inputFormatter:o.formatInputInt,outputFormatter:o.formatOutputUInt}),new u({name:"bytes",match:"strict",mode:"bytes",inputFormatter:o.formatInputDynamicBytes,outputFormatter:o.formatOutputDynamicBytes}),new u({name:"bytes",match:"prefix",mode:"value",inputFormatter:o.formatInputBytes,outputFormatter:o.formatOutputBytes}),new u({name:"real",match:"prefix",mode:"value",inputFormatter:o.formatInputReal,outputFormatter:o.formatOutputReal}),new u({name:"ureal",match:"prefix",mode:"value",inputFormatter:o.formatInputReal,outputFormatter:o.formatOutputUReal})]);e.exports=l},{"../utils/utils":7,"./formatters":2,"./param":3,"bignumber.js":"bignumber.js"}],2:[function(t,e,n){var r=t("bignumber.js"),i=t("../utils/utils"),o=t("../utils/config"),a=t("./param"),s=function(t){var e=2*o.ETH_PADDING;r.config(o.ETH_BIGNUMBER_ROUNDING_MODE);var n=i.padLeft(i.toTwosComplement(t).round().toString(16),e);return new a(n)},u=function(t){var e=i.fromAscii(t,o.ETH_PADDING).substr(2);return new a(e)},c=function(t){var e=i.fromAscii(t,o.ETH_PADDING).substr(2);return new a(s(t.length).value+e,32)},l=function(t){var e="000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0");return new a(e)},f=function(t){return s(new r(t).times(new r(2).pow(128)))},p=function(t){return"1"===new r(t.substr(0,1),16).toString(2).substr(0,1)},h=function(t){var e=t.staticPart()||"0";return p(e)?new r(e,16).minus(new r("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new r(e,16)},m=function(t){var e=t.staticPart()||"0";return new r(e,16)},d=function(t){return h(t).dividedBy(new r(2).pow(128))},g=function(t){return m(t).dividedBy(new r(2).pow(128))},y=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t.staticPart()?!0:!1},v=function(t){return i.toAscii(t.staticPart())},b=function(t){return i.toAscii(t.dynamicPart().slice(64))},w=function(t){var e=t.staticPart();return"0x"+e.slice(e.length-40,e.length)};e.exports={formatInputInt:s,formatInputBytes:u,formatInputDynamicBytes:c,formatInputBool:l,formatInputReal:f,formatOutputInt:h,formatOutputUInt:m,formatOutputReal:d,formatOutputUReal:g,formatOutputBool:y,formatOutputBytes:v,formatOutputDynamicBytes:b,formatOutputAddress:w}},{"../utils/config":5,"../utils/utils":7,"./param":3,"bignumber.js":"bignumber.js"}],3:[function(t,e,n){var r=t("../utils/utils"),i=function(t,e){this.value=t||"",this.offset=e};i.prototype.dynamicPartLength=function(){return this.dynamicPart().length/2},i.prototype.withOffset=function(t){return new i(this.value,t)},i.prototype.combine=function(t){return new i(this.value+t.value)},i.prototype.isDynamic=function(){return this.value.length>64||void 0!==this.offset},i.prototype.offsetAsBytes=function(){return this.isDynamic()?r.padLeft(r.toTwosComplement(this.offset).toString(16),64):""},i.prototype.staticPart=function(){return this.isDynamic()?this.offsetAsBytes():this.value},i.prototype.dynamicPart=function(){return this.isDynamic()?this.value:""},i.prototype.encode=function(){return this.staticPart()+this.dynamicPart()},i.encodeList=function(t){var e=32*t.length,n=t.map(function(t){if(!t.isDynamic())return t;var n=e;return e+=t.dynamicPartLength(),t.withOffset(n)});return n.reduce(function(t,e){return t+e.dynamicPart()},n.reduce(function(t,e){return t+e.staticPart()},""))},i.decodeParam=function(t,e){return e=e||0,new i(t.substr(64*e,64))};var o=function(t,e){return parseInt("0x"+t.substr(64*e,64))};i.decodeBytes=function(t,e){e=e||0;var n=o(t,e);return new i(t.substr(2*n,128),0)},i.decodeArray=function(t,e){e=e||0;var n=o(t,e),r=parseInt("0x"+t.substr(2*n,64));return new i(t.substr(2*n,64*(r+1)),0)},e.exports=i},{"../utils/utils":7}],4:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],5:[function(t,e,n){var r=t("bignumber.js"),i=["wei","kwei","Mwei","Gwei","szabo","finney","femtoether","picoether","nanoether","microether","milliether","nano","micro","milli","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:i,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:r.ROUND_DOWN},ETH_POLLING_TIMEOUT:500,defaultBlock:"latest",defaultAccount:void 0}},{"bignumber.js":"bignumber.js"}],6:[function(t,e,n){var r=t("./utils"),i=t("crypto-js/sha3");e.exports=function(t,e){return"0x"!==t.substr(0,2)||e||(console.warn("requirement of using web3.fromAscii before sha3 is deprecated"),console.warn("new usage: 'web3.sha3(\"hello\")'"),console.warn("see https://github.com/ethereum/web3.js/pull/205"),console.warn("if you need to hash hex value, you can do 'sha3(\"0xfff\", true)'"),t=r.toAscii(t)),i(t,{outputLength:256}).toString()}},{"./utils":7,"crypto-js/sha3":33}],7:[function(t,e,n){var r=t("bignumber.js"),i={wei:"1",kwei:"1000",ada:"1000",femtoether:"1000",mwei:"1000000",babbage:"1000000",picoether:"1000000",gwei:"1000000000",shannon:"1000000000",nanoether:"1000000000",nano:"1000000000",szabo:"1000000000000",microether:"1000000000000",micro:"1000000000000",finney:"1000000000000000",milliether:"1000000000000000",milli:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},o=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},a=function(t){var e="",n=0,r=t.length;for("0x"===t.substring(0,2)&&(n=2);r>n;n+=2){var i=parseInt(t.substr(n,2),16);if(0===i)break;e+=String.fromCharCode(i)}return e},s=function(t){for(var e="",n=0;nthis._inputTypes.length&&!o.isObject(t[t.length-1])?a.inputDefaultBlockNumberFormatter(t.pop()):void 0},u.prototype.toPayload=function(t){var e={};return t.length>this._inputTypes.length&&o.isObject(t[t.length-1])&&(e=t[t.length-1]),e.to=this._address,e.data="0x"+this.signature()+i.encodeParams(this._inputTypes,t),e},u.prototype.signature=function(){return s(this._name).slice(0,8)},u.prototype.unpackOutput=function(t){if(t){t=t.length>=2?t.slice(2):t;var e=i.decodeParams(this._outputTypes,t);return 1===e.length?e[0]:e}},u.prototype.call=function(){var t=Array.prototype.slice.call(arguments).filter(function(t){return void 0!==t}),e=this.extractCallback(t),n=this.extractDefaultBlock(t),i=this.toPayload(t);if(!e){var o=r.eth.call(i,n);return this.unpackOutput(o)}var a=this;r.eth.call(i,n,function(t,n){e(t,a.unpackOutput(n))})},u.prototype.sendTransaction=function(){var t=Array.prototype.slice.call(arguments).filter(function(t){return void 0!==t}),e=this.extractCallback(t),n=this.toPayload(t);return e?void r.eth.sendTransaction(n,e):r.eth.sendTransaction(n)},u.prototype.estimateGas=function(){var t=Array.prototype.slice.call(arguments),e=this.extractCallback(t),n=this.toPayload(t);return e?void r.eth.estimateGas(n,e):r.eth.estimateGas(n)},u.prototype.displayName=function(){return o.extractDisplayName(this._name)},u.prototype.typeName=function(){return o.extractTypeName(this._name)},u.prototype.request=function(){var t=Array.prototype.slice.call(arguments),e=this.extractCallback(t),n=this.toPayload(t),r=this.unpackOutput.bind(this);return{callback:e,payload:n,format:r}},u.prototype.execute=function(){var t=!this._constant;return t?this.sendTransaction.apply(this,Array.prototype.slice.call(arguments)):this.call.apply(this,Array.prototype.slice.call(arguments))},u.prototype.attachToContract=function(t){var e=this.execute.bind(this);e.request=this.request.bind(this),e.call=this.call.bind(this),e.sendTransaction=this.sendTransaction.bind(this),e.estimateGas=this.estimateGas.bind(this);var n=this.displayName();t[n]||(t[n]=e),t[n][this.typeName()]=e},e.exports=u},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9,"./formatters":17}],19:[function(t,e,n){"use strict";var r=t("xmlhttprequest").XMLHttpRequest,i=t("./errors"),o=function(t){this.host=t||"http://localhost:8545"};o.prototype.send=function(t){var e=new r;e.open("POST",this.host,!1),e.setRequestHeader("Content-type","application/json");try{e.send(JSON.stringify(t))}catch(n){throw i.InvalidConnection(this.host)}var o=e.responseText;try{o=JSON.parse(o)}catch(a){throw i.InvalidResponse(o)}return o},o.prototype.sendAsync=function(t,e){var n=new r;n.onreadystatechange=function(){if(4===n.readyState){var t=n.responseText,r=null;try{t=JSON.parse(t)}catch(o){r=i.InvalidResponse(t)}e(r,t)}},n.open("POST",this.host,!0),n.setRequestHeader("Content-type","application/json");try{n.send(JSON.stringify(t))}catch(o){e(i.InvalidConnection(this.host))}},e.exports=o},{"./errors":13,xmlhttprequest:4}],20:[function(t,e,n){var r=t("../utils/utils"),i=function(t){this._iban=t};i.prototype.isValid=function(){return r.isIBAN(this._iban)},i.prototype.isDirect=function(){return 34===this._iban.length},i.prototype.isIndirect=function(){return 20===this._iban.length},i.prototype.checksum=function(){return this._iban.substr(2,2)},i.prototype.institution=function(){return this.isIndirect()?this._iban.substr(7,4):""},i.prototype.client=function(){return this.isIndirect()?this._iban.substr(11):""},i.prototype.address=function(){return this.isDirect()?this._iban.substr(4):""},e.exports=i},{"../utils/utils":7}],21:[function(t,e,n){var r=function(){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,void(this.messageId=1))};r.getInstance=function(){var t=new r;return t},r.prototype.toPayload=function(t,e){return t||console.error("jsonrpc method should be specified!"),{jsonrpc:"2.0",method:t,params:e||[],id:this.messageId++}},r.prototype.isValidResponse=function(t){return!!t&&!t.error&&"2.0"===t.jsonrpc&&"number"==typeof t.id&&void 0!==t.result},r.prototype.toBatchPayload=function(t){var e=this;return t.map(function(t){return e.toPayload(t.method,t.params)})},e.exports=r},{}],22:[function(t,e,n){var r=t("./requestmanager"),i=t("../utils/utils"),o=t("./errors"),a=function(t){this.name=t.name,this.call=t.call,this.params=t.params||0,this.inputFormatter=t.inputFormatter,this.outputFormatter=t.outputFormatter};a.prototype.getCall=function(t){return i.isFunction(this.call)?this.call(t):this.call},a.prototype.extractCallback=function(t){return i.isFunction(t[t.length-1])?t.pop():void 0},a.prototype.validateArgs=function(t){if(t.length!==this.params)throw o.InvalidNumberOfParams()},a.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter.map(function(e,n){return e?e(t[n]):t[n]}):t},a.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},a.prototype.attachToObject=function(t){var e=this.send.bind(this);e.request=this.request.bind(this),e.call=this.call;var n=this.name.split(".");n.length>1?(t[n[0]]=t[n[0]]||{},t[n[0]][n[1]]=e):t[n[0]]=e},a.prototype.toPayload=function(t){var e=this.getCall(t),n=this.extractCallback(t),r=this.formatInput(t);return this.validateArgs(r),{method:e,params:r,callback:n}},a.prototype.request=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));return t.format=this.formatOutput.bind(this),t},a.prototype.send=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));if(t.callback){var e=this;return r.getInstance().sendAsync(t,function(n,r){t.callback(n,e.formatOutput(r))})}return this.formatOutput(r.getInstance().send(t))},e.exports=a},{"../utils/utils":7,"./errors":13,"./requestmanager":27}],23:[function(t,e,n){var r=t("./contract"),i="0xc6d9d2cd449a754c494264e1809c50e34d64562b",o=[{constant:!0,inputs:[{name:"_owner",type:"address"}],name:"name",outputs:[{name:"o_name",type:"bytes32"}],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"owner",outputs:[{name:"",type:"address"}],type:"function"},{constant:!0, -inputs:[{name:"_name",type:"bytes32"}],name:"content",outputs:[{name:"",type:"bytes32"}],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"addr",outputs:[{name:"",type:"address"}],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"}],name:"reserve",outputs:[],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"subRegistrar",outputs:[{name:"o_subRegistrar",type:"address"}],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_newOwner",type:"address"}],name:"transfer",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_registrar",type:"address"}],name:"setSubRegistrar",outputs:[],type:"function"},{constant:!1,inputs:[],name:"Registrar",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_a",type:"address"},{name:"_primary",type:"bool"}],name:"setAddress",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_content",type:"bytes32"}],name:"setContent",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"}],name:"disown",outputs:[],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"register",outputs:[{name:"",type:"address"}],type:"function"},{anonymous:!1,inputs:[{indexed:!0,name:"name",type:"bytes32"}],name:"Changed",type:"event"},{anonymous:!1,inputs:[{indexed:!0,name:"name",type:"bytes32"},{indexed:!0,name:"addr",type:"address"}],name:"PrimaryChanged",type:"event"}];e.exports=r(o).at(i)},{"./contract":11}],24:[function(t,e,n){var r=t("../utils/utils"),i=t("./property"),o=[],a=[new i({name:"listening",getter:"net_listening"}),new i({name:"peerCount",getter:"net_peerCount",outputFormatter:r.toDecimal})];e.exports={methods:o,properties:a}},{"../utils/utils":7,"./property":25}],25:[function(t,e,n){var r=t("./requestmanager"),i=function(t){this.name=t.name,this.getter=t.getter,this.setter=t.setter,this.outputFormatter=t.outputFormatter,this.inputFormatter=t.inputFormatter};i.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter(t):t},i.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},i.prototype.attachToObject=function(t){var e={get:this.get.bind(this)},n=this.name.split("."),r=n[0];n.length>1&&(t[n[0]]=t[n[0]]||{},t=t[n[0]],r=n[1]),Object.defineProperty(t,r,e);var i=function(t,e){return t+e.charAt(0).toUpperCase()+e.slice(1)};t[i("get",r)]=this.getAsync.bind(this)},i.prototype.get=function(){return this.formatOutput(r.getInstance().send({method:this.getter}))},i.prototype.getAsync=function(t){var e=this;r.getInstance().sendAsync({method:this.getter},function(n,r){return n?t(n):void t(n,e.formatOutput(r))})},e.exports=i},{"./requestmanager":27}],26:[function(t,e,n){var r=function(){};r.prototype.send=function(t){var e=navigator.qt.callMethod(JSON.stringify(t));return JSON.parse(e)},e.exports=r},{}],27:[function(t,e,n){var r=t("./jsonrpc"),i=t("../utils/utils"),o=t("../utils/config"),a=t("./errors"),s=function(t){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,this.provider=t,this.polls={},this.timeout=null,void(this.isPolling=!1))};s.getInstance=function(){var t=new s;return t},s.prototype.send=function(t){if(!this.provider)return console.error(a.InvalidProvider()),null;var e=r.getInstance().toPayload(t.method,t.params),n=this.provider.send(e);if(!r.getInstance().isValidResponse(n))throw a.InvalidResponse(n);return n.result},s.prototype.sendAsync=function(t,e){if(!this.provider)return e(a.InvalidProvider());var n=r.getInstance().toPayload(t.method,t.params);this.provider.sendAsync(n,function(t,n){return t?e(t):r.getInstance().isValidResponse(n)?void e(null,n.result):e(a.InvalidResponse(n))})},s.prototype.sendBatch=function(t,e){if(!this.provider)return e(a.InvalidProvider());var n=r.getInstance().toBatchPayload(t);this.provider.sendAsync(n,function(t,n){return t?e(t):i.isArray(n)?void e(t,n):e(a.InvalidResponse(n))})},s.prototype.setProvider=function(t){this.provider=t,this.provider&&!this.isPolling&&(this.poll(),this.isPolling=!0)},s.prototype.startPolling=function(t,e,n,r){this.polls["poll_"+e]={data:t,id:e,callback:n,uninstall:r}},s.prototype.stopPolling=function(t){delete this.polls["poll_"+t]},s.prototype.reset=function(){for(var t in this.polls)this.polls[t].uninstall();this.polls={},this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.poll()},s.prototype.poll=function(){if(this.timeout=setTimeout(this.poll.bind(this),o.ETH_POLLING_TIMEOUT),0!==Object.keys(this.polls).length){if(!this.provider)return void console.error(a.InvalidProvider());var t=[],e=[];for(var n in this.polls)t.push(this.polls[n].data),e.push(n);if(0!==t.length){var s=r.getInstance().toBatchPayload(t),u=this;this.provider.sendAsync(s,function(t,n){if(!t){if(!i.isArray(n))throw a.InvalidResponse(n);n.map(function(t,n){var r=e[n];return u.polls[r]?(t.callback=u.polls[r].callback,t):!1}).filter(function(t){return!!t}).filter(function(t){var e=r.getInstance().isValidResponse(t);return e||t.callback(a.InvalidResponse(t)),e}).filter(function(t){return i.isArray(t.result)&&t.result.length>0}).forEach(function(t){t.callback(null,t.result)})}})}}},e.exports=s},{"../utils/config":5,"../utils/utils":7,"./errors":13,"./jsonrpc":21}],28:[function(t,e,n){var r=t("./method"),i=t("./formatters"),o=new r({name:"post",call:"shh_post",params:1,inputFormatter:[i.inputPostFormatter]}),a=new r({name:"newIdentity",call:"shh_newIdentity",params:0}),s=new r({name:"hasIdentity",call:"shh_hasIdentity",params:1}),u=new r({name:"newGroup",call:"shh_newGroup",params:0}),c=new r({name:"addToGroup",call:"shh_addToGroup",params:0}),l=[o,a,s,u,c];e.exports={methods:l}},{"./formatters":17,"./method":22}],29:[function(t,e,n){var r=t("../web3"),i=t("./icap"),o=t("./namereg"),a=t("./contract"),s=function(t,e,n,r){var a=new i(e);if(!a.isValid())throw new Error("invalid iban address");if(a.isDirect())return u(t,a.address(),n,r);if(!r){var s=o.addr(a.institution());return c(t,s,n,a.client())}o.addr(a.insitution(),function(e,i){return c(t,i,n,a.client(),r)})},u=function(t,e,n,i){return r.eth.sendTransaction({address:e,from:t,value:n},i)},c=function(t,e,n,r,i){var o=[{constant:!1,inputs:[{name:"name",type:"bytes32"}],name:"deposit",outputs:[],type:"function"}];return a(o).at(e).deposit(r,{from:t,value:n},i)};e.exports=s},{"../web3":9,"./contract":11,"./icap":20,"./namereg":23}],30:[function(t,e,n){var r=t("./method"),i=function(){var t=function(t){var e=t[0];switch(e){case"latest":return t.shift(),this.params=0,"eth_newBlockFilter";case"pending":return t.shift(),this.params=0,"eth_newPendingTransactionFilter";default:return"eth_newFilter"}},e=new r({name:"newFilter",call:t,params:1}),n=new r({name:"uninstallFilter",call:"eth_uninstallFilter",params:1}),i=new r({name:"getLogs",call:"eth_getFilterLogs",params:1}),o=new r({name:"poll",call:"eth_getFilterChanges",params:1});return[e,n,i,o]},o=function(){var t=new r({name:"newFilter",call:"shh_newFilter",params:1}),e=new r({name:"uninstallFilter",call:"shh_uninstallFilter",params:1}),n=new r({name:"getLogs",call:"shh_getMessages",params:1}),i=new r({name:"poll",call:"shh_getFilterChanges",params:1});return[t,e,n,i]};e.exports={eth:i,shh:o}},{"./method":22}],31:[function(t,e,n){},{}],32:[function(t,e,n){!function(t,r){"object"==typeof n?e.exports=n=r():"function"==typeof define&&define.amd?define([],r):t.CryptoJS=r()}(this,function(){var t=t||function(t,e){var n={},r=n.lib={},i=r.Base=function(){function t(){}return{extend:function(e){t.prototype=this;var n=new t;return e&&n.mixIn(e),n.hasOwnProperty("init")||(n.init=function(){n.$super.init.apply(this,arguments)}),n.init.prototype=n,n.$super=this,n},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}}}(),o=r.WordArray=i.extend({init:function(t,n){t=this.words=t||[],this.sigBytes=n!=e?n:4*t.length},toString:function(t){return(t||s).stringify(this)},concat:function(t){var e=this.words,n=t.words,r=this.sigBytes,i=t.sigBytes;if(this.clamp(),r%4)for(var o=0;i>o;o++){var a=n[o>>>2]>>>24-o%4*8&255;e[r+o>>>2]|=a<<24-(r+o)%4*8}else for(var o=0;i>o;o+=4)e[r+o>>>2]=n[o>>>2];return this.sigBytes+=i,this},clamp:function(){var e=this.words,n=this.sigBytes;e[n>>>2]&=4294967295<<32-n%4*8,e.length=t.ceil(n/4)},clone:function(){var t=i.clone.call(this);return t.words=this.words.slice(0),t},random:function(e){for(var n,r=[],i=function(e){var e=e,n=987654321,r=4294967295;return function(){n=36969*(65535&n)+(n>>16)&r,e=18e3*(65535&e)+(e>>16)&r;var i=(n<<16)+e&r;return i/=4294967296,i+=.5,i*(t.random()>.5?1:-1)}},a=0;e>a;a+=4){var s=i(4294967296*(n||t.random()));n=987654071*s(),r.push(4294967296*s()|0)}return new o.init(r,e)}}),a=n.enc={},s=a.Hex={stringify:function(t){for(var e=t.words,n=t.sigBytes,r=[],i=0;n>i;i++){var o=e[i>>>2]>>>24-i%4*8&255;r.push((o>>>4).toString(16)),r.push((15&o).toString(16))}return r.join("")},parse:function(t){for(var e=t.length,n=[],r=0;e>r;r+=2)n[r>>>3]|=parseInt(t.substr(r,2),16)<<24-r%8*4;return new o.init(n,e/2)}},u=a.Latin1={stringify:function(t){for(var e=t.words,n=t.sigBytes,r=[],i=0;n>i;i++){var o=e[i>>>2]>>>24-i%4*8&255;r.push(String.fromCharCode(o))}return r.join("")},parse:function(t){for(var e=t.length,n=[],r=0;e>r;r++)n[r>>>2]|=(255&t.charCodeAt(r))<<24-r%4*8;return new o.init(n,e)}},c=a.Utf8={stringify:function(t){try{return decodeURIComponent(escape(u.stringify(t)))}catch(e){throw new Error("Malformed UTF-8 data")}},parse:function(t){return u.parse(unescape(encodeURIComponent(t)))}},l=r.BufferedBlockAlgorithm=i.extend({reset:function(){this._data=new o.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=c.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(e){var n=this._data,r=n.words,i=n.sigBytes,a=this.blockSize,s=4*a,u=i/s;u=e?t.ceil(u):t.max((0|u)-this._minBufferSize,0);var c=u*a,l=t.min(4*c,i);if(c){for(var f=0;c>f;f+=a)this._doProcessBlock(r,f);var p=r.splice(0,c);n.sigBytes-=l}return new o.init(p,l)},clone:function(){var t=i.clone.call(this);return t._data=this._data.clone(),t},_minBufferSize:0}),f=(r.Hasher=l.extend({cfg:i.extend(),init:function(t){this.cfg=this.cfg.extend(t),this.reset()},reset:function(){l.reset.call(this),this._doReset()},update:function(t){return this._append(t),this._process(),this},finalize:function(t){t&&this._append(t);var e=this._doFinalize();return e},blockSize:16,_createHelper:function(t){return function(e,n){return new t.init(n).finalize(e)}},_createHmacHelper:function(t){return function(e,n){return new f.HMAC.init(t,n).finalize(e)}}}),n.algo={});return n}(Math);return t})},{}],33:[function(t,e,n){!function(r,i,o){"object"==typeof n?e.exports=n=i(t("./core"),t("./x64-core")):"function"==typeof define&&define.amd?define(["./core","./x64-core"],i):i(r.CryptoJS)}(this,function(t){return function(e){var n=t,r=n.lib,i=r.WordArray,o=r.Hasher,a=n.x64,s=a.Word,u=n.algo,c=[],l=[],f=[];!function(){for(var t=1,e=0,n=0;24>n;n++){c[t+5*e]=(n+1)*(n+2)/2%64;var r=e%5,i=(2*t+3*e)%5;t=r,e=i}for(var t=0;5>t;t++)for(var e=0;5>e;e++)l[t+5*e]=e+(2*t+3*e)%5*5;for(var o=1,a=0;24>a;a++){for(var u=0,p=0,h=0;7>h;h++){if(1&o){var m=(1<m?p^=1<t;t++)p[t]=s.create()}();var h=u.SHA3=o.extend({cfg:o.cfg.extend({outputLength:512}),_doReset:function(){for(var t=this._state=[],e=0;25>e;e++)t[e]=new s.init;this.blockSize=(1600-2*this.cfg.outputLength)/32},_doProcessBlock:function(t,e){for(var n=this._state,r=this.blockSize/2,i=0;r>i;i++){var o=t[e+2*i],a=t[e+2*i+1];o=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),a=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8);var s=n[i];s.high^=a,s.low^=o}for(var u=0;24>u;u++){for(var h=0;5>h;h++){for(var m=0,d=0,g=0;5>g;g++){var s=n[h+5*g];m^=s.high,d^=s.low}var y=p[h];y.high=m,y.low=d}for(var h=0;5>h;h++)for(var v=p[(h+4)%5],b=p[(h+1)%5],w=b.high,_=b.low,m=v.high^(w<<1|_>>>31),d=v.low^(_<<1|w>>>31),g=0;5>g;g++){var s=n[h+5*g];s.high^=m,s.low^=d}for(var x=1;25>x;x++){var s=n[x],F=s.high,I=s.low,B=c[x];if(32>B)var m=F<>>32-B,d=I<>>32-B;else var m=I<>>64-B,d=F<>>64-B;var N=p[l[x]];N.high=m,N.low=d}var O=p[0],A=n[0];O.high=A.high,O.low=A.low;for(var h=0;5>h;h++)for(var g=0;5>g;g++){var x=h+5*g,s=n[x],k=p[x],P=p[(h+1)%5+5*g],T=p[(h+2)%5+5*g];s.high=k.high^~P.high&T.high,s.low=k.low^~P.low&T.low}var s=n[0],D=f[u];s.high^=D.high,s.low^=D.low}},_doFinalize:function(){var t=this._data,n=t.words,r=(8*this._nDataBytes,8*t.sigBytes),o=32*this.blockSize;n[r>>>5]|=1<<24-r%32,n[(e.ceil((r+1)/o)*o>>>5)-1]|=128,t.sigBytes=4*n.length,this._process();for(var a=this._state,s=this.cfg.outputLength/8,u=s/8,c=[],l=0;u>l;l++){var f=a[l],p=f.high,h=f.low;p=16711935&(p<<8|p>>>24)|4278255360&(p<<24|p>>>8),h=16711935&(h<<8|h>>>24)|4278255360&(h<<24|h>>>8),c.push(h),c.push(p)}return new i.init(c,s)},clone:function(){for(var t=o.clone.call(this),e=t._state=this._state.slice(0),n=0;25>n;n++)e[n]=e[n].clone();return t}});n.SHA3=o._createHelper(h),n.HmacSHA3=o._createHmacHelper(h)}(Math),t.SHA3})},{"./core":32,"./x64-core":34}],34:[function(t,e,n){!function(r,i){"object"==typeof n?e.exports=n=i(t("./core")):"function"==typeof define&&define.amd?define(["./core"],i):i(r.CryptoJS)}(this,function(t){return function(e){{var n=t,r=n.lib,i=r.Base,o=r.WordArray,a=n.x64={};a.Word=i.extend({init:function(t,e){this.high=t,this.low=e}}),a.WordArray=i.extend({init:function(t,n){t=this.words=t||[],this.sigBytes=n!=e?n:8*t.length},toX32:function(){for(var t=this.words,e=t.length,n=[],r=0;e>r;r++){var i=t[r];n.push(i.high),n.push(i.low)}return o.create(n,this.sigBytes)},clone:function(){for(var t=i.clone.call(this),e=t.words=this.words.slice(0),n=e.length,r=0;n>r;r++)e[r]=e[r].clone();return t}})}}(),t})},{"./core":32}],"bignumber.js":[function(t,e,n){!function(n){"use strict";function r(t){function e(t,r){var i,o,a,s,u,c,l=this;if(!(l instanceof e))return z&&D(26,"constructor call without new",t),new e(t,r);if(null!=r&&W(r,2,64,C,"base")){if(r=0|r,c=t+"",10==r)return l=new e(t instanceof e?t:c),S(l,j+l.e+1,L);if((s="number"==typeof t)&&0*t!=0||!new RegExp("^-?"+(i="["+x.slice(0,r)+"]+")+"(?:\\."+i+")?$",37>r?"i":"").test(c))return d(l,c,s,r);s?(l.s=0>1/t?(c=c.slice(1),-1):1,z&&c.replace(/^0\.0*|\./,"").length>15&&D(C,_,t),s=!1):l.s=45===c.charCodeAt(0)?(c=c.slice(1),-1):1,c=n(c,10,r,l.s)}else{if(t instanceof e)return l.s=t.s,l.e=t.e,l.c=(t=t.c)?t.slice():t,void(C=0);if((s="number"==typeof t)&&0*t==0){if(l.s=0>1/t?(t=-t,-1):1,t===~~t){for(o=0,a=t;a>=10;a/=10,o++);return l.e=o,l.c=[t],void(C=0)}c=t+""}else{if(!g.test(c=t+""))return d(l,c,s);l.s=45===c.charCodeAt(0)?(c=c.slice(1),-1):1}}for((o=c.indexOf("."))>-1&&(c=c.replace(".","")),(a=c.search(/e/i))>0?(0>o&&(o=a),o+=+c.slice(a+1),c=c.substring(0,a)):0>o&&(o=c.length),a=0;48===c.charCodeAt(a);a++);for(u=c.length;48===c.charCodeAt(--u););if(c=c.slice(a,u+1))if(u=c.length,s&&z&&u>15&&D(C,_,l.s*t),o=o-a-1,o>G)l.c=l.e=null;else if(M>o)l.c=[l.e=0];else{if(l.e=o,l.c=[],a=(o+1)%I,0>o&&(a+=I),u>a){for(a&&l.c.push(+c.slice(0,a)),u-=I;u>a;)l.c.push(+c.slice(a,a+=I));c=c.slice(a),a=I-c.length}else a-=u;for(;a--;c+="0");l.c.push(+c)}else l.c=[l.e=0];C=0}function n(t,n,r,i){var a,s,u,l,p,h,m,d=t.indexOf("."),g=j,y=L;for(37>r&&(t=t.toLowerCase()),d>=0&&(u=V,V=0,t=t.replace(".",""),m=new e(r),p=m.pow(t.length-d),V=u,m.c=c(f(o(p.c),p.e),10,n),m.e=m.c.length),h=c(t,r,n),s=u=h.length;0==h[--u];h.pop());if(!h[0])return"0";if(0>d?--s:(p.c=h,p.e=s,p.s=i,p=E(p,m,g,y,n),h=p.c,l=p.r,s=p.e),a=s+g+1,d=h[a],u=n/2,l=l||0>a||null!=h[a+1],l=4>y?(null!=d||l)&&(0==y||y==(p.s<0?3:2)):d>u||d==u&&(4==y||l||6==y&&1&h[a-1]||y==(p.s<0?8:7)),1>a||!h[0])t=l?f("1",-g):"0";else{if(h.length=a,l)for(--n;++h[--a]>n;)h[a]=0,a||(++s,h.unshift(1));for(u=h.length;!h[--u];);for(d=0,t="";u>=d;t+=x.charAt(h[d++]));t=f(t,s)}return t}function h(t,n,r,i){var a,s,u,c,p;if(r=null!=r&&W(r,0,8,i,w)?0|r:L,!t.c)return t.toString();if(a=t.c[0],u=t.e,null==n)p=o(t.c),p=19==i||24==i&&q>=u?l(p,u):f(p,u);else if(t=S(new e(t),n,r),s=t.e,p=o(t.c),c=p.length,19==i||24==i&&(s>=n||q>=s)){for(;n>c;p+="0",c++);p=l(p,s)}else if(n-=u,p=f(p,s),s+1>c){if(--n>0)for(p+=".";n--;p+="0");}else if(n+=s-c,n>0)for(s+1==c&&(p+=".");n--;p+="0");return t.s<0&&a?"-"+p:p}function k(t,n){var r,i,o=0;for(u(t[0])&&(t=t[0]),r=new e(t[0]);++ot||t>n||t!=p(t))&&D(r,(i||"decimal places")+(e>t||t>n?" out of range":" not an integer"),t),!0}function T(t,e,n){for(var r=1,i=e.length;!e[--i];e.pop());for(i=e[0];i>=10;i/=10,r++);return(n=r+n*I-1)>G?t.c=t.e=null:M>n?t.c=[t.e=0]:(t.e=n,t.c=e),t}function D(t,e,n){var r=new Error(["new BigNumber","cmp","config","div","divToInt","eq","gt","gte","lt","lte","minus","mod","plus","precision","random","round","shift","times","toDigits","toExponential","toFixed","toFormat","toFraction","pow","toPrecision","toString","BigNumber"][t]+"() "+e+": "+n);throw r.name="BigNumber Error",C=0,r}function S(t,e,n,r){var i,o,a,s,u,c,l,f=t.c,p=N;if(f){t:{for(i=1,s=f[0];s>=10;s/=10,i++);if(o=e-i,0>o)o+=I,a=e,u=f[c=0],l=u/p[i-a-1]%10|0;else if(c=y((o+1)/I),c>=f.length){if(!r)break t;for(;f.length<=c;f.push(0));u=l=0,i=1,o%=I,a=o-I+1}else{for(u=s=f[c],i=1;s>=10;s/=10,i++);o%=I,a=o-I+i,l=0>a?0:u/p[i-a-1]%10|0}if(r=r||0>e||null!=f[c+1]||(0>a?u:u%p[i-a-1]),r=4>n?(l||r)&&(0==n||n==(t.s<0?3:2)):l>5||5==l&&(4==n||r||6==n&&(o>0?a>0?u/p[i-a]:0:f[c-1])%10&1||n==(t.s<0?8:7)),1>e||!f[0])return f.length=0,r?(e-=t.e+1,f[0]=p[e%I],t.e=-e||0):f[0]=t.e=0,t;if(0==o?(f.length=c,s=1,c--):(f.length=c+1,s=p[I-o],f[c]=a>0?v(u/p[i-a]%p[a])*s:0),r)for(;;){if(0==c){for(o=1,a=f[0];a>=10;a/=10,o++);for(a=f[0]+=s,s=1;a>=10;a/=10,s++);o!=s&&(t.e++,f[0]==F&&(f[0]=1));break}if(f[c]+=s,f[c]!=F)break;f[c--]=0,s=1}for(o=f.length;0===f[--o];f.pop());}t.e>G?t.c=t.e=null:t.en?null!=(t=i[n++]):void 0};return a(e="DECIMAL_PLACES")&&W(t,0,A,2,e)&&(j=0|t),r[e]=j,a(e="ROUNDING_MODE")&&W(t,0,8,2,e)&&(L=0|t),r[e]=L,a(e="EXPONENTIAL_AT")&&(u(t)?W(t[0],-A,0,2,e)&&W(t[1],0,A,2,e)&&(q=0|t[0],U=0|t[1]):W(t,-A,A,2,e)&&(q=-(U=0|(0>t?-t:t)))),r[e]=[q,U],a(e="RANGE")&&(u(t)?W(t[0],-A,-1,2,e)&&W(t[1],1,A,2,e)&&(M=0|t[0],G=0|t[1]):W(t,-A,A,2,e)&&(0|t?M=-(G=0|(0>t?-t:t)):z&&D(2,e+" cannot be zero",t))),r[e]=[M,G],a(e="ERRORS")&&(t===!!t||1===t||0===t?(C=0,W=(z=!!t)?P:s):z&&D(2,e+b,t)),r[e]=z,a(e="CRYPTO")&&(t===!!t||1===t||0===t?(J=!(!t||!m||"object"!=typeof m),t&&!J&&z&&D(2,"crypto unavailable",m)):z&&D(2,e+b,t)),r[e]=J,a(e="MODULO_MODE")&&W(t,0,9,2,e)&&($=0|t),r[e]=$,a(e="POW_PRECISION")&&W(t,0,A,2,e)&&(V=0|t),r[e]=V,a(e="FORMAT")&&("object"==typeof t?X=t:z&&D(2,e+" not an object",t)),r[e]=X,r},e.max=function(){return k(arguments,R.lt)},e.min=function(){return k(arguments,R.gt)},e.random=function(){var t=9007199254740992,n=Math.random()*t&2097151?function(){return v(Math.random()*t)}:function(){return 8388608*(1073741824*Math.random()|0)+(8388608*Math.random()|0)};return function(t){var r,i,o,a,s,u=0,c=[],l=new e(H);if(t=null!=t&&W(t,0,A,14)?0|t:j,a=y(t/I),J)if(m&&m.getRandomValues){for(r=m.getRandomValues(new Uint32Array(a*=2));a>u;)s=131072*r[u]+(r[u+1]>>>11),s>=9e15?(i=m.getRandomValues(new Uint32Array(2)),r[u]=i[0],r[u+1]=i[1]):(c.push(s%1e14),u+=2);u=a/2}else if(m&&m.randomBytes){for(r=m.randomBytes(a*=7);a>u;)s=281474976710656*(31&r[u])+1099511627776*r[u+1]+4294967296*r[u+2]+16777216*r[u+3]+(r[u+4]<<16)+(r[u+5]<<8)+r[u+6],s>=9e15?m.randomBytes(7).copy(r,u):(c.push(s%1e14),u+=7);u=a/7}else z&&D(14,"crypto unavailable",m);if(!u)for(;a>u;)s=n(),9e15>s&&(c[u++]=s%1e14);for(a=c[--u],t%=I,a&&t&&(s=N[I-t],c[u]=v(a/s)*s);0===c[u];c.pop(),u--);if(0>u)c=[o=0];else{for(o=-1;0===c[0];c.shift(),o-=I);for(u=1,s=c[0];s>=10;s/=10,u++);I>u&&(o-=I-u)}return l.e=o,l.c=c,l}}(),E=function(){function t(t,e,n){var r,i,o,a,s=0,u=t.length,c=e%O,l=e/O|0;for(t=t.slice();u--;)o=t[u]%O,a=t[u]/O|0,r=l*o+a*c,i=c*o+r%O*O+s,s=(i/n|0)+(r/O|0)+l*a,t[u]=i%n;return s&&t.unshift(s),t}function n(t,e,n,r){var i,o;if(n!=r)o=n>r?1:-1;else for(i=o=0;n>i;i++)if(t[i]!=e[i]){o=t[i]>e[i]?1:-1;break}return o}function r(t,e,n,r){for(var i=0;n--;)t[n]-=i,i=t[n]1;t.shift());}return function(o,a,s,u,c){var l,f,p,h,m,d,g,y,b,w,_,x,B,N,O,A,k,P=o.s==a.s?1:-1,T=o.c,D=a.c;if(!(T&&T[0]&&D&&D[0]))return new e(o.s&&a.s&&(T?!D||T[0]!=D[0]:D)?T&&0==T[0]||!D?0*P:P/0:0/0);for(y=new e(P),b=y.c=[],f=o.e-a.e,P=s+f+1,c||(c=F,f=i(o.e/I)-i(a.e/I),P=P/I|0),p=0;D[p]==(T[p]||0);p++);if(D[p]>(T[p]||0)&&f--,0>P)b.push(1),h=!0;else{for(N=T.length,A=D.length,p=0,P+=2,m=v(c/(D[0]+1)),m>1&&(D=t(D,m,c),T=t(T,m,c),A=D.length,N=T.length),B=A,w=T.slice(0,A),_=w.length;A>_;w[_++]=0);k=D.slice(),k.unshift(0),O=D[0],D[1]>=c/2&&O++;do{if(m=0,l=n(D,w,A,_),0>l){if(x=w[0],A!=_&&(x=x*c+(w[1]||0)),m=v(x/O),m>1)for(m>=c&&(m=c-1),d=t(D,m,c),g=d.length,_=w.length;1==n(d,w,g,_);)m--,r(d,g>A?k:D,g,c),g=d.length,l=1;else 0==m&&(l=m=1),d=D.slice(),g=d.length;if(_>g&&d.unshift(0),r(w,d,_,c),_=w.length,-1==l)for(;n(D,w,A,_)<1;)m++,r(w,_>A?k:D,_,c),_=w.length}else 0===l&&(m++,w=[0]);b[p++]=m,w[0]?w[_++]=T[B]||0:(w=[T[B]],_=1)}while((B++=10;P/=10,p++);S(y,s+(y.e=p+f*I-1)+1,u,h)}else y.e=f,y.r=+h;return y}}(),d=function(){var t=/^(-?)0([xbo])/i,n=/^([^.]+)\.$/,r=/^\.([^.]+)$/,i=/^-?(Infinity|NaN)$/,o=/^\s*\+|^\s+|\s+$/g;return function(a,s,u,c){var l,f=u?s:s.replace(o,"");if(i.test(f))a.s=isNaN(f)?null:0>f?-1:1;else{if(!u&&(f=f.replace(t,function(t,e,n){return l="x"==(n=n.toLowerCase())?16:"b"==n?2:8,c&&c!=l?t:e}),c&&(l=c,f=f.replace(n,"$1").replace(r,"0.$1")),s!=f))return new e(f,l);z&&D(C,"not a"+(c?" base "+c:"")+" number",s),a.s=null}a.c=a.e=null,C=0}}(),R.absoluteValue=R.abs=function(){var t=new e(this);return t.s<0&&(t.s=1),t},R.ceil=function(){return S(new e(this),this.e+1,2)},R.comparedTo=R.cmp=function(t,n){return C=1,a(this,new e(t,n))},R.decimalPlaces=R.dp=function(){var t,e,n=this.c;if(!n)return null;if(t=((e=n.length-1)-i(this.e/I))*I,e=n[e])for(;e%10==0;e/=10,t--);return 0>t&&(t=0),t},R.dividedBy=R.div=function(t,n){return C=3,E(this,new e(t,n),j,L)},R.dividedToIntegerBy=R.divToInt=function(t,n){return C=4,E(this,new e(t,n),0,1)},R.equals=R.eq=function(t,n){return C=5,0===a(this,new e(t,n))},R.floor=function(){return S(new e(this),this.e+1,3)},R.greaterThan=R.gt=function(t,n){return C=6,a(this,new e(t,n))>0},R.greaterThanOrEqualTo=R.gte=function(t,n){return C=7,1===(n=a(this,new e(t,n)))||0===n},R.isFinite=function(){return!!this.c},R.isInteger=R.isInt=function(){return!!this.c&&i(this.e/I)>this.c.length-2},R.isNaN=function(){return!this.s},R.isNegative=R.isNeg=function(){return this.s<0},R.isZero=function(){return!!this.c&&0==this.c[0]},R.lessThan=R.lt=function(t,n){return C=8,a(this,new e(t,n))<0},R.lessThanOrEqualTo=R.lte=function(t,n){return C=9,-1===(n=a(this,new e(t,n)))||0===n},R.minus=R.sub=function(t,n){var r,o,a,s,u=this,c=u.s;if(C=10,t=new e(t,n),n=t.s,!c||!n)return new e(0/0);if(c!=n)return t.s=-n,u.plus(t);var l=u.e/I,f=t.e/I,p=u.c,h=t.c;if(!l||!f){if(!p||!h)return p?(t.s=-n,t):new e(h?u:0/0);if(!p[0]||!h[0])return h[0]?(t.s=-n,t):new e(p[0]?u:3==L?-0:0)}if(l=i(l),f=i(f),p=p.slice(),c=l-f){for((s=0>c)?(c=-c,a=p):(f=l,a=h),a.reverse(),n=c;n--;a.push(0));a.reverse()}else for(o=(s=(c=p.length)<(n=h.length))?c:n,c=n=0;o>n;n++)if(p[n]!=h[n]){s=p[n]0)for(;n--;p[r++]=0);for(n=F-1;o>c;){if(p[--o]0?(u=s,r=l):(a=-a,r=c),r.reverse();a--;r.push(0));r.reverse()}for(a=c.length,n=l.length,0>a-n&&(r=l,l=c,c=r,n=a),a=0;n;)a=(c[--n]=c[n]+l[n]+a)/F|0,c[n]%=F;return a&&(c.unshift(a),++u),T(t,c,u)},R.precision=R.sd=function(t){var e,n,r=this,i=r.c;if(null!=t&&t!==!!t&&1!==t&&0!==t&&(z&&D(13,"argument"+b,t),t!=!!t&&(t=null)),!i)return null;if(n=i.length-1,e=n*I+1,n=i[n]){for(;n%10==0;n/=10,e--);for(n=i[0];n>=10;n/=10,e++);}return t&&r.e+1>e&&(e=r.e+1),e},R.round=function(t,n){var r=new e(this);return(null==t||W(t,0,A,15))&&S(r,~~t+this.e+1,null!=n&&W(n,0,8,15,w)?0|n:L),r},R.shift=function(t){var n=this;return W(t,-B,B,16,"argument")?n.times("1e"+p(t)):new e(n.c&&n.c[0]&&(-B>t||t>B)?n.s*(0>t?0:1/0):n)},R.squareRoot=R.sqrt=function(){var t,n,r,a,s,u=this,c=u.c,l=u.s,f=u.e,p=j+4,h=new e("0.5");if(1!==l||!c||!c[0])return new e(!l||0>l&&(!c||c[0])?0/0:c?u:1/0);if(l=Math.sqrt(+u),0==l||l==1/0?(n=o(c),(n.length+f)%2==0&&(n+="0"),l=Math.sqrt(n),f=i((f+1)/2)-(0>f||f%2),l==1/0?n="1e"+f:(n=l.toExponential(),n=n.slice(0,n.indexOf("e")+1)+f),r=new e(n)):r=new e(l+""),r.c[0])for(f=r.e,l=f+p,3>l&&(l=0);;)if(s=r,r=h.times(s.plus(E(u,s,p,1))),o(s.c).slice(0,l)===(n=o(r.c)).slice(0,l)){if(r.el&&(g=w,w=_,_=g,a=l,l=h,h=a),a=l+h,g=[];a--;g.push(0));for(y=F,v=O,a=h;--a>=0;){for(r=0,m=_[a]%v,d=_[a]/v|0,u=l,s=a+u;s>a;)f=w[--u]%v,p=w[u]/v|0,c=d*f+p*m,f=m*f+c%v*v+g[s]+r,r=(f/y|0)+(c/v|0)+d*p,g[s--]=f%y;g[s]=r}return r?++o:g.shift(),T(t,g,o)},R.toDigits=function(t,n){var r=new e(this);return t=null!=t&&W(t,1,A,18,"precision")?0|t:null,n=null!=n&&W(n,0,8,18,w)?0|n:L,t?S(r,t,n):r},R.toExponential=function(t,e){return h(this,null!=t&&W(t,0,A,19)?~~t+1:null,e,19)},R.toFixed=function(t,e){return h(this,null!=t&&W(t,0,A,20)?~~t+this.e+1:null,e,20)},R.toFormat=function(t,e){var n=h(this,null!=t&&W(t,0,A,21)?~~t+this.e+1:null,e,21);if(this.c){var r,i=n.split("."),o=+X.groupSize,a=+X.secondaryGroupSize,s=X.groupSeparator,u=i[0],c=i[1],l=this.s<0,f=l?u.slice(1):u,p=f.length;if(a&&(r=o,o=a,a=r,p-=r),o>0&&p>0){for(r=p%o||o,u=f.substr(0,r);p>r;r+=o)u+=s+f.substr(r,o);a>0&&(u+=s+f.slice(r)),l&&(u="-"+u)}n=c?u+X.decimalSeparator+((a=+X.fractionGroupSize)?c.replace(new RegExp("\\d{"+a+"}\\B","g"),"$&"+X.fractionGroupSeparator):c):u}return n},R.toFraction=function(t){var n,r,i,a,s,u,c,l,f,p=z,h=this,m=h.c,d=new e(H),g=r=new e(H),y=c=new e(H);if(null!=t&&(z=!1,u=new e(t),z=p,(!(p=u.isInt())||u.lt(H))&&(z&&D(22,"max denominator "+(p?"out of range":"not an integer"),t),t=!p&&u.c&&S(u,u.e+1,1).gte(H)?u:null)),!m)return h.toString();for(f=o(m),a=d.e=f.length-h.e-1,d.c[0]=N[(s=a%I)<0?I+s:s],t=!t||u.cmp(d)>0?a>0?d:g:u,s=G,G=1/0,u=new e(f),c.c[0]=0;l=E(u,d,0,1),i=r.plus(l.times(y)),1!=i.cmp(t);)r=y,y=i,g=c.plus(l.times(i=g)),c=i,d=u.minus(l.times(i=d)),u=i;return i=E(t.minus(r),y,0,1),c=c.plus(i.times(g)),r=r.plus(i.times(y)),c.s=g.s=h.s,a*=2,n=E(g,y,a,L).minus(h).abs().cmp(E(c,r,a,L).minus(h).abs())<1?[g.toString(),y.toString()]:[c.toString(),r.toString()],G=s,n},R.toNumber=function(){var t=this;return+t||(t.s?0*t.s:0/0)},R.toPower=R.pow=function(t){var n,r,i=v(0>t?-t:+t),o=this;if(!W(t,-B,B,23,"exponent")&&(!isFinite(t)||i>B&&(t/=0)||parseFloat(t)!=t&&!(t=0/0)))return new e(Math.pow(+o,t));for(n=V?y(V/I+2):0,r=new e(H);;){if(i%2){if(r=r.times(o),!r.c)break;n&&r.c.length>n&&(r.c.length=n)}if(i=v(i/2),!i)break;o=o.times(o),n&&o.c&&o.c.length>n&&(o.c.length=n)}return 0>t&&(r=H.div(r)),n?S(r,V,L):r},R.toPrecision=function(t,e){return h(this,null!=t&&W(t,1,A,24,"precision")?0|t:null,e,24)},R.toString=function(t){var e,r=this,i=r.s,a=r.e;return null===a?i?(e="Infinity",0>i&&(e="-"+e)):e="NaN":(e=o(r.c),e=null!=t&&W(t,2,64,25,"base")?n(f(e,a),0|t,10,i):q>=a||a>=U?l(e,a):f(e,a),0>i&&r.c[0]&&(e="-"+e)),e},R.truncated=R.trunc=function(){return S(new e(this),this.e+1,1)},R.valueOf=R.toJSON=function(){return this.toString()},null!=t&&e.config(t),e}function i(t){var e=0|t;return t>0||t===e?e:e-1}function o(t){for(var e,n,r=1,i=t.length,o=t[0]+"";i>r;){for(e=t[r++]+"",n=I-e.length;n--;e="0"+e);o+=e}for(i=o.length;48===o.charCodeAt(--i););return o.slice(0,i+1||1)}function a(t,e){var n,r,i=t.c,o=e.c,a=t.s,s=e.s,u=t.e,c=e.e;if(!a||!s)return null;if(n=i&&!i[0],r=o&&!o[0],n||r)return n?r?0:-s:a;if(a!=s)return a;if(n=0>a,r=u==c,!i||!o)return r?0:!i^n?1:-1;if(!r)return u>c^n?1:-1;for(s=(u=i.length)<(c=o.length)?u:c,a=0;s>a;a++)if(i[a]!=o[a])return i[a]>o[a]^n?1:-1;return u==c?0:u>c^n?1:-1}function s(t,e,n){return(t=p(t))>=e&&n>=t}function u(t){return"[object Array]"==Object.prototype.toString.call(t)}function c(t,e,n){for(var r,i,o=[0],a=0,s=t.length;s>a;){for(i=o.length;i--;o[i]*=e);for(o[r=0]+=x.indexOf(t.charAt(a++));rn-1&&(null==o[r+1]&&(o[r+1]=0),o[r+1]+=o[r]/n|0,o[r]%=n)}return o.reverse()}function l(t,e){return(t.length>1?t.charAt(0)+"."+t.slice(1):t)+(0>e?"e":"e+")+e}function f(t,e){var n,r;if(0>e){for(r="0.";++e;r+="0");t=r+t}else if(n=t.length,++e>n){for(r="0",e-=n;--e;r+="0");t+=r}else n>e&&(t=t.slice(0,e)+"."+t.slice(e));return t}function p(t){return t=parseFloat(t),0>t?y(t):v(t)}var h,m,d,g=/^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,y=Math.ceil,v=Math.floor,b=" not a boolean or binary digit",w="rounding mode",_="number type has more than 15 significant digits",x="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_",F=1e14,I=14,B=9007199254740991,N=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],O=1e7,A=1e9;if(h=r(),"function"==typeof define&&define.amd)define(function(){return h});else if("undefined"!=typeof e&&e.exports){if(e.exports=h,!m)try{m=t("crypto")}catch(k){}}else n.BigNumber=h}(this)},{crypto:31}],web3:[function(t,e,n){var r=t("./lib/web3");r.providers.HttpProvider=t("./lib/web3/httpprovider"),r.providers.QtSyncProvider=t("./lib/web3/qtsync"),r.eth.contract=t("./lib/web3/contract"),r.eth.namereg=t("./lib/web3/namereg"),r.eth.sendIBANTransaction=t("./lib/web3/transfer"),"undefined"!=typeof window&&"undefined"==typeof window.web3&&(window.web3=r),e.exports=r},{"./lib/web3":9,"./lib/web3/contract":11,"./lib/web3/httpprovider":19,"./lib/web3/namereg":23,"./lib/web3/qtsync":26,"./lib/web3/transfer":29}]},{},["web3"]); \ No newline at end of file +require=function t(e,n,r){function i(a,s){if(!n[a]){if(!e[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(o)return o(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return i(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;ao;o+=64)n.push(this._outputFormatter(new a(t.dynamicPart().substr(o+64,64))));return n}return this._outputFormatter(t)},u.prototype.sliceParam=function(t,e,n){return"bytes"===this._mode?a.decodeBytes(t,e):s(n)?a.decodeArray(t,e):a.decodeParam(t,e)};var c=function(t){this._types=t};c.prototype._requireType=function(t){var e=this._types.filter(function(e){return e.isType(t)})[0];if(!e)throw Error("invalid solidity type!: "+t);return e},c.prototype._formatInput=function(t,e){return this._requireType(t).formatInput(e,s(t))},c.prototype.encodeParam=function(t,e){return this._formatInput(t,e).encode()},c.prototype.encodeParams=function(t,e){var n=this,r=t.map(function(t,r){return n._formatInput(t,e[r])});return a.encodeList(r)},c.prototype.decodeParam=function(t,e){return this.decodeParams([t],e)[0]},c.prototype.decodeParams=function(t,e){var n=this;return t.map(function(t,r){var i=n._requireType(t),o=i.sliceParam(e,r,t);return i.formatOutput(o,s(t))})};var l=new c([new u({name:"address",match:"strict",mode:"value",inputFormatter:o.formatInputInt,outputFormatter:o.formatOutputAddress}),new u({name:"bool",match:"strict",mode:"value",inputFormatter:o.formatInputBool,outputFormatter:o.formatOutputBool}),new u({name:"int",match:"prefix",mode:"value",inputFormatter:o.formatInputInt,outputFormatter:o.formatOutputInt}),new u({name:"uint",match:"prefix",mode:"value",inputFormatter:o.formatInputInt,outputFormatter:o.formatOutputUInt}),new u({name:"bytes",match:"strict",mode:"bytes",inputFormatter:o.formatInputDynamicBytes,outputFormatter:o.formatOutputDynamicBytes}),new u({name:"bytes",match:"prefix",mode:"value",inputFormatter:o.formatInputBytes,outputFormatter:o.formatOutputBytes}),new u({name:"string",match:"strict",mode:"bytes",inputFormatter:o.formatInputString,outputFormatter:o.formatOutputString}),new u({name:"real",match:"prefix",mode:"value",inputFormatter:o.formatInputReal,outputFormatter:o.formatOutputReal}),new u({name:"ureal",match:"prefix",mode:"value",inputFormatter:o.formatInputReal,outputFormatter:o.formatOutputUReal})]);e.exports=l},{"../utils/utils":7,"./formatters":2,"./param":3,"bignumber.js":"bignumber.js"}],2:[function(t,e,n){var r=t("bignumber.js"),i=t("../utils/utils"),o=t("../utils/config"),a=t("./param"),s=function(t){var e=2*o.ETH_PADDING;r.config(o.ETH_BIGNUMBER_ROUNDING_MODE);var n=i.padLeft(i.toTwosComplement(t).round().toString(16),e);return new a(n)},u=function(t){var e=i.padRight(i.toHex(t).substr(2),64);return new a(e)},c=function(t){t=i.toHex(t).substr(2);var e=Math.floor((t.length+63)/64),n=i.padRight(t,64*e),r=Math.floor(t.length/2);return new a(s(r).value+n,32)},l=function(t){var e=i.fromAscii(t).substr(2),n=Math.floor((e.length+63)/64);return e=i.padRight(e,64*n),new a(s(t.length).value+e,32)},f=function(t){var e="000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0");return new a(e)},p=function(t){return s(new r(t).times(new r(2).pow(128)))},h=function(t){return"1"===new r(t.substr(0,1),16).toString(2).substr(0,1)},m=function(t){var e=t.staticPart()||"0";return h(e)?new r(e,16).minus(new r("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new r(e,16)},d=function(t){var e=t.staticPart()||"0";return new r(e,16)},g=function(t){return m(t).dividedBy(new r(2).pow(128))},y=function(t){return d(t).dividedBy(new r(2).pow(128))},v=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t.staticPart()?!0:!1},w=function(t){return"0x"+t.staticPart()},b=function(t){var e=2*new r(t.dynamicPart().slice(0,64),16).toNumber();return"0x"+t.dynamicPart().substr(64,e)},_=function(t){var e=2*new r(t.dynamicPart().slice(0,64),16).toNumber();return i.toAscii(t.dynamicPart().substr(64,e))},x=function(t){var e=t.staticPart();return"0x"+e.slice(e.length-40,e.length)};e.exports={formatInputInt:s,formatInputBytes:u,formatInputDynamicBytes:c,formatInputString:l,formatInputBool:f,formatInputReal:p,formatOutputInt:m,formatOutputUInt:d,formatOutputReal:g,formatOutputUReal:y,formatOutputBool:v,formatOutputBytes:w,formatOutputDynamicBytes:b,formatOutputString:_,formatOutputAddress:x}},{"../utils/config":5,"../utils/utils":7,"./param":3,"bignumber.js":"bignumber.js"}],3:[function(t,e,n){var r=t("../utils/utils"),i=function(t,e){this.value=t||"",this.offset=e};i.prototype.dynamicPartLength=function(){return this.dynamicPart().length/2},i.prototype.withOffset=function(t){return new i(this.value,t)},i.prototype.combine=function(t){return new i(this.value+t.value)},i.prototype.isDynamic=function(){return this.value.length>64||void 0!==this.offset},i.prototype.offsetAsBytes=function(){return this.isDynamic()?r.padLeft(r.toTwosComplement(this.offset).toString(16),64):""},i.prototype.staticPart=function(){return this.isDynamic()?this.offsetAsBytes():this.value},i.prototype.dynamicPart=function(){return this.isDynamic()?this.value:""},i.prototype.encode=function(){return this.staticPart()+this.dynamicPart()},i.encodeList=function(t){var e=32*t.length,n=t.map(function(t){if(!t.isDynamic())return t;var n=e;return e+=t.dynamicPartLength(),t.withOffset(n)});return n.reduce(function(t,e){return t+e.dynamicPart()},n.reduce(function(t,e){return t+e.staticPart()},""))},i.decodeParam=function(t,e){return e=e||0,new i(t.substr(64*e,64))};var o=function(t,e){return parseInt("0x"+t.substr(64*e,64))};i.decodeBytes=function(t,e){e=e||0;var n=o(t,e),r=parseInt("0x"+t.substr(2*n,64));return r=Math.floor((r+31)/32),new i(t.substr(2*n,64*(1+r)),0)},i.decodeArray=function(t,e){e=e||0;var n=o(t,e),r=parseInt("0x"+t.substr(2*n,64));return new i(t.substr(2*n,64*(r+1)),0)},e.exports=i},{"../utils/utils":7}],4:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],5:[function(t,e,n){var r=t("bignumber.js"),i=["wei","kwei","Mwei","Gwei","szabo","finney","femtoether","picoether","nanoether","microether","milliether","nano","micro","milli","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:i,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:r.ROUND_DOWN},ETH_POLLING_TIMEOUT:500,defaultBlock:"latest",defaultAccount:void 0}},{"bignumber.js":"bignumber.js"}],6:[function(t,e,n){var r=t("./utils"),i=t("crypto-js/sha3");e.exports=function(t,e){return"0x"!==t.substr(0,2)||e||(console.warn("requirement of using web3.fromAscii before sha3 is deprecated"),console.warn("new usage: 'web3.sha3(\"hello\")'"),console.warn("see https://github.com/ethereum/web3.js/pull/205"),console.warn("if you need to hash hex value, you can do 'sha3(\"0xfff\", true)'"),t=r.toAscii(t)),i(t,{outputLength:256}).toString()}},{"./utils":7,"crypto-js/sha3":34}],7:[function(t,e,n){var r=t("bignumber.js"),i={wei:"1",kwei:"1000",ada:"1000",femtoether:"1000",mwei:"1000000",babbage:"1000000",picoether:"1000000",gwei:"1000000000",shannon:"1000000000",nanoether:"1000000000",nano:"1000000000",szabo:"1000000000000",microether:"1000000000000",micro:"1000000000000",finney:"1000000000000000",milliether:"1000000000000000",milli:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},o=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},a=function(t,e,n){return t+new Array(e-t.length+1).join(n?n:"0")},s=function(t){var e="",n=0,r=t.length;for("0x"===t.substring(0,2)&&(n=2);r>n;n+=2){var i=parseInt(t.substr(n,2),16);e+=String.fromCharCode(i)}return e},u=function(t){for(var e="",n=0;n0&&c(i),r)return i.watch(r)})};l.prototype.watch=function(t){return this.callbacks.push(t),this.filterId&&(u(this,t),c(this)),this},l.prototype.stopWatching=function(){r.getInstance().stopPolling(this.filterId),this.implementation.uninstallFilter(this.filterId,function(){}),this.callbacks=[]},l.prototype.get=function(t){var e=this;if(!o.isFunction(t)){var n=this.implementation.getLogs(this.filterId);return n.map(function(t){return e.formatter?e.formatter(t):t})}return this.implementation.getLogs(this.filterId,function(n,r){n?t(n):t(null,r.map(function(t){return e.formatter?e.formatter(t):t}))}),this},e.exports=l},{"../utils/utils":7,"./formatters":18,"./requestmanager":28}],18:[function(t,e,n){var r=t("../utils/utils"),i=t("../utils/config"),o=function(t){return r.toBigNumber(t)},a=function(t){return"latest"===t||"pending"===t||"earliest"===t},s=function(t){return void 0===t?i.defaultBlock:u(t)},u=function(t){return void 0===t?void 0:a(t)?t:r.toHex(t)},c=function(t){return t.from=t.from||i.defaultAccount,t.code&&(t.data=t.code,delete t.code),["gasPrice","gas","value","nonce"].filter(function(e){return void 0!==t[e]}).forEach(function(e){t[e]=r.fromDecimal(t[e])}),t},l=function(t){return null!==t.blockNumber&&(t.blockNumber=r.toDecimal(t.blockNumber)),null!==t.transactionIndex&&(t.transactionIndex=r.toDecimal(t.transactionIndex)),t.nonce=r.toDecimal(t.nonce),t.gas=r.toDecimal(t.gas),t.gasPrice=r.toBigNumber(t.gasPrice),t.value=r.toBigNumber(t.value),t},f=function(t){return t.gasLimit=r.toDecimal(t.gasLimit),t.gasUsed=r.toDecimal(t.gasUsed),t.size=r.toDecimal(t.size),t.timestamp=r.toDecimal(t.timestamp),null!==t.number&&(t.number=r.toDecimal(t.number)),t.difficulty=r.toBigNumber(t.difficulty),t.totalDifficulty=r.toBigNumber(t.totalDifficulty),r.isArray(t.transactions)&&t.transactions.forEach(function(t){return r.isString(t)?void 0:l(t)}),t},p=function(t){return null!==t.blockNumber&&(t.blockNumber=r.toDecimal(t.blockNumber)),null!==t.transactionIndex&&(t.transactionIndex=r.toDecimal(t.transactionIndex)),null!==t.logIndex&&(t.logIndex=r.toDecimal(t.logIndex)),t},h=function(t){return t.payload=r.toHex(t.payload),t.ttl=r.fromDecimal(t.ttl),t.workToProve=r.fromDecimal(t.workToProve),t.priority=r.fromDecimal(t.priority),r.isArray(t.topics)||(t.topics=t.topics?[t.topics]:[]),t.topics=t.topics.map(function(t){return r.fromAscii(t)}),t},m=function(t){return t.expiry=r.toDecimal(t.expiry),t.sent=r.toDecimal(t.sent),t.ttl=r.toDecimal(t.ttl),t.workProved=r.toDecimal(t.workProved),t.payloadRaw=t.payload,t.payload=r.toAscii(t.payload),r.isJson(t.payload)&&(t.payload=JSON.parse(t.payload)),t.topics||(t.topics=[]),t.topics=t.topics.map(function(t){return r.toAscii(t)}),t};e.exports={inputDefaultBlockNumberFormatter:s,inputBlockNumberFormatter:u,inputTransactionFormatter:c,inputPostFormatter:h,outputBigNumberFormatter:o,outputTransactionFormatter:l,outputBlockFormatter:f,outputLogFormatter:p,outputPostFormatter:m}},{"../utils/config":5,"../utils/utils":7}],19:[function(t,e,n){var r=t("../web3"),i=t("../solidity/coder"),o=t("../utils/utils"),a=t("./formatters"),s=t("../utils/sha3"),u=function(t,e){this._inputTypes=t.inputs.map(function(t){return t.type}),this._outputTypes=t.outputs.map(function(t){return t.type}),this._constant=t.constant,this._name=o.transformToFullName(t),this._address=e};u.prototype.extractCallback=function(t){return o.isFunction(t[t.length-1])?t.pop():void 0},u.prototype.extractDefaultBlock=function(t){return t.length>this._inputTypes.length&&!o.isObject(t[t.length-1])?a.inputDefaultBlockNumberFormatter(t.pop()):void 0},u.prototype.toPayload=function(t){var e={};return t.length>this._inputTypes.length&&o.isObject(t[t.length-1])&&(e=t[t.length-1]),e.to=this._address,e.data="0x"+this.signature()+i.encodeParams(this._inputTypes,t),e},u.prototype.signature=function(){return s(this._name).slice(0,8)},u.prototype.unpackOutput=function(t){if(t){t=t.length>=2?t.slice(2):t;var e=i.decodeParams(this._outputTypes,t);return 1===e.length?e[0]:e}},u.prototype.call=function(){var t=Array.prototype.slice.call(arguments).filter(function(t){return void 0!==t}),e=this.extractCallback(t),n=this.extractDefaultBlock(t),i=this.toPayload(t);if(!e){var o=r.eth.call(i,n);return this.unpackOutput(o)}var a=this;r.eth.call(i,n,function(t,n){e(t,a.unpackOutput(n))})},u.prototype.sendTransaction=function(){var t=Array.prototype.slice.call(arguments).filter(function(t){return void 0!==t}),e=this.extractCallback(t),n=this.toPayload(t);return e?void r.eth.sendTransaction(n,e):r.eth.sendTransaction(n)},u.prototype.estimateGas=function(){var t=Array.prototype.slice.call(arguments),e=this.extractCallback(t),n=this.toPayload(t);return e?void r.eth.estimateGas(n,e):r.eth.estimateGas(n)},u.prototype.displayName=function(){return o.extractDisplayName(this._name)},u.prototype.typeName=function(){return o.extractTypeName(this._name)},u.prototype.request=function(){var t=Array.prototype.slice.call(arguments),e=this.extractCallback(t),n=this.toPayload(t),r=this.unpackOutput.bind(this);return{method:this._constant?"eth_call":"eth_sendTransaction",callback:e,params:[n],format:r}},u.prototype.execute=function(){var t=!this._constant;return t?this.sendTransaction.apply(this,Array.prototype.slice.call(arguments)):this.call.apply(this,Array.prototype.slice.call(arguments))},u.prototype.attachToContract=function(t){var e=this.execute.bind(this);e.request=this.request.bind(this),e.call=this.call.bind(this),e.sendTransaction=this.sendTransaction.bind(this),e.estimateGas=this.estimateGas.bind(this);var n=this.displayName();t[n]||(t[n]=e),t[n][this.typeName()]=e},e.exports=u},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9,"./formatters":18}],20:[function(t,e,n){"use strict";var r="undefined"!=typeof window&&window.XMLHttpRequest?window.XMLHttpRequest:t("xmlhttprequest").XMLHttpRequest,i=t("./errors"),o=function(t){this.host=t||"http://localhost:8545"};o.prototype.send=function(t){var e=new r;e.open("POST",this.host,!1),e.setRequestHeader("Content-type","application/json");try{e.send(JSON.stringify(t))}catch(n){throw i.InvalidConnection(this.host)}var o=e.responseText;try{o=JSON.parse(o)}catch(a){throw i.InvalidResponse(o)}return o},o.prototype.sendAsync=function(t,e){var n=new r;n.onreadystatechange=function(){if(4===n.readyState){var t=n.responseText,r=null;try{t=JSON.parse(t)}catch(o){r=i.InvalidResponse(t)}e(r,t)}},n.open("POST",this.host,!0),n.setRequestHeader("Content-type","application/json");try{n.send(JSON.stringify(t))}catch(o){e(i.InvalidConnection(this.host))}},e.exports=o},{"./errors":14,xmlhttprequest:4}],21:[function(t,e,n){var r=t("../utils/utils"),i=function(t){this._iban=t};i.prototype.isValid=function(){return r.isIBAN(this._iban)},i.prototype.isDirect=function(){return 34===this._iban.length},i.prototype.isIndirect=function(){return 20===this._iban.length},i.prototype.checksum=function(){return this._iban.substr(2,2)},i.prototype.institution=function(){return this.isIndirect()?this._iban.substr(7,4):""},i.prototype.client=function(){return this.isIndirect()?this._iban.substr(11):""},i.prototype.address=function(){return this.isDirect()?this._iban.substr(4):""},e.exports=i},{"../utils/utils":7}],22:[function(t,e,n){var r=function(){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,void(this.messageId=1))};r.getInstance=function(){var t=new r;return t},r.prototype.toPayload=function(t,e){return t||console.error("jsonrpc method should be specified!"),{jsonrpc:"2.0",method:t,params:e||[],id:this.messageId++ +}},r.prototype.isValidResponse=function(t){return!!t&&!t.error&&"2.0"===t.jsonrpc&&"number"==typeof t.id&&void 0!==t.result},r.prototype.toBatchPayload=function(t){var e=this;return t.map(function(t){return e.toPayload(t.method,t.params)})},e.exports=r},{}],23:[function(t,e,n){var r=t("./requestmanager"),i=t("../utils/utils"),o=t("./errors"),a=function(t){this.name=t.name,this.call=t.call,this.params=t.params||0,this.inputFormatter=t.inputFormatter,this.outputFormatter=t.outputFormatter};a.prototype.getCall=function(t){return i.isFunction(this.call)?this.call(t):this.call},a.prototype.extractCallback=function(t){return i.isFunction(t[t.length-1])?t.pop():void 0},a.prototype.validateArgs=function(t){if(t.length!==this.params)throw o.InvalidNumberOfParams()},a.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter.map(function(e,n){return e?e(t[n]):t[n]}):t},a.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},a.prototype.attachToObject=function(t){var e=this.send.bind(this);e.request=this.request.bind(this),e.call=this.call;var n=this.name.split(".");n.length>1?(t[n[0]]=t[n[0]]||{},t[n[0]][n[1]]=e):t[n[0]]=e},a.prototype.toPayload=function(t){var e=this.getCall(t),n=this.extractCallback(t),r=this.formatInput(t);return this.validateArgs(r),{method:e,params:r,callback:n}},a.prototype.request=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));return t.format=this.formatOutput.bind(this),t},a.prototype.send=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));if(t.callback){var e=this;return r.getInstance().sendAsync(t,function(n,r){t.callback(n,e.formatOutput(r))})}return this.formatOutput(r.getInstance().send(t))},e.exports=a},{"../utils/utils":7,"./errors":14,"./requestmanager":28}],24:[function(t,e,n){var r=t("./contract"),i="0xc6d9d2cd449a754c494264e1809c50e34d64562b",o=[{constant:!0,inputs:[{name:"_owner",type:"address"}],name:"name",outputs:[{name:"o_name",type:"bytes32"}],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"owner",outputs:[{name:"",type:"address"}],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"content",outputs:[{name:"",type:"bytes32"}],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"addr",outputs:[{name:"",type:"address"}],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"}],name:"reserve",outputs:[],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"subRegistrar",outputs:[{name:"o_subRegistrar",type:"address"}],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_newOwner",type:"address"}],name:"transfer",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_registrar",type:"address"}],name:"setSubRegistrar",outputs:[],type:"function"},{constant:!1,inputs:[],name:"Registrar",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_a",type:"address"},{name:"_primary",type:"bool"}],name:"setAddress",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"},{name:"_content",type:"bytes32"}],name:"setContent",outputs:[],type:"function"},{constant:!1,inputs:[{name:"_name",type:"bytes32"}],name:"disown",outputs:[],type:"function"},{constant:!0,inputs:[{name:"_name",type:"bytes32"}],name:"register",outputs:[{name:"",type:"address"}],type:"function"},{anonymous:!1,inputs:[{indexed:!0,name:"name",type:"bytes32"}],name:"Changed",type:"event"},{anonymous:!1,inputs:[{indexed:!0,name:"name",type:"bytes32"},{indexed:!0,name:"addr",type:"address"}],name:"PrimaryChanged",type:"event"}];e.exports=r(o).at(i)},{"./contract":12}],25:[function(t,e,n){var r=t("../utils/utils"),i=t("./property"),o=[],a=[new i({name:"listening",getter:"net_listening"}),new i({name:"peerCount",getter:"net_peerCount",outputFormatter:r.toDecimal})];e.exports={methods:o,properties:a}},{"../utils/utils":7,"./property":26}],26:[function(t,e,n){var r=t("./requestmanager"),i=function(t){this.name=t.name,this.getter=t.getter,this.setter=t.setter,this.outputFormatter=t.outputFormatter,this.inputFormatter=t.inputFormatter};i.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter(t):t},i.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},i.prototype.attachToObject=function(t){var e={get:this.get.bind(this)},n=this.name.split("."),r=n[0];n.length>1&&(t[n[0]]=t[n[0]]||{},t=t[n[0]],r=n[1]),Object.defineProperty(t,r,e);var i=function(t,e){return t+e.charAt(0).toUpperCase()+e.slice(1)};t[i("get",r)]=this.getAsync.bind(this)},i.prototype.get=function(){return this.formatOutput(r.getInstance().send({method:this.getter}))},i.prototype.getAsync=function(t){var e=this;r.getInstance().sendAsync({method:this.getter},function(n,r){return n?t(n):void t(n,e.formatOutput(r))})},e.exports=i},{"./requestmanager":28}],27:[function(t,e,n){var r=function(){};r.prototype.send=function(t){var e=navigator.qt.callMethod(JSON.stringify(t));return JSON.parse(e)},e.exports=r},{}],28:[function(t,e,n){var r=t("./jsonrpc"),i=t("../utils/utils"),o=t("../utils/config"),a=t("./errors"),s=function(t){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,this.provider=t,this.polls={},this.timeout=null,void(this.isPolling=!1))};s.getInstance=function(){var t=new s;return t},s.prototype.send=function(t){if(!this.provider)return console.error(a.InvalidProvider()),null;var e=r.getInstance().toPayload(t.method,t.params),n=this.provider.send(e);if(!r.getInstance().isValidResponse(n))throw a.InvalidResponse(n);return n.result},s.prototype.sendAsync=function(t,e){if(!this.provider)return e(a.InvalidProvider());var n=r.getInstance().toPayload(t.method,t.params);this.provider.sendAsync(n,function(t,n){return t?e(t):r.getInstance().isValidResponse(n)?void e(null,n.result):e(a.InvalidResponse(n))})},s.prototype.sendBatch=function(t,e){if(!this.provider)return e(a.InvalidProvider());var n=r.getInstance().toBatchPayload(t);this.provider.sendAsync(n,function(t,n){return t?e(t):i.isArray(n)?void e(t,n):e(a.InvalidResponse(n))})},s.prototype.setProvider=function(t){this.provider=t,this.provider&&!this.isPolling&&(this.poll(),this.isPolling=!0)},s.prototype.startPolling=function(t,e,n,r){this.polls["poll_"+e]={data:t,id:e,callback:n,uninstall:r}},s.prototype.stopPolling=function(t){delete this.polls["poll_"+t]},s.prototype.reset=function(){for(var t in this.polls)this.polls[t].uninstall();this.polls={},this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.poll()},s.prototype.poll=function(){if(this.timeout=setTimeout(this.poll.bind(this),o.ETH_POLLING_TIMEOUT),0!==Object.keys(this.polls).length){if(!this.provider)return void console.error(a.InvalidProvider());var t=[],e=[];for(var n in this.polls)t.push(this.polls[n].data),e.push(n);if(0!==t.length){var s=r.getInstance().toBatchPayload(t),u=this;this.provider.sendAsync(s,function(t,n){if(!t){if(!i.isArray(n))throw a.InvalidResponse(n);n.map(function(t,n){var r=e[n];return u.polls[r]?(t.callback=u.polls[r].callback,t):!1}).filter(function(t){return!!t}).filter(function(t){var e=r.getInstance().isValidResponse(t);return e||t.callback(a.InvalidResponse(t)),e}).filter(function(t){return i.isArray(t.result)&&t.result.length>0}).forEach(function(t){t.callback(null,t.result)})}})}}},e.exports=s},{"../utils/config":5,"../utils/utils":7,"./errors":14,"./jsonrpc":22}],29:[function(t,e,n){var r=t("./method"),i=t("./formatters"),o=new r({name:"post",call:"shh_post",params:1,inputFormatter:[i.inputPostFormatter]}),a=new r({name:"newIdentity",call:"shh_newIdentity",params:0}),s=new r({name:"hasIdentity",call:"shh_hasIdentity",params:1}),u=new r({name:"newGroup",call:"shh_newGroup",params:0}),c=new r({name:"addToGroup",call:"shh_addToGroup",params:0}),l=[o,a,s,u,c];e.exports={methods:l}},{"./formatters":18,"./method":23}],30:[function(t,e,n){var r=t("../web3"),i=t("./icap"),o=t("./namereg"),a=t("./contract"),s=function(t,e,n,r){var a=new i(e);if(!a.isValid())throw new Error("invalid iban address");if(a.isDirect())return u(t,a.address(),n,r);if(!r){var s=o.addr(a.institution());return c(t,s,n,a.client())}o.addr(a.insitution(),function(e,i){return c(t,i,n,a.client(),r)})},u=function(t,e,n,i){return r.eth.sendTransaction({address:e,from:t,value:n},i)},c=function(t,e,n,r,i){var o=[{constant:!1,inputs:[{name:"name",type:"bytes32"}],name:"deposit",outputs:[],type:"function"}];return a(o).at(e).deposit(r,{from:t,value:n},i)};e.exports=s},{"../web3":9,"./contract":12,"./icap":21,"./namereg":24}],31:[function(t,e,n){var r=t("./method"),i=function(){var t=function(t){var e=t[0];switch(e){case"latest":return t.shift(),this.params=0,"eth_newBlockFilter";case"pending":return t.shift(),this.params=0,"eth_newPendingTransactionFilter";default:return"eth_newFilter"}},e=new r({name:"newFilter",call:t,params:1}),n=new r({name:"uninstallFilter",call:"eth_uninstallFilter",params:1}),i=new r({name:"getLogs",call:"eth_getFilterLogs",params:1}),o=new r({name:"poll",call:"eth_getFilterChanges",params:1});return[e,n,i,o]},o=function(){var t=new r({name:"newFilter",call:"shh_newFilter",params:1}),e=new r({name:"uninstallFilter",call:"shh_uninstallFilter",params:1}),n=new r({name:"getLogs",call:"shh_getMessages",params:1}),i=new r({name:"poll",call:"shh_getFilterChanges",params:1});return[t,e,n,i]};e.exports={eth:i,shh:o}},{"./method":23}],32:[function(t,e,n){},{}],33:[function(t,e,n){!function(t,r){"object"==typeof n?e.exports=n=r():"function"==typeof define&&define.amd?define([],r):t.CryptoJS=r()}(this,function(){var t=t||function(t,e){var n={},r=n.lib={},i=r.Base=function(){function t(){}return{extend:function(e){t.prototype=this;var n=new t;return e&&n.mixIn(e),n.hasOwnProperty("init")||(n.init=function(){n.$super.init.apply(this,arguments)}),n.init.prototype=n,n.$super=this,n},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}}}(),o=r.WordArray=i.extend({init:function(t,n){t=this.words=t||[],this.sigBytes=n!=e?n:4*t.length},toString:function(t){return(t||s).stringify(this)},concat:function(t){var e=this.words,n=t.words,r=this.sigBytes,i=t.sigBytes;if(this.clamp(),r%4)for(var o=0;i>o;o++){var a=n[o>>>2]>>>24-o%4*8&255;e[r+o>>>2]|=a<<24-(r+o)%4*8}else for(var o=0;i>o;o+=4)e[r+o>>>2]=n[o>>>2];return this.sigBytes+=i,this},clamp:function(){var e=this.words,n=this.sigBytes;e[n>>>2]&=4294967295<<32-n%4*8,e.length=t.ceil(n/4)},clone:function(){var t=i.clone.call(this);return t.words=this.words.slice(0),t},random:function(e){for(var n,r=[],i=function(e){var e=e,n=987654321,r=4294967295;return function(){n=36969*(65535&n)+(n>>16)&r,e=18e3*(65535&e)+(e>>16)&r;var i=(n<<16)+e&r;return i/=4294967296,i+=.5,i*(t.random()>.5?1:-1)}},a=0;e>a;a+=4){var s=i(4294967296*(n||t.random()));n=987654071*s(),r.push(4294967296*s()|0)}return new o.init(r,e)}}),a=n.enc={},s=a.Hex={stringify:function(t){for(var e=t.words,n=t.sigBytes,r=[],i=0;n>i;i++){var o=e[i>>>2]>>>24-i%4*8&255;r.push((o>>>4).toString(16)),r.push((15&o).toString(16))}return r.join("")},parse:function(t){for(var e=t.length,n=[],r=0;e>r;r+=2)n[r>>>3]|=parseInt(t.substr(r,2),16)<<24-r%8*4;return new o.init(n,e/2)}},u=a.Latin1={stringify:function(t){for(var e=t.words,n=t.sigBytes,r=[],i=0;n>i;i++){var o=e[i>>>2]>>>24-i%4*8&255;r.push(String.fromCharCode(o))}return r.join("")},parse:function(t){for(var e=t.length,n=[],r=0;e>r;r++)n[r>>>2]|=(255&t.charCodeAt(r))<<24-r%4*8;return new o.init(n,e)}},c=a.Utf8={stringify:function(t){try{return decodeURIComponent(escape(u.stringify(t)))}catch(e){throw new Error("Malformed UTF-8 data")}},parse:function(t){return u.parse(unescape(encodeURIComponent(t)))}},l=r.BufferedBlockAlgorithm=i.extend({reset:function(){this._data=new o.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=c.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(e){var n=this._data,r=n.words,i=n.sigBytes,a=this.blockSize,s=4*a,u=i/s;u=e?t.ceil(u):t.max((0|u)-this._minBufferSize,0);var c=u*a,l=t.min(4*c,i);if(c){for(var f=0;c>f;f+=a)this._doProcessBlock(r,f);var p=r.splice(0,c);n.sigBytes-=l}return new o.init(p,l)},clone:function(){var t=i.clone.call(this);return t._data=this._data.clone(),t},_minBufferSize:0}),f=(r.Hasher=l.extend({cfg:i.extend(),init:function(t){this.cfg=this.cfg.extend(t),this.reset()},reset:function(){l.reset.call(this),this._doReset()},update:function(t){return this._append(t),this._process(),this},finalize:function(t){t&&this._append(t);var e=this._doFinalize();return e},blockSize:16,_createHelper:function(t){return function(e,n){return new t.init(n).finalize(e)}},_createHmacHelper:function(t){return function(e,n){return new f.HMAC.init(t,n).finalize(e)}}}),n.algo={});return n}(Math);return t})},{}],34:[function(t,e,n){!function(r,i,o){"object"==typeof n?e.exports=n=i(t("./core"),t("./x64-core")):"function"==typeof define&&define.amd?define(["./core","./x64-core"],i):i(r.CryptoJS)}(this,function(t){return function(e){var n=t,r=n.lib,i=r.WordArray,o=r.Hasher,a=n.x64,s=a.Word,u=n.algo,c=[],l=[],f=[];!function(){for(var t=1,e=0,n=0;24>n;n++){c[t+5*e]=(n+1)*(n+2)/2%64;var r=e%5,i=(2*t+3*e)%5;t=r,e=i}for(var t=0;5>t;t++)for(var e=0;5>e;e++)l[t+5*e]=e+(2*t+3*e)%5*5;for(var o=1,a=0;24>a;a++){for(var u=0,p=0,h=0;7>h;h++){if(1&o){var m=(1<m?p^=1<t;t++)p[t]=s.create()}();var h=u.SHA3=o.extend({cfg:o.cfg.extend({outputLength:512}),_doReset:function(){for(var t=this._state=[],e=0;25>e;e++)t[e]=new s.init;this.blockSize=(1600-2*this.cfg.outputLength)/32},_doProcessBlock:function(t,e){for(var n=this._state,r=this.blockSize/2,i=0;r>i;i++){var o=t[e+2*i],a=t[e+2*i+1];o=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),a=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8);var s=n[i];s.high^=a,s.low^=o}for(var u=0;24>u;u++){for(var h=0;5>h;h++){for(var m=0,d=0,g=0;5>g;g++){var s=n[h+5*g];m^=s.high,d^=s.low}var y=p[h];y.high=m,y.low=d}for(var h=0;5>h;h++)for(var v=p[(h+4)%5],w=p[(h+1)%5],b=w.high,_=w.low,m=v.high^(b<<1|_>>>31),d=v.low^(_<<1|b>>>31),g=0;5>g;g++){var s=n[h+5*g];s.high^=m,s.low^=d}for(var x=1;25>x;x++){var s=n[x],F=s.high,I=s.low,B=c[x];if(32>B)var m=F<>>32-B,d=I<>>32-B;else var m=I<>>64-B,d=F<>>64-B;var N=p[l[x]];N.high=m,N.low=d}var O=p[0],k=n[0];O.high=k.high,O.low=k.low;for(var h=0;5>h;h++)for(var g=0;5>g;g++){var x=h+5*g,s=n[x],A=p[x],P=p[(h+1)%5+5*g],T=p[(h+2)%5+5*g];s.high=A.high^~P.high&T.high,s.low=A.low^~P.low&T.low}var s=n[0],D=f[u];s.high^=D.high,s.low^=D.low}},_doFinalize:function(){var t=this._data,n=t.words,r=(8*this._nDataBytes,8*t.sigBytes),o=32*this.blockSize;n[r>>>5]|=1<<24-r%32,n[(e.ceil((r+1)/o)*o>>>5)-1]|=128,t.sigBytes=4*n.length,this._process();for(var a=this._state,s=this.cfg.outputLength/8,u=s/8,c=[],l=0;u>l;l++){var f=a[l],p=f.high,h=f.low;p=16711935&(p<<8|p>>>24)|4278255360&(p<<24|p>>>8),h=16711935&(h<<8|h>>>24)|4278255360&(h<<24|h>>>8),c.push(h),c.push(p)}return new i.init(c,s)},clone:function(){for(var t=o.clone.call(this),e=t._state=this._state.slice(0),n=0;25>n;n++)e[n]=e[n].clone();return t}});n.SHA3=o._createHelper(h),n.HmacSHA3=o._createHmacHelper(h)}(Math),t.SHA3})},{"./core":33,"./x64-core":35}],35:[function(t,e,n){!function(r,i){"object"==typeof n?e.exports=n=i(t("./core")):"function"==typeof define&&define.amd?define(["./core"],i):i(r.CryptoJS)}(this,function(t){return function(e){{var n=t,r=n.lib,i=r.Base,o=r.WordArray,a=n.x64={};a.Word=i.extend({init:function(t,e){this.high=t,this.low=e}}),a.WordArray=i.extend({init:function(t,n){t=this.words=t||[],this.sigBytes=n!=e?n:8*t.length},toX32:function(){for(var t=this.words,e=t.length,n=[],r=0;e>r;r++){var i=t[r];n.push(i.high),n.push(i.low)}return o.create(n,this.sigBytes)},clone:function(){for(var t=i.clone.call(this),e=t.words=this.words.slice(0),n=e.length,r=0;n>r;r++)e[r]=e[r].clone();return t}})}}(),t})},{"./core":33}],"bignumber.js":[function(t,e,n){!function(n){"use strict";function r(t){function e(t,r){var i,o,a,s,u,c,l=this;if(!(l instanceof e))return z&&D(26,"constructor call without new",t),new e(t,r);if(null!=r&&W(r,2,64,C,"base")){if(r=0|r,c=t+"",10==r)return l=new e(t instanceof e?t:c),S(l,j+l.e+1,L);if((s="number"==typeof t)&&0*t!=0||!new RegExp("^-?"+(i="["+x.slice(0,r)+"]+")+"(?:\\."+i+")?$",37>r?"i":"").test(c))return d(l,c,s,r);s?(l.s=0>1/t?(c=c.slice(1),-1):1,z&&c.replace(/^0\.0*|\./,"").length>15&&D(C,_,t),s=!1):l.s=45===c.charCodeAt(0)?(c=c.slice(1),-1):1,c=n(c,10,r,l.s)}else{if(t instanceof e)return l.s=t.s,l.e=t.e,l.c=(t=t.c)?t.slice():t,void(C=0);if((s="number"==typeof t)&&0*t==0){if(l.s=0>1/t?(t=-t,-1):1,t===~~t){for(o=0,a=t;a>=10;a/=10,o++);return l.e=o,l.c=[t],void(C=0)}c=t+""}else{if(!g.test(c=t+""))return d(l,c,s);l.s=45===c.charCodeAt(0)?(c=c.slice(1),-1):1}}for((o=c.indexOf("."))>-1&&(c=c.replace(".","")),(a=c.search(/e/i))>0?(0>o&&(o=a),o+=+c.slice(a+1),c=c.substring(0,a)):0>o&&(o=c.length),a=0;48===c.charCodeAt(a);a++);for(u=c.length;48===c.charCodeAt(--u););if(c=c.slice(a,u+1))if(u=c.length,s&&z&&u>15&&D(C,_,l.s*t),o=o-a-1,o>G)l.c=l.e=null;else if(M>o)l.c=[l.e=0];else{if(l.e=o,l.c=[],a=(o+1)%I,0>o&&(a+=I),u>a){for(a&&l.c.push(+c.slice(0,a)),u-=I;u>a;)l.c.push(+c.slice(a,a+=I));c=c.slice(a),a=I-c.length}else a-=u;for(;a--;c+="0");l.c.push(+c)}else l.c=[l.e=0];C=0}function n(t,n,r,i){var a,s,u,l,p,h,m,d=t.indexOf("."),g=j,y=L;for(37>r&&(t=t.toLowerCase()),d>=0&&(u=V,V=0,t=t.replace(".",""),m=new e(r),p=m.pow(t.length-d),V=u,m.c=c(f(o(p.c),p.e),10,n),m.e=m.c.length),h=c(t,r,n),s=u=h.length;0==h[--u];h.pop());if(!h[0])return"0";if(0>d?--s:(p.c=h,p.e=s,p.s=i,p=R(p,m,g,y,n),h=p.c,l=p.r,s=p.e),a=s+g+1,d=h[a],u=n/2,l=l||0>a||null!=h[a+1],l=4>y?(null!=d||l)&&(0==y||y==(p.s<0?3:2)):d>u||d==u&&(4==y||l||6==y&&1&h[a-1]||y==(p.s<0?8:7)),1>a||!h[0])t=l?f("1",-g):"0";else{if(h.length=a,l)for(--n;++h[--a]>n;)h[a]=0,a||(++s,h.unshift(1));for(u=h.length;!h[--u];);for(d=0,t="";u>=d;t+=x.charAt(h[d++]));t=f(t,s)}return t}function h(t,n,r,i){var a,s,u,c,p;if(r=null!=r&&W(r,0,8,i,b)?0|r:L,!t.c)return t.toString();if(a=t.c[0],u=t.e,null==n)p=o(t.c),p=19==i||24==i&&q>=u?l(p,u):f(p,u);else if(t=S(new e(t),n,r),s=t.e,p=o(t.c),c=p.length,19==i||24==i&&(s>=n||q>=s)){for(;n>c;p+="0",c++);p=l(p,s)}else if(n-=u,p=f(p,s),s+1>c){if(--n>0)for(p+=".";n--;p+="0");}else if(n+=s-c,n>0)for(s+1==c&&(p+=".");n--;p+="0");return t.s<0&&a?"-"+p:p}function A(t,n){var r,i,o=0;for(u(t[0])&&(t=t[0]),r=new e(t[0]);++ot||t>n||t!=p(t))&&D(r,(i||"decimal places")+(e>t||t>n?" out of range":" not an integer"),t),!0}function T(t,e,n){for(var r=1,i=e.length;!e[--i];e.pop());for(i=e[0];i>=10;i/=10,r++);return(n=r+n*I-1)>G?t.c=t.e=null:M>n?t.c=[t.e=0]:(t.e=n,t.c=e),t}function D(t,e,n){var r=new Error(["new BigNumber","cmp","config","div","divToInt","eq","gt","gte","lt","lte","minus","mod","plus","precision","random","round","shift","times","toDigits","toExponential","toFixed","toFormat","toFraction","pow","toPrecision","toString","BigNumber"][t]+"() "+e+": "+n);throw r.name="BigNumber Error",C=0,r}function S(t,e,n,r){var i,o,a,s,u,c,l,f=t.c,p=N;if(f){t:{for(i=1,s=f[0];s>=10;s/=10,i++);if(o=e-i,0>o)o+=I,a=e,u=f[c=0],l=u/p[i-a-1]%10|0;else if(c=y((o+1)/I),c>=f.length){if(!r)break t;for(;f.length<=c;f.push(0));u=l=0,i=1,o%=I,a=o-I+1}else{for(u=s=f[c],i=1;s>=10;s/=10,i++);o%=I,a=o-I+i,l=0>a?0:u/p[i-a-1]%10|0}if(r=r||0>e||null!=f[c+1]||(0>a?u:u%p[i-a-1]),r=4>n?(l||r)&&(0==n||n==(t.s<0?3:2)):l>5||5==l&&(4==n||r||6==n&&(o>0?a>0?u/p[i-a]:0:f[c-1])%10&1||n==(t.s<0?8:7)),1>e||!f[0])return f.length=0,r?(e-=t.e+1,f[0]=p[e%I],t.e=-e||0):f[0]=t.e=0,t;if(0==o?(f.length=c,s=1,c--):(f.length=c+1,s=p[I-o],f[c]=a>0?v(u/p[i-a]%p[a])*s:0),r)for(;;){if(0==c){for(o=1,a=f[0];a>=10;a/=10,o++);for(a=f[0]+=s,s=1;a>=10;a/=10,s++);o!=s&&(t.e++,f[0]==F&&(f[0]=1));break}if(f[c]+=s,f[c]!=F)break;f[c--]=0,s=1}for(o=f.length;0===f[--o];f.pop());}t.e>G?t.c=t.e=null:t.en?null!=(t=i[n++]):void 0};return a(e="DECIMAL_PLACES")&&W(t,0,k,2,e)&&(j=0|t),r[e]=j,a(e="ROUNDING_MODE")&&W(t,0,8,2,e)&&(L=0|t),r[e]=L,a(e="EXPONENTIAL_AT")&&(u(t)?W(t[0],-k,0,2,e)&&W(t[1],0,k,2,e)&&(q=0|t[0],U=0|t[1]):W(t,-k,k,2,e)&&(q=-(U=0|(0>t?-t:t)))),r[e]=[q,U],a(e="RANGE")&&(u(t)?W(t[0],-k,-1,2,e)&&W(t[1],1,k,2,e)&&(M=0|t[0],G=0|t[1]):W(t,-k,k,2,e)&&(0|t?M=-(G=0|(0>t?-t:t)):z&&D(2,e+" cannot be zero",t))),r[e]=[M,G],a(e="ERRORS")&&(t===!!t||1===t||0===t?(C=0,W=(z=!!t)?P:s):z&&D(2,e+w,t)),r[e]=z,a(e="CRYPTO")&&(t===!!t||1===t||0===t?(J=!(!t||!m||"object"!=typeof m),t&&!J&&z&&D(2,"crypto unavailable",m)):z&&D(2,e+w,t)),r[e]=J,a(e="MODULO_MODE")&&W(t,0,9,2,e)&&($=0|t),r[e]=$,a(e="POW_PRECISION")&&W(t,0,k,2,e)&&(V=0|t),r[e]=V,a(e="FORMAT")&&("object"==typeof t?X=t:z&&D(2,e+" not an object",t)),r[e]=X,r},e.max=function(){return A(arguments,E.lt)},e.min=function(){return A(arguments,E.gt)},e.random=function(){var t=9007199254740992,n=Math.random()*t&2097151?function(){return v(Math.random()*t)}:function(){return 8388608*(1073741824*Math.random()|0)+(8388608*Math.random()|0)};return function(t){var r,i,o,a,s,u=0,c=[],l=new e(H);if(t=null!=t&&W(t,0,k,14)?0|t:j,a=y(t/I),J)if(m&&m.getRandomValues){for(r=m.getRandomValues(new Uint32Array(a*=2));a>u;)s=131072*r[u]+(r[u+1]>>>11),s>=9e15?(i=m.getRandomValues(new Uint32Array(2)),r[u]=i[0],r[u+1]=i[1]):(c.push(s%1e14),u+=2);u=a/2}else if(m&&m.randomBytes){for(r=m.randomBytes(a*=7);a>u;)s=281474976710656*(31&r[u])+1099511627776*r[u+1]+4294967296*r[u+2]+16777216*r[u+3]+(r[u+4]<<16)+(r[u+5]<<8)+r[u+6],s>=9e15?m.randomBytes(7).copy(r,u):(c.push(s%1e14),u+=7);u=a/7}else z&&D(14,"crypto unavailable",m);if(!u)for(;a>u;)s=n(),9e15>s&&(c[u++]=s%1e14);for(a=c[--u],t%=I,a&&t&&(s=N[I-t],c[u]=v(a/s)*s);0===c[u];c.pop(),u--);if(0>u)c=[o=0];else{for(o=-1;0===c[0];c.shift(),o-=I);for(u=1,s=c[0];s>=10;s/=10,u++);I>u&&(o-=I-u)}return l.e=o,l.c=c,l}}(),R=function(){function t(t,e,n){var r,i,o,a,s=0,u=t.length,c=e%O,l=e/O|0;for(t=t.slice();u--;)o=t[u]%O,a=t[u]/O|0,r=l*o+a*c,i=c*o+r%O*O+s,s=(i/n|0)+(r/O|0)+l*a,t[u]=i%n;return s&&t.unshift(s),t}function n(t,e,n,r){var i,o;if(n!=r)o=n>r?1:-1;else for(i=o=0;n>i;i++)if(t[i]!=e[i]){o=t[i]>e[i]?1:-1;break}return o}function r(t,e,n,r){for(var i=0;n--;)t[n]-=i,i=t[n]1;t.shift());}return function(o,a,s,u,c){var l,f,p,h,m,d,g,y,w,b,_,x,B,N,O,k,A,P=o.s==a.s?1:-1,T=o.c,D=a.c;if(!(T&&T[0]&&D&&D[0]))return new e(o.s&&a.s&&(T?!D||T[0]!=D[0]:D)?T&&0==T[0]||!D?0*P:P/0:0/0);for(y=new e(P),w=y.c=[],f=o.e-a.e,P=s+f+1,c||(c=F,f=i(o.e/I)-i(a.e/I),P=P/I|0),p=0;D[p]==(T[p]||0);p++);if(D[p]>(T[p]||0)&&f--,0>P)w.push(1),h=!0;else{for(N=T.length,k=D.length,p=0,P+=2,m=v(c/(D[0]+1)),m>1&&(D=t(D,m,c),T=t(T,m,c),k=D.length,N=T.length),B=k,b=T.slice(0,k),_=b.length;k>_;b[_++]=0);A=D.slice(),A.unshift(0),O=D[0],D[1]>=c/2&&O++;do{if(m=0,l=n(D,b,k,_),0>l){if(x=b[0],k!=_&&(x=x*c+(b[1]||0)),m=v(x/O),m>1)for(m>=c&&(m=c-1),d=t(D,m,c),g=d.length,_=b.length;1==n(d,b,g,_);)m--,r(d,g>k?A:D,g,c),g=d.length,l=1;else 0==m&&(l=m=1),d=D.slice(),g=d.length;if(_>g&&d.unshift(0),r(b,d,_,c),_=b.length,-1==l)for(;n(D,b,k,_)<1;)m++,r(b,_>k?A:D,_,c),_=b.length}else 0===l&&(m++,b=[0]);w[p++]=m,b[0]?b[_++]=T[B]||0:(b=[T[B]],_=1)}while((B++=10;P/=10,p++);S(y,s+(y.e=p+f*I-1)+1,u,h)}else y.e=f,y.r=+h;return y}}(),d=function(){var t=/^(-?)0([xbo])/i,n=/^([^.]+)\.$/,r=/^\.([^.]+)$/,i=/^-?(Infinity|NaN)$/,o=/^\s*\+|^\s+|\s+$/g;return function(a,s,u,c){var l,f=u?s:s.replace(o,"");if(i.test(f))a.s=isNaN(f)?null:0>f?-1:1;else{if(!u&&(f=f.replace(t,function(t,e,n){return l="x"==(n=n.toLowerCase())?16:"b"==n?2:8,c&&c!=l?t:e}),c&&(l=c,f=f.replace(n,"$1").replace(r,"0.$1")),s!=f))return new e(f,l);z&&D(C,"not a"+(c?" base "+c:"")+" number",s),a.s=null}a.c=a.e=null,C=0}}(),E.absoluteValue=E.abs=function(){var t=new e(this);return t.s<0&&(t.s=1),t},E.ceil=function(){return S(new e(this),this.e+1,2)},E.comparedTo=E.cmp=function(t,n){return C=1,a(this,new e(t,n))},E.decimalPlaces=E.dp=function(){var t,e,n=this.c;if(!n)return null;if(t=((e=n.length-1)-i(this.e/I))*I,e=n[e])for(;e%10==0;e/=10,t--);return 0>t&&(t=0),t},E.dividedBy=E.div=function(t,n){return C=3,R(this,new e(t,n),j,L)},E.dividedToIntegerBy=E.divToInt=function(t,n){return C=4,R(this,new e(t,n),0,1)},E.equals=E.eq=function(t,n){return C=5,0===a(this,new e(t,n))},E.floor=function(){return S(new e(this),this.e+1,3)},E.greaterThan=E.gt=function(t,n){return C=6,a(this,new e(t,n))>0},E.greaterThanOrEqualTo=E.gte=function(t,n){return C=7,1===(n=a(this,new e(t,n)))||0===n},E.isFinite=function(){return!!this.c},E.isInteger=E.isInt=function(){return!!this.c&&i(this.e/I)>this.c.length-2},E.isNaN=function(){return!this.s},E.isNegative=E.isNeg=function(){return this.s<0},E.isZero=function(){return!!this.c&&0==this.c[0]},E.lessThan=E.lt=function(t,n){return C=8,a(this,new e(t,n))<0},E.lessThanOrEqualTo=E.lte=function(t,n){return C=9,-1===(n=a(this,new e(t,n)))||0===n},E.minus=E.sub=function(t,n){var r,o,a,s,u=this,c=u.s;if(C=10,t=new e(t,n),n=t.s,!c||!n)return new e(0/0);if(c!=n)return t.s=-n,u.plus(t);var l=u.e/I,f=t.e/I,p=u.c,h=t.c;if(!l||!f){if(!p||!h)return p?(t.s=-n,t):new e(h?u:0/0);if(!p[0]||!h[0])return h[0]?(t.s=-n,t):new e(p[0]?u:3==L?-0:0)}if(l=i(l),f=i(f),p=p.slice(),c=l-f){for((s=0>c)?(c=-c,a=p):(f=l,a=h),a.reverse(),n=c;n--;a.push(0));a.reverse()}else for(o=(s=(c=p.length)<(n=h.length))?c:n,c=n=0;o>n;n++)if(p[n]!=h[n]){s=p[n]0)for(;n--;p[r++]=0);for(n=F-1;o>c;){if(p[--o]0?(u=s,r=l):(a=-a,r=c),r.reverse();a--;r.push(0));r.reverse()}for(a=c.length,n=l.length,0>a-n&&(r=l,l=c,c=r,n=a),a=0;n;)a=(c[--n]=c[n]+l[n]+a)/F|0,c[n]%=F;return a&&(c.unshift(a),++u),T(t,c,u)},E.precision=E.sd=function(t){var e,n,r=this,i=r.c;if(null!=t&&t!==!!t&&1!==t&&0!==t&&(z&&D(13,"argument"+w,t),t!=!!t&&(t=null)),!i)return null;if(n=i.length-1,e=n*I+1,n=i[n]){for(;n%10==0;n/=10,e--);for(n=i[0];n>=10;n/=10,e++);}return t&&r.e+1>e&&(e=r.e+1),e},E.round=function(t,n){var r=new e(this);return(null==t||W(t,0,k,15))&&S(r,~~t+this.e+1,null!=n&&W(n,0,8,15,b)?0|n:L),r},E.shift=function(t){var n=this;return W(t,-B,B,16,"argument")?n.times("1e"+p(t)):new e(n.c&&n.c[0]&&(-B>t||t>B)?n.s*(0>t?0:1/0):n)},E.squareRoot=E.sqrt=function(){var t,n,r,a,s,u=this,c=u.c,l=u.s,f=u.e,p=j+4,h=new e("0.5");if(1!==l||!c||!c[0])return new e(!l||0>l&&(!c||c[0])?0/0:c?u:1/0);if(l=Math.sqrt(+u),0==l||l==1/0?(n=o(c),(n.length+f)%2==0&&(n+="0"),l=Math.sqrt(n),f=i((f+1)/2)-(0>f||f%2),l==1/0?n="1e"+f:(n=l.toExponential(),n=n.slice(0,n.indexOf("e")+1)+f),r=new e(n)):r=new e(l+""),r.c[0])for(f=r.e,l=f+p,3>l&&(l=0);;)if(s=r,r=h.times(s.plus(R(u,s,p,1))),o(s.c).slice(0,l)===(n=o(r.c)).slice(0,l)){if(r.el&&(g=b,b=_,_=g,a=l,l=h,h=a),a=l+h,g=[];a--;g.push(0));for(y=F,v=O,a=h;--a>=0;){for(r=0,m=_[a]%v,d=_[a]/v|0,u=l,s=a+u;s>a;)f=b[--u]%v,p=b[u]/v|0,c=d*f+p*m,f=m*f+c%v*v+g[s]+r,r=(f/y|0)+(c/v|0)+d*p,g[s--]=f%y;g[s]=r}return r?++o:g.shift(),T(t,g,o)},E.toDigits=function(t,n){var r=new e(this);return t=null!=t&&W(t,1,k,18,"precision")?0|t:null,n=null!=n&&W(n,0,8,18,b)?0|n:L,t?S(r,t,n):r},E.toExponential=function(t,e){return h(this,null!=t&&W(t,0,k,19)?~~t+1:null,e,19)},E.toFixed=function(t,e){return h(this,null!=t&&W(t,0,k,20)?~~t+this.e+1:null,e,20)},E.toFormat=function(t,e){var n=h(this,null!=t&&W(t,0,k,21)?~~t+this.e+1:null,e,21);if(this.c){var r,i=n.split("."),o=+X.groupSize,a=+X.secondaryGroupSize,s=X.groupSeparator,u=i[0],c=i[1],l=this.s<0,f=l?u.slice(1):u,p=f.length;if(a&&(r=o,o=a,a=r,p-=r),o>0&&p>0){for(r=p%o||o,u=f.substr(0,r);p>r;r+=o)u+=s+f.substr(r,o);a>0&&(u+=s+f.slice(r)),l&&(u="-"+u)}n=c?u+X.decimalSeparator+((a=+X.fractionGroupSize)?c.replace(new RegExp("\\d{"+a+"}\\B","g"),"$&"+X.fractionGroupSeparator):c):u}return n},E.toFraction=function(t){var n,r,i,a,s,u,c,l,f,p=z,h=this,m=h.c,d=new e(H),g=r=new e(H),y=c=new e(H);if(null!=t&&(z=!1,u=new e(t),z=p,(!(p=u.isInt())||u.lt(H))&&(z&&D(22,"max denominator "+(p?"out of range":"not an integer"),t),t=!p&&u.c&&S(u,u.e+1,1).gte(H)?u:null)),!m)return h.toString();for(f=o(m),a=d.e=f.length-h.e-1,d.c[0]=N[(s=a%I)<0?I+s:s],t=!t||u.cmp(d)>0?a>0?d:g:u,s=G,G=1/0,u=new e(f),c.c[0]=0;l=R(u,d,0,1),i=r.plus(l.times(y)),1!=i.cmp(t);)r=y,y=i,g=c.plus(l.times(i=g)),c=i,d=u.minus(l.times(i=d)),u=i;return i=R(t.minus(r),y,0,1),c=c.plus(i.times(g)),r=r.plus(i.times(y)),c.s=g.s=h.s,a*=2,n=R(g,y,a,L).minus(h).abs().cmp(R(c,r,a,L).minus(h).abs())<1?[g.toString(),y.toString()]:[c.toString(),r.toString()],G=s,n},E.toNumber=function(){var t=this;return+t||(t.s?0*t.s:0/0)},E.toPower=E.pow=function(t){var n,r,i=v(0>t?-t:+t),o=this;if(!W(t,-B,B,23,"exponent")&&(!isFinite(t)||i>B&&(t/=0)||parseFloat(t)!=t&&!(t=0/0)))return new e(Math.pow(+o,t));for(n=V?y(V/I+2):0,r=new e(H);;){if(i%2){if(r=r.times(o),!r.c)break;n&&r.c.length>n&&(r.c.length=n)}if(i=v(i/2),!i)break;o=o.times(o),n&&o.c&&o.c.length>n&&(o.c.length=n)}return 0>t&&(r=H.div(r)),n?S(r,V,L):r},E.toPrecision=function(t,e){return h(this,null!=t&&W(t,1,k,24,"precision")?0|t:null,e,24)},E.toString=function(t){var e,r=this,i=r.s,a=r.e;return null===a?i?(e="Infinity",0>i&&(e="-"+e)):e="NaN":(e=o(r.c),e=null!=t&&W(t,2,64,25,"base")?n(f(e,a),0|t,10,i):q>=a||a>=U?l(e,a):f(e,a),0>i&&r.c[0]&&(e="-"+e)),e},E.truncated=E.trunc=function(){return S(new e(this),this.e+1,1)},E.valueOf=E.toJSON=function(){return this.toString()},null!=t&&e.config(t),e}function i(t){var e=0|t;return t>0||t===e?e:e-1}function o(t){for(var e,n,r=1,i=t.length,o=t[0]+"";i>r;){for(e=t[r++]+"",n=I-e.length;n--;e="0"+e);o+=e}for(i=o.length;48===o.charCodeAt(--i););return o.slice(0,i+1||1)}function a(t,e){var n,r,i=t.c,o=e.c,a=t.s,s=e.s,u=t.e,c=e.e;if(!a||!s)return null;if(n=i&&!i[0],r=o&&!o[0],n||r)return n?r?0:-s:a; + +if(a!=s)return a;if(n=0>a,r=u==c,!i||!o)return r?0:!i^n?1:-1;if(!r)return u>c^n?1:-1;for(s=(u=i.length)<(c=o.length)?u:c,a=0;s>a;a++)if(i[a]!=o[a])return i[a]>o[a]^n?1:-1;return u==c?0:u>c^n?1:-1}function s(t,e,n){return(t=p(t))>=e&&n>=t}function u(t){return"[object Array]"==Object.prototype.toString.call(t)}function c(t,e,n){for(var r,i,o=[0],a=0,s=t.length;s>a;){for(i=o.length;i--;o[i]*=e);for(o[r=0]+=x.indexOf(t.charAt(a++));rn-1&&(null==o[r+1]&&(o[r+1]=0),o[r+1]+=o[r]/n|0,o[r]%=n)}return o.reverse()}function l(t,e){return(t.length>1?t.charAt(0)+"."+t.slice(1):t)+(0>e?"e":"e+")+e}function f(t,e){var n,r;if(0>e){for(r="0.";++e;r+="0");t=r+t}else if(n=t.length,++e>n){for(r="0",e-=n;--e;r+="0");t+=r}else n>e&&(t=t.slice(0,e)+"."+t.slice(e));return t}function p(t){return t=parseFloat(t),0>t?y(t):v(t)}var h,m,d,g=/^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,y=Math.ceil,v=Math.floor,w=" not a boolean or binary digit",b="rounding mode",_="number type has more than 15 significant digits",x="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_",F=1e14,I=14,B=9007199254740991,N=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],O=1e7,k=1e9;if(h=r(),"function"==typeof define&&define.amd)define(function(){return h});else if("undefined"!=typeof e&&e.exports){if(e.exports=h,!m)try{m=t("crypto")}catch(A){}}else n.BigNumber=h}(this)},{crypto:32}],web3:[function(t,e,n){var r=t("./lib/web3");r.providers.HttpProvider=t("./lib/web3/httpprovider"),r.providers.QtSyncProvider=t("./lib/web3/qtsync"),r.eth.contract=t("./lib/web3/contract"),r.eth.namereg=t("./lib/web3/namereg"),r.eth.sendIBANTransaction=t("./lib/web3/transfer"),"undefined"!=typeof window&&"undefined"==typeof window.web3&&(window.web3=r),e.exports=r},{"./lib/web3":9,"./lib/web3/contract":12,"./lib/web3/httpprovider":20,"./lib/web3/namereg":24,"./lib/web3/qtsync":27,"./lib/web3/transfer":30}]},{},["web3"]); \ No newline at end of file diff --git a/example/contract_array.html b/example/contract_array.html new file mode 100644 index 000000000..421e42baf --- /dev/null +++ b/example/contract_array.html @@ -0,0 +1,83 @@ + + + + + + + + +

contract

+
+
+
+ +
+ +
+ + + diff --git a/gulpfile.js b/gulpfile.js index 360c5242b..1291e3028 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -17,7 +17,7 @@ var bower = require('bower'); var streamify = require('gulp-streamify'); var replace = require('gulp-replace'); -var DEST = './dist/'; +var DEST = path.join(__dirname, 'dist/'); var src = 'index'; var dst = 'web3'; var lightDst = 'web3-light'; @@ -29,7 +29,7 @@ var browserifyOptions = { bundleExternal: true }; -gulp.task('versionReplace', function(){ +gulp.task('version', function(){ gulp.src(['./package.json']) .pipe(replace(/\"version\"\: \"(.{5})\"/, '"version": "'+ version.version + '"')) .pipe(gulp.dest('./')); @@ -41,24 +41,24 @@ gulp.task('versionReplace', function(){ .pipe(gulp.dest('./')); }); -gulp.task('bower', function(cb){ +gulp.task('bower', ['version'], function(cb){ bower.commands.install().on('end', function (installed){ console.log(installed); cb(); }); }); -gulp.task('clean', ['lint'], function(cb) { - del([ DEST ], cb); -}); - -gulp.task('lint', function(){ +gulp.task('lint', ['bower'], function(){ return gulp.src(['./*.js', './lib/*.js']) .pipe(jshint()) .pipe(jshint.reporter('default')); }); -gulp.task('buildLight', ['clean'], function () { +gulp.task('clean', ['lint'], function(cb) { + del([ DEST ], cb); +}); + +gulp.task('light', ['clean'], function () { return browserify(browserifyOptions) .require('./' + src + '.js', {expose: 'web3'}) .ignore('bignumber.js') @@ -73,7 +73,7 @@ gulp.task('buildLight', ['clean'], function () { .pipe(gulp.dest( DEST )); }); -gulp.task('buildStandalone', ['clean'], function () { +gulp.task('standalone', ['clean'], function () { return browserify(browserifyOptions) .require('./' + src + '.js', {expose: 'web3'}) .require('bignumber.js') // expose it to dapp users @@ -92,10 +92,5 @@ gulp.task('watch', function() { gulp.watch(['./lib/*.js'], ['lint', 'build']); }); -gulp.task('light', ['versionReplace','bower', 'lint', 'buildLight']); -gulp.task('standalone', ['versionReplace','bower', 'lint', 'buildStandalone']); -gulp.task('default', ['light', 'standalone']); - - -gulp.task('version', ['versionReplace']); +gulp.task('default', ['version', 'bower', 'lint', 'clean', 'light', 'standalone']); diff --git a/karma.conf.js b/karma.conf.js deleted file mode 100644 index 9375315f7..000000000 --- a/karma.conf.js +++ /dev/null @@ -1,95 +0,0 @@ -// Karma configuration -// Generated on Thu Feb 19 2015 19:57:47 GMT+0100 (W. Europe Standard Time) - -module.exports = function (config) { - config.set({ - - // base path that will be used to resolve all patterns (eg. files, exclude) - basePath: '', - - // level of logging - // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG - - // Continuous Integration mode - // if true, Karma captures browsers, runs the tests and exits - singleRun: true, logLevel: config.LOG_INFO, - //singleRun: true, logLevel: config.LOG_DEBUG, - - // frameworks to use - // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - frameworks: ['browserify', 'mocha'], - - - // list of files / patterns to load in the browser - files: [ - 'test/*.js' - ], - - - // list of files to exclude - exclude: [ - ], - - client: { - mocha: { - //ui: 'tdd' - timeout: 5000 // especially for the post requests - } - }, - browserify: { - bundleDelay: 750, - debug: true - // transform: [], - // //extensions: ['.js'] - }, - - // preprocess matching files before serving them to the browser - // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor - preprocessors: { - 'test/*.js': ['browserify'] - }, - - - // test results reporter to use - // possible values: 'dots', 'progress' - // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ['dots'], - - - // web server port - port: 9876, - - - // enable / disable colors in the output (reporters and logs) - colors: true, - - - // enable / disable watching file and executing tests whenever any file changes - autoWatch: true, - - - // start these browsers - // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher - // // Chrome - // // PhantomJS - browsers: ['Chrome', 'Safari', 'Firefox'], - browserNoActivityTimeout: 10000, - browserDisconnectTimeout: 5000, - - customLaunchers: { - chromeWithoutSecurity: { - base: 'Chrome', - flags: ['--disable-web-security'] - }, - - IE9: { - base: 'IE', - 'x-ua-compatible': 'IE=EmulateIE9' - }, - IE8: { - base: 'IE', - 'x-ua-compatible': 'IE=EmulateIE8' - } - } - }); -}; diff --git a/lib/solidity/coder.js b/lib/solidity/coder.js index b46a38b0b..59b001fdd 100644 --- a/lib/solidity/coder.js +++ b/lib/solidity/coder.js @@ -262,6 +262,13 @@ var coder = new SolidityCoder([ inputFormatter: f.formatInputBytes, outputFormatter: f.formatOutputBytes }), + new SolidityType({ + name: 'string', + match: 'strict', + mode: 'bytes', + inputFormatter: f.formatInputString, + outputFormatter: f.formatOutputString + }), new SolidityType({ name: 'real', match: 'prefix', diff --git a/lib/solidity/formatters.js b/lib/solidity/formatters.js index 3db936528..de388cfd9 100644 --- a/lib/solidity/formatters.js +++ b/lib/solidity/formatters.js @@ -43,26 +43,43 @@ var formatInputInt = function (value) { }; /** - * Formats input value to byte representation of string + * Formats input bytes * * @method formatInputBytes * @param {String} * @returns {SolidityParam} */ var formatInputBytes = function (value) { - var result = utils.fromAscii(value, c.ETH_PADDING).substr(2); + var result = utils.padRight(utils.toHex(value).substr(2), 64); return new SolidityParam(result); }; /** - * Formats input value to byte representation of string + * Formats input bytes * - * @method formatInputDynamicBytes + * @method formatDynamicInputBytes * @param {String} * @returns {SolidityParam} */ var formatInputDynamicBytes = function (value) { - var result = utils.fromAscii(value, c.ETH_PADDING).substr(2); + value = utils.toHex(value).substr(2); + var l = Math.floor((value.length + 63) / 64); + var result = utils.padRight(value, l * 64); + var length = Math.floor(value.length / 2); + return new SolidityParam(formatInputInt(length).value + result, 32); +}; + +/** + * Formats input value to byte representation of string + * + * @method formatInputString + * @param {String} + * @returns {SolidityParam} + */ +var formatInputString = function (value) { + var result = utils.fromAscii(value).substr(2); + var l = Math.floor((result.length + 63) / 64); + result = utils.padRight(result, l * 64); return new SolidityParam(formatInputInt(value.length).value + result, 32); }; @@ -165,27 +182,38 @@ var formatOutputBool = function (param) { }; /** - * Should be used to format output string + * Should be used to format output bytes * * @method formatOutputBytes * @param {SolidityParam} left-aligned hex representation of string - * @returns {String} ascii string + * @returns {String} hex string */ var formatOutputBytes = function (param) { - // length might also be important! - return utils.toAscii(param.staticPart()); + return '0x' + param.staticPart(); }; /** - * Should be used to format output string + * Should be used to format output bytes * * @method formatOutputDynamicBytes * @param {SolidityParam} left-aligned hex representation of string - * @returns {String} ascii string + * @returns {String} hex string */ var formatOutputDynamicBytes = function (param) { - // length might also be important! - return utils.toAscii(param.dynamicPart().slice(64)); + var length = (new BigNumber(param.dynamicPart().slice(0, 64), 16)).toNumber() * 2; + return '0x' + param.dynamicPart().substr(64, length); +}; + +/** + * Should be used to format output string + * + * @method formatOutputString + * @param {SolidityParam} left-aligned hex representation of string + * @returns {String} ascii string + */ +var formatOutputString = function (param) { + var length = (new BigNumber(param.dynamicPart().slice(0, 64), 16)).toNumber() * 2; + return utils.toAscii(param.dynamicPart().substr(64, length)); }; /** @@ -204,6 +232,7 @@ module.exports = { formatInputInt: formatInputInt, formatInputBytes: formatInputBytes, formatInputDynamicBytes: formatInputDynamicBytes, + formatInputString: formatInputString, formatInputBool: formatInputBool, formatInputReal: formatInputReal, formatOutputInt: formatOutputInt, @@ -213,6 +242,7 @@ module.exports = { formatOutputBool: formatOutputBool, formatOutputBytes: formatOutputBytes, formatOutputDynamicBytes: formatOutputDynamicBytes, + formatOutputString: formatOutputString, formatOutputAddress: formatOutputAddress }; diff --git a/lib/solidity/param.js b/lib/solidity/param.js index 25fa3f4f8..2a78a9b66 100644 --- a/lib/solidity/param.js +++ b/lib/solidity/param.js @@ -182,13 +182,14 @@ var getOffset = function (bytes, index) { */ SolidityParam.decodeBytes = function (bytes, index) { index = index || 0; - //TODO add support for strings longer than 32 bytes - //var length = parseInt('0x' + bytes.substr(offset * 64, 64)); var offset = getOffset(bytes, index); - // 2 * , cause we also parse length - return new SolidityParam(bytes.substr(offset * 2, 2 * 64), 0); + var l = parseInt('0x' + bytes.substr(offset * 2, 64)); + l = Math.floor((l + 31) / 32); + + // (1 + l) * , cause we also parse length + return new SolidityParam(bytes.substr(offset * 2, (1 + l) * 64), 0); }; /** diff --git a/lib/utils/utils.js b/lib/utils/utils.js index 42363ab88..7d6057713 100644 --- a/lib/utils/utils.js +++ b/lib/utils/utils.js @@ -75,6 +75,19 @@ var padLeft = function (string, chars, sign) { return new Array(chars - string.length + 1).join(sign ? sign : "0") + string; }; +/** + * Should be called to pad string to expected length + * + * @method padRight + * @param {String} string to be padded + * @param {Number} characters that result string should have + * @param {String} sign, by default 0 + * @returns {String} right aligned string + */ +var padRight = function (string, chars, sign) { + return string + (new Array(chars - string.length + 1).join(sign ? sign : "0")); +}; + /** * Should be called to get sting from it's hex representation * @@ -91,10 +104,6 @@ var toAscii = function(hex) { } for (; i < l; i+=2) { var code = parseInt(hex.substr(i, 2), 16); - if (code === 0) { - break; - } - str += String.fromCharCode(code); } @@ -204,7 +213,7 @@ var fromDecimal = function (value) { * @return {String} */ var toHex = function (val) { - /*jshint maxcomplexity:7 */ + /*jshint maxcomplexity: 8 */ if (isBoolean(val)) return fromDecimal(+val); @@ -218,9 +227,11 @@ var toHex = function (val) { // if its a negative number, pass it through fromDecimal if (isString(val)) { if (val.indexOf('-0x') === 0) - return fromDecimal(val); + return fromDecimal(val); else if (!isFinite(val)) return fromAscii(val); + else if(val.indexOf('0x') === 0) + return val; } return fromDecimal(val); @@ -471,6 +482,7 @@ var isIBAN = function (iban) { module.exports = { padLeft: padLeft, + padRight: padRight, toHex: toHex, toDecimal: toDecimal, fromDecimal: fromDecimal, diff --git a/lib/version.json b/lib/version.json index 424d60960..4fe134016 100644 --- a/lib/version.json +++ b/lib/version.json @@ -1,3 +1,3 @@ { - "version": "0.6.0" + "version": "0.7.1" } diff --git a/lib/web3.js b/lib/web3.js index 66eea6ee1..8f684d132 100644 --- a/lib/web3.js +++ b/lib/web3.js @@ -80,31 +80,25 @@ var setupProperties = function (obj, properties) { /// setups web3 object, and it's in-browser executed methods var web3 = {}; web3.providers = {}; +web3.currentProvider = null; web3.version = {}; web3.version.api = version.version; web3.eth = {}; /*jshint maxparams:4 */ -web3.eth.filter = function (fil, eventParams, options, formatter) { - - // if its event, treat it differently - // TODO: simplify and remove - if (fil._isEvent) { - return fil(eventParams, options); - } - - // output logs works for blockFilter and pendingTransaction filters? - return new Filter(fil, watches.eth(), formatter || formatters.outputLogFormatter); +web3.eth.filter = function (fil, callback) { + return new Filter(fil, watches.eth(), formatters.outputLogFormatter, callback); }; /*jshint maxparams:3 */ web3.shh = {}; -web3.shh.filter = function (fil) { - return new Filter(fil, watches.shh(), formatters.outputPostFormatter); +web3.shh.filter = function (fil, callback) { + return new Filter(fil, watches.shh(), formatters.outputPostFormatter, callback); }; web3.net = {}; web3.db = {}; web3.setProvider = function (provider) { + this.currentProvider = provider; RequestManager.getInstance().setProvider(provider); }; web3.reset = function () { diff --git a/lib/web3/allevents.js b/lib/web3/allevents.js new file mode 100644 index 000000000..190643034 --- /dev/null +++ b/lib/web3/allevents.js @@ -0,0 +1,81 @@ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** + * @file allevents.js + * @author Marek Kotewicz + * @date 2014 + */ + +var sha3 = require('../utils/sha3'); +var SolidityEvent = require('./event'); +var formatters = require('./formatters'); +var utils = require('../utils/utils'); +var Filter = require('./filter'); +var watches = require('./watches'); + +var AllSolidityEvents = function (json, address) { + this._json = json; + this._address = address; +}; + +AllSolidityEvents.prototype.encode = function (options) { + options = options || {}; + var result = {}; + + ['fromBlock', 'toBlock'].filter(function (f) { + return options[f] !== undefined; + }).forEach(function (f) { + result[f] = formatters.inputBlockNumberFormatter(options[f]); + }); + + result.topics = [null, null, null, null, null]; // match all topics + result.address = this._address; + + return result; +}; + +AllSolidityEvents.prototype.decode = function (data) { + data.data = data.data || ''; + data.topics = data.topics || []; + + var eventTopic = data.topics[0].slice(2); + var match = this._json.filter(function (j) { + return eventTopic === sha3(utils.transformToFullName(j)); + })[0]; + + if (!match) { // cannot find matching event? + console.warn('cannot find event for log'); + return data; + } + + var event = new SolidityEvent(match, this._address); + return event.decode(data); +}; + +AllSolidityEvents.prototype.execute = function (options, callback) { + var o = this.encode(options); + var formatter = this.decode.bind(this); + return new Filter(o, watches.eth(), formatter, callback); +}; + +AllSolidityEvents.prototype.attachToContract = function (contract) { + var execute = this.execute.bind(this); + contract.allEvents = execute; +}; + +module.exports = AllSolidityEvents; + diff --git a/lib/web3/contract.js b/lib/web3/contract.js index 9666f9eaa..433e7ecba 100644 --- a/lib/web3/contract.js +++ b/lib/web3/contract.js @@ -25,6 +25,7 @@ var utils = require('../utils/utils'); var coder = require('../solidity/coder'); var SolidityEvent = require('./event'); var SolidityFunction = require('./function'); +var AllEvents = require('./allevents'); /** * Should be called to encode constructor params @@ -70,9 +71,14 @@ var addFunctionsToContract = function (contract, abi) { * @param {Array} abi */ var addEventsToContract = function (contract, abi) { - abi.filter(function (json) { + var events = abi.filter(function (json) { return json.type === 'event'; - }).map(function (json) { + }); + + var All = new AllEvents(events, contract.address); + All.attachToContract(contract); + + events.map(function (json) { return new SolidityEvent(json, contract.address); }).forEach(function (e) { e.attachToContract(contract); diff --git a/lib/web3/event.js b/lib/web3/event.js index 7295cf63d..f2b40e3ea 100644 --- a/lib/web3/event.js +++ b/lib/web3/event.js @@ -22,9 +22,10 @@ var utils = require('../utils/utils'); var coder = require('../solidity/coder'); -var web3 = require('../web3'); var formatters = require('./formatters'); var sha3 = require('../utils/sha3'); +var Filter = require('./filter'); +var watches = require('./watches'); /** * This prototype should be used to create event filters @@ -170,10 +171,21 @@ SolidityEvent.prototype.decode = function (data) { * @param {Object} options * @return {Object} filter object */ -SolidityEvent.prototype.execute = function (indexed, options) { +SolidityEvent.prototype.execute = function (indexed, options, callback) { + + if (utils.isFunction(arguments[arguments.length - 1])) { + callback = arguments[arguments.length - 1]; + if(arguments.length === 2) + options = null; + if(arguments.length === 1) { + options = null; + indexed = {}; + } + } + var o = this.encode(indexed, options); var formatter = this.decode.bind(this); - return web3.eth.filter(o, undefined, undefined, formatter); + return new Filter(o, watches.eth(), formatter, callback); }; /** diff --git a/lib/web3/filter.js b/lib/web3/filter.js index bb760c3dc..0361aa0b8 100644 --- a/lib/web3/filter.js +++ b/lib/web3/filter.js @@ -127,7 +127,7 @@ var pollFilter = function(self) { }; -var Filter = function (options, methods, formatter) { +var Filter = function (options, methods, formatter, callback) { var self = this; var implementation = {}; methods.forEach(function (method) { @@ -135,23 +135,32 @@ var Filter = function (options, methods, formatter) { }); this.options = getOptions(options); this.implementation = implementation; + this.filterId = null; this.callbacks = []; this.pollFilters = []; this.formatter = formatter; this.implementation.newFilter(this.options, function(error, id){ if(error) { - self.callbacks.forEach(function(callback){ - callback(error); + self.callbacks.forEach(function(cb){ + cb(error); }); } else { self.filterId = id; - // get filter logs at start - self.callbacks.forEach(function(callback){ - getLogsAtStart(self, callback); + + // get filter logs for the already existing watch calls + self.callbacks.forEach(function(cb){ + getLogsAtStart(self, cb); }); - pollFilter(self); + if(self.callbacks.length > 0) + pollFilter(self); + + // start to watch immediately + if(callback) { + return self.watch(callback); + } } }); + }; Filter.prototype.watch = function (callback) { diff --git a/lib/web3/function.js b/lib/web3/function.js index c510adf15..918d367f9 100644 --- a/lib/web3/function.js +++ b/lib/web3/function.js @@ -188,8 +188,9 @@ SolidityFunction.prototype.request = function () { var format = this.unpackOutput.bind(this); return { + method: this._constant ? 'eth_call' : 'eth_sendTransaction', callback: callback, - payload: payload, + params: [payload], format: format }; }; diff --git a/lib/web3/httpprovider.js b/lib/web3/httpprovider.js index d3ac9cc34..6bdf32a85 100644 --- a/lib/web3/httpprovider.js +++ b/lib/web3/httpprovider.js @@ -24,7 +24,8 @@ "use strict"; -var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line +// resolves the problem for electron/atom shell environments, which use node integration, but have no process variable available +var XMLHttpRequest = (typeof window !== 'undefined' && window.XMLHttpRequest) ? window.XMLHttpRequest : require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line var errors = require('./errors'); var HttpProvider = function (host) { diff --git a/package-init.js b/package-init.js index 90313013b..efc2da65b 100644 --- a/package-init.js +++ b/package-init.js @@ -1,8 +1,17 @@ /* jshint ignore:start */ -if(typeof web3 === 'undefined') { - web3 = require('web3'); - BigNumber = require('bignumber.js'); + +// Browser environment +if(typeof window !== 'undefined') { + web3 = (typeof window.web3 !== 'undefined') ? window.web3 : require('web3'); + BigNumber = (typeof window.BigNumber !== 'undefined') ? window.BigNumber : require('bignumber.js'); +} + + +// Node environment +if(typeof global !== 'undefined') { + web3 = (typeof global.web3 !== 'undefined') ? global.web3 : require('web3'); + BigNumber = (typeof global.BigNumber !== 'undefined') ? global.BigNumber : require('bignumber.js'); } /* jshint ignore:end */ \ No newline at end of file diff --git a/package.js b/package.js index 66c3ddb5d..e46e9cbc6 100644 --- a/package.js +++ b/package.js @@ -1,7 +1,7 @@ /* jshint ignore:start */ Package.describe({ name: 'ethereum:web3', - version: '0.6.0', + version: '0.7.1', summary: 'Ethereum JavaScript API, middleware to talk to a ethreum node over RPC', git: 'https://github.com/ethereum/ethereum.js', // By default, Meteor will default to using README.md for documentation. @@ -14,7 +14,7 @@ Package.onUse(function(api) { // api.use('3stack:bignumber@2.0.0', 'client'); - api.export(['web3', 'BigNumber'], 'client'); + api.export(['web3', 'BigNumber'], ['client', 'server']); api.addFiles('dist/web3.js', 'client'); api.addFiles('package-init.js', 'client'); diff --git a/package.json b/package.json index f051c61cd..52b1be15d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "web3", "namespace": "ethereum", - "version": "0.6.0", + "version": "0.7.1", "description": "Ethereum JavaScript API, middleware to talk to a ethereum node over RPC", "main": "./index.js", "directories": { @@ -16,37 +16,30 @@ "xmlhttprequest": "./lib/utils/browser-xhr.js" }, "devDependencies": { - "bower": ">=1.3.0", + "bower": ">=1.4.1", "browserify": ">=10.0", - "chai": "^2.1.1", + "chai": "^3.0.0", "coveralls": "^2.11.2", - "del": ">=0.1.1", + "del": ">=1.2.0", "exorcist": "^0.4.0", - "gulp": ">=3.4.0", + "gulp": ">=3.9.0", "gulp-jshint": ">=1.5.0", "gulp-rename": ">=1.2.0", "gulp-replace": "^0.5.3", "gulp-streamify": "0.0.5", - "gulp-uglify": ">=1.0.0", + "gulp-uglify": ">=1.2.0", "istanbul": "^0.3.5", "jshint": ">=2.5.0", - "karma": "^0.12.31", - "karma-browserify": "^4.0.0", - "karma-chrome-launcher": "^0.1.7", - "karma-firefox-launcher": "^0.1.4", - "karma-mocha": "^0.1.10", - "karma-safari-launcher": "^0.1.1", "mocha": ">=2.1.0", - "sandboxed-module": "^2.0.0", - "vinyl-source-stream": "^1.0.0" + "sandboxed-module": "^2.0.2", + "vinyl-source-stream": "^1.1.0" }, "scripts": { "build": "gulp", "watch": "gulp watch", "lint": "jshint *.js lib", "test": "mocha", - "test-coveralls": "istanbul cover _mocha -- -R spec && cat coverage/lcov.info | coveralls --verbose", - "karma": "./node_modules/karma/bin/karma start --singleRun=true --browsers=\"Firefox\"" + "test-coveralls": "istanbul cover _mocha -- -R spec && cat coverage/lcov.info | coveralls --verbose" }, "repository": { "type": "git", diff --git a/test/batch.js b/test/batch.js index f368a5d74..5a06f0e7b 100644 --- a/test/batch.js +++ b/test/batch.js @@ -28,6 +28,16 @@ describe('lib/web3/batch', function () { done(); }; + provider.injectValidation(function (payload) { + var first = payload[0]; + var second = payload[1]; + + assert.equal(first.method, 'eth_getBalance'); + assert.deepEqual(first.params, ['0x0000000000000000000000000000000000000000', 'latest']); + assert.equal(second.method, 'eth_getBalance'); + assert.deepEqual(second.params, ['0x0000000000000000000000000000000000000005', 'latest']); + }); + var batch = web3.createBatch(); batch.add(web3.eth.getBalance.request('0x0000000000000000000000000000000000000000', 'latest', callback)); batch.add(web3.eth.getBalance.request('0x0000000000000000000000000000000000000005', 'latest', callback2)); @@ -55,7 +65,7 @@ describe('lib/web3/batch', function () { }]; - var address = '0x0000000000000000000000000000000000000000'; + var address = '0x1000000000000000000000000000000000000001'; var result = '0x126'; var result2 = '0x0000000000000000000000000000000000000000000000000000000000000123'; @@ -71,6 +81,19 @@ describe('lib/web3/batch', function () { done(); }; + provider.injectValidation(function (payload) { + var first = payload[0]; + var second = payload[1]; + + assert.equal(first.method, 'eth_getBalance'); + assert.deepEqual(first.params, ['0x0000000000000000000000000000000000000000', 'latest']); + assert.equal(second.method, 'eth_call'); + assert.deepEqual(second.params, [{ + 'to': '0x1000000000000000000000000000000000000001', + 'data': '0xe3d670d70000000000000000000000001000000000000000000000000000000000000001' + }]); + }); + var batch = web3.createBatch(); batch.add(web3.eth.getBalance.request('0x0000000000000000000000000000000000000000', 'latest', callback)); batch.add(web3.eth.contract(abi).at(address).balance.request(address, callback2)); diff --git a/test/coder.decodeParam.js b/test/coder.decodeParam.js index 959e96cf2..5555b7800 100644 --- a/test/coder.decodeParam.js +++ b/test/coder.decodeParam.js @@ -20,10 +20,53 @@ describe('lib/solidity/coder', function () { test({ type: 'int256', expected: new bn(1), value: '0000000000000000000000000000000000000000000000000000000000000001'}); test({ type: 'int256', expected: new bn(16), value: '0000000000000000000000000000000000000000000000000000000000000010'}); test({ type: 'int256', expected: new bn(-1), value: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); - test({ type: 'bytes32', expected: 'gavofyork', value: '6761766f66796f726b0000000000000000000000000000000000000000000000'}); - test({ type: 'bytes', expected: 'gavofyork', value: '0000000000000000000000000000000000000000000000000000000000000020' + + test({ type: 'int8', expected: new bn(16), value: '0000000000000000000000000000000000000000000000000000000000000010'}); + test({ type: 'int32', expected: new bn(16), value: '0000000000000000000000000000000000000000000000000000000000000010'}); + test({ type: 'int64', expected: new bn(16), value: '0000000000000000000000000000000000000000000000000000000000000010'}); + test({ type: 'int128', expected: new bn(16), value: '0000000000000000000000000000000000000000000000000000000000000010'}); + test({ type: 'bytes32', expected: '0x6761766f66796f726b0000000000000000000000000000000000000000000000', + value: '6761766f66796f726b0000000000000000000000000000000000000000000000'}); + test({ type: 'bytes', expected: '0x6761766f66796f726b', + value: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000009' + + '6761766f66796f726b0000000000000000000000000000000000000000000000'}); + test({ type: 'bytes32', expected: '0x731a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b', + value: '731a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b'}); + test({ type: 'bytes', expected: '0x731a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b', + value: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000020' + + '731a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b'}); + test({ type: 'bytes', expected: '0x731a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '731a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b', + value: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000040' + + '731a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '731a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b'}); + test({ type: 'bytes', expected: '0x131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '231a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '331a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b', + value: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000060' + + '131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '231a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '331a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b'}); + test({ type: 'string', expected: 'gavofyork', value: '0000000000000000000000000000000000000000000000000000000000000020' + '0000000000000000000000000000000000000000000000000000000000000009' + '6761766f66796f726b0000000000000000000000000000000000000000000000'}); + test({ type: 'string', expected: '\xc3\xa4\x00\x00\xc3\xa4', + value: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000006' + + 'c3a40000c3a40000000000000000000000000000000000000000000000000000'}); + test({ type: 'string', expected: '\xc3', + value: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000001' + + 'c300000000000000000000000000000000000000000000000000000000000000'}); + test({ type: 'bytes', expected: '0xc3a40000c3a4', + value: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000006' + + 'c3a40000c3a40000000000000000000000000000000000000000000000000000'}); + test({ type: 'bytes32', expected: '0xc3a40000c3a40000000000000000000000000000000000000000000000000000', + value: 'c3a40000c3a40000000000000000000000000000000000000000000000000000'}); test({ type: 'int[]', expected: [], value: '0000000000000000000000000000000000000000000000000000000000000020' + '0000000000000000000000000000000000000000000000000000000000000000'}); test({ type: 'int[]', expected: [new bn(3)], value: '0000000000000000000000000000000000000000000000000000000000000020' + @@ -49,6 +92,11 @@ describe('lib/solidity/coder', function () { test({ type: 'ureal', expected: new bn(8.5), value: '0000000000000000000000000000000880000000000000000000000000000000'}); test({ type: 'address', expected: '0x407d73d8a49eeb85d32cf465507dd71d507100c1', value: '000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1'}); + test({ type: 'string', expected: 'welcome to ethereum. welcome to ethereum. welcome to ethereum.', + value: '0000000000000000000000000000000000000000000000000000000000000020' + + '000000000000000000000000000000000000000000000000000000000000003e' + + '77656c636f6d6520746f20657468657265756d2e2077656c636f6d6520746f20' + + '657468657265756d2e2077656c636f6d6520746f20657468657265756d2e0000'}); }); }); @@ -62,26 +110,44 @@ describe('lib/solidity/coder', function () { test({ types: ['int'], expected: [new bn(1)], values: '0000000000000000000000000000000000000000000000000000000000000001'}); - test({ types: ['bytes32', 'int'], expected: ['gavofyork', new bn(5)], + test({ types: ['bytes32', 'int'], expected: ['0x6761766f66796f726b0000000000000000000000000000000000000000000000', new bn(5)], values: '6761766f66796f726b0000000000000000000000000000000000000000000000' + '0000000000000000000000000000000000000000000000000000000000000005'}); - test({ types: ['int', 'bytes32'], expected: [new bn(5), 'gavofyork'], + test({ types: ['int', 'bytes32'], expected: [new bn(5), '0x6761766f66796f726b0000000000000000000000000000000000000000000000'], values: '0000000000000000000000000000000000000000000000000000000000000005' + '6761766f66796f726b0000000000000000000000000000000000000000000000'}); - test({ types: ['int', 'bytes', 'int', 'int', 'int', 'int[]'], expected: [new bn(1), 'gavofyork', new bn(2), new bn(3), new bn(4), + test({ types: ['int', 'string', 'int', 'int', 'int', 'int[]'], expected: [new bn(1), 'gavofyork', new bn(2), new bn(3), new bn(4), [new bn(5), new bn(6), new bn(7)]], values: '0000000000000000000000000000000000000000000000000000000000000001' + - '00000000000000000000000000000000000000000000000000000000000000c0' + - '0000000000000000000000000000000000000000000000000000000000000002' + - '0000000000000000000000000000000000000000000000000000000000000003' + - '0000000000000000000000000000000000000000000000000000000000000004' + - '0000000000000000000000000000000000000000000000000000000000000100' + - '0000000000000000000000000000000000000000000000000000000000000009' + - '6761766f66796f726b0000000000000000000000000000000000000000000000' + - '0000000000000000000000000000000000000000000000000000000000000003' + - '0000000000000000000000000000000000000000000000000000000000000005' + - '0000000000000000000000000000000000000000000000000000000000000006' + - '0000000000000000000000000000000000000000000000000000000000000007'}); + '00000000000000000000000000000000000000000000000000000000000000c0' + + '0000000000000000000000000000000000000000000000000000000000000002' + + '0000000000000000000000000000000000000000000000000000000000000003' + + '0000000000000000000000000000000000000000000000000000000000000004' + + '0000000000000000000000000000000000000000000000000000000000000100' + + '0000000000000000000000000000000000000000000000000000000000000009' + + '6761766f66796f726b0000000000000000000000000000000000000000000000' + + '0000000000000000000000000000000000000000000000000000000000000003' + + '0000000000000000000000000000000000000000000000000000000000000005' + + '0000000000000000000000000000000000000000000000000000000000000006' + + '0000000000000000000000000000000000000000000000000000000000000007'}); + test({ types: ['int', 'bytes', 'int', 'bytes'], expected: [ + new bn(5), + '0x131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '231a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b', + new bn(3), + '0x331a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '431a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b', + ], + values: '0000000000000000000000000000000000000000000000000000000000000005' + + '0000000000000000000000000000000000000000000000000000000000000080' + + '0000000000000000000000000000000000000000000000000000000000000003' + + '00000000000000000000000000000000000000000000000000000000000000e0' + + '0000000000000000000000000000000000000000000000000000000000000040' + + '131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '231a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '0000000000000000000000000000000000000000000000000000000000000040' + + '331a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '431a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b'}); }); }); diff --git a/test/coder.encodeParam.js b/test/coder.encodeParam.js index 55ff657c2..71ae7804e 100644 --- a/test/coder.encodeParam.js +++ b/test/coder.encodeParam.js @@ -20,10 +20,37 @@ describe('lib/solidity/coder', function () { test({ type: 'int256', value: 1, expected: '0000000000000000000000000000000000000000000000000000000000000001'}); test({ type: 'int256', value: 16, expected: '0000000000000000000000000000000000000000000000000000000000000010'}); test({ type: 'int256', value: -1, expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); - test({ type: 'bytes32', value: 'gavofyork', expected: '6761766f66796f726b0000000000000000000000000000000000000000000000'}); - test({ type: 'bytes', value: 'gavofyork', expected: '0000000000000000000000000000000000000000000000000000000000000020' + + test({ type: 'bytes32', value: '0x6761766f66796f726b', + expected: '6761766f66796f726b0000000000000000000000000000000000000000000000'}); + test({ type: 'bytes32', value: '0x731a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b', + expected: '731a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b'}); + test({ type: 'bytes32', value: '0x02838654a83c213dae3698391eabbd54a5b6e1fb3452bc7fa4ea0dd5c8ce7e29', + expected: '02838654a83c213dae3698391eabbd54a5b6e1fb3452bc7fa4ea0dd5c8ce7e29'}); + test({ type: 'bytes', value: '0x6761766f66796f726b', + expected: '0000000000000000000000000000000000000000000000000000000000000020' + '0000000000000000000000000000000000000000000000000000000000000009' + '6761766f66796f726b0000000000000000000000000000000000000000000000'}); + test({ type: 'bytes', value: '0x731a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b', + expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000020' + + '731a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b'}); + test({ type: 'string', value: 'gavofyork', expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000009' + + '6761766f66796f726b0000000000000000000000000000000000000000000000'}); + test({ type: 'bytes', value: '0xc3a40000c3a4', + expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000006' + + 'c3a40000c3a40000000000000000000000000000000000000000000000000000'}); + test({ type: 'bytes32', value: '0xc3a40000c3a4', + expected: 'c3a40000c3a40000000000000000000000000000000000000000000000000000'}); + test({ type: 'string', value: '\xc3\xa4\x00\x00\xc3\xa4', + expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000006' + + 'c3a40000c3a40000000000000000000000000000000000000000000000000000'}); + test({ type: 'string', value: '\xc3', + expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000001' + + 'c300000000000000000000000000000000000000000000000000000000000000'}); test({ type: 'int[]', value: [], expected: '0000000000000000000000000000000000000000000000000000000000000020' + '0000000000000000000000000000000000000000000000000000000000000000'}); test({ type: 'int[]', value: [3], expected: '0000000000000000000000000000000000000000000000000000000000000020' + @@ -48,6 +75,25 @@ describe('lib/solidity/coder', function () { test({ type: 'ureal', value: 1, expected: '0000000000000000000000000000000100000000000000000000000000000000'}); test({ type: 'ureal', value: 2.125, expected: '0000000000000000000000000000000220000000000000000000000000000000'}); test({ type: 'ureal', value: 8.5, expected: '0000000000000000000000000000000880000000000000000000000000000000'}); + test({ type: 'bytes', value: '0x131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '231a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b', + expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000040' + + '131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '231a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b'}); + test({ type: 'bytes', value: '0x131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '231a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '331a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b', + expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000060' + + '131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '231a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '331a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b'}); + test({ type: 'string', value: 'welcome to ethereum. welcome to ethereum. welcome to ethereum.', + expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '000000000000000000000000000000000000000000000000000000000000003e' + + '77656c636f6d6520746f20657468657265756d2e2077656c636f6d6520746f20' + + '657468657265756d2e2077656c636f6d6520746f20657468657265756d2e0000'}); }); }); @@ -67,8 +113,9 @@ describe('lib/solidity/coder', function () { test({ types: ['int256'], values: [1], expected: '0000000000000000000000000000000000000000000000000000000000000001'}); test({ types: ['int256'], values: [16], expected: '0000000000000000000000000000000000000000000000000000000000000010'}); test({ types: ['int256'], values: [-1], expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); - test({ types: ['bytes32'], values: ['gavofyork'], expected: '6761766f66796f726b0000000000000000000000000000000000000000000000'}); - test({ types: ['bytes'], values: ['gavofyork'], expected: '0000000000000000000000000000000000000000000000000000000000000020' + + test({ types: ['bytes32'], values: ['0x6761766f66796f726b'], + expected: '6761766f66796f726b0000000000000000000000000000000000000000000000'}); + test({ types: ['string'], values: ['gavofyork'], expected: '0000000000000000000000000000000000000000000000000000000000000020' + '0000000000000000000000000000000000000000000000000000000000000009' + '6761766f66796f726b0000000000000000000000000000000000000000000000'}); test({ types: ['int[]'], values: [[3]], expected: '0000000000000000000000000000000000000000000000000000000000000020' + @@ -91,18 +138,18 @@ describe('lib/solidity/coder', function () { '0000000000000000000000000000000000000000000000000000000000000002' + '0000000000000000000000000000000000000000000000000000000000000003' + '0000000000000000000000000000000000000000000000000000000000000004'}); - test({ types: ['bytes32', 'int'], values: ['gavofyork', 5], + test({ types: ['bytes32', 'int'], values: ['0x6761766f66796f726b', 5], expected: '6761766f66796f726b0000000000000000000000000000000000000000000000' + '0000000000000000000000000000000000000000000000000000000000000005'}); - test({ types: ['int', 'bytes32'], values: [5, 'gavofyork'], + test({ types: ['int', 'bytes32'], values: [5, '0x6761766f66796f726b'], expected: '0000000000000000000000000000000000000000000000000000000000000005' + '6761766f66796f726b0000000000000000000000000000000000000000000000'}); - test({ types: ['bytes', 'int'], values: ['gavofyork', 5], + test({ types: ['string', 'int'], values: ['gavofyork', 5], expected: '0000000000000000000000000000000000000000000000000000000000000040' + '0000000000000000000000000000000000000000000000000000000000000005' + '0000000000000000000000000000000000000000000000000000000000000009' + '6761766f66796f726b0000000000000000000000000000000000000000000000'}); - test({ types: ['bytes', 'bool', 'int[]'], values: ['gavofyork', true, [1, 2, 3]], + test({ types: ['string', 'bool', 'int[]'], values: ['gavofyork', true, [1, 2, 3]], expected: '0000000000000000000000000000000000000000000000000000000000000060' + '0000000000000000000000000000000000000000000000000000000000000001' + '00000000000000000000000000000000000000000000000000000000000000a0' + @@ -112,7 +159,7 @@ describe('lib/solidity/coder', function () { '0000000000000000000000000000000000000000000000000000000000000001' + '0000000000000000000000000000000000000000000000000000000000000002' + '0000000000000000000000000000000000000000000000000000000000000003'}); - test({ types: ['bytes', 'int[]'], values: ['gavofyork', [1, 2, 3]], + test({ types: ['string', 'int[]'], values: ['gavofyork', [1, 2, 3]], expected: '0000000000000000000000000000000000000000000000000000000000000040' + '0000000000000000000000000000000000000000000000000000000000000080' + '0000000000000000000000000000000000000000000000000000000000000009' + @@ -121,12 +168,12 @@ describe('lib/solidity/coder', function () { '0000000000000000000000000000000000000000000000000000000000000001' + '0000000000000000000000000000000000000000000000000000000000000002' + '0000000000000000000000000000000000000000000000000000000000000003'}); - test({ types: ['int', 'bytes'], values: [5, 'gavofyork'], + test({ types: ['int', 'string'], values: [5, 'gavofyork'], expected: '0000000000000000000000000000000000000000000000000000000000000005' + '0000000000000000000000000000000000000000000000000000000000000040' + '0000000000000000000000000000000000000000000000000000000000000009' + '6761766f66796f726b0000000000000000000000000000000000000000000000'}); - test({ types: ['int', 'bytes', 'int', 'int', 'int', 'int[]'], values: [1, 'gavofyork', 2, 3, 4, [5, 6, 7]], + test({ types: ['int', 'string', 'int', 'int', 'int', 'int[]'], values: [1, 'gavofyork', 2, 3, 4, [5, 6, 7]], expected: '0000000000000000000000000000000000000000000000000000000000000001' + '00000000000000000000000000000000000000000000000000000000000000c0' + '0000000000000000000000000000000000000000000000000000000000000002' + @@ -139,6 +186,24 @@ describe('lib/solidity/coder', function () { '0000000000000000000000000000000000000000000000000000000000000005' + '0000000000000000000000000000000000000000000000000000000000000006' + '0000000000000000000000000000000000000000000000000000000000000007'}); + test({ types: ['int', 'bytes', 'int', 'bytes'], values: [ + 5, + '0x131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '231a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b', + 3, + '0x331a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '431a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b', + ], + expected: '0000000000000000000000000000000000000000000000000000000000000005' + + '0000000000000000000000000000000000000000000000000000000000000080' + + '0000000000000000000000000000000000000000000000000000000000000003' + + '00000000000000000000000000000000000000000000000000000000000000e0' + + '0000000000000000000000000000000000000000000000000000000000000040' + + '131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '231a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '0000000000000000000000000000000000000000000000000000000000000040' + + '331a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b' + + '431a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b'}); }); }); diff --git a/test/contract.js b/test/contract.js index 2632575f5..71ac20701 100644 --- a/test/contract.js +++ b/test/contract.js @@ -127,6 +127,147 @@ describe('web3.eth.contract', function () { }); }); + it('should create event filter and watch immediately', function (done) { + var provider = new FakeHttpProvider(); + web3.setProvider(provider); + web3.reset(); // reset different polls + var signature = 'Changed(address,uint256,uint256,uint256)'; + var step = 0; + provider.injectValidation(function (payload) { + if (step === 0) { + step = 1; + provider.injectResult('0x3'); + assert.equal(payload.jsonrpc, '2.0'); + assert.equal(payload.method, 'eth_newFilter'); + assert.deepEqual(payload.params[0], { + topics: [ + '0x' + sha3(signature), + '0x0000000000000000000000001234567890123456789012345678901234567890', + null + ], + address: '0x1234567890123456789012345678901234567890' + }); + } else if (step === 1) { + step = 2; + provider.injectResult([{ + address: address, + topics: [ + '0x' + sha3(signature), + '0x0000000000000000000000001234567890123456789012345678901234567890', + '0x0000000000000000000000000000000000000000000000000000000000000001' + ], + number: 2, + data: '0x0000000000000000000000000000000000000000000000000000000000000001' + + '0000000000000000000000000000000000000000000000000000000000000008' + }]); + assert.equal(payload.jsonrpc, '2.0'); + assert.equal(payload.method, 'eth_getFilterLogs'); + } else if (step === 2 && utils.isArray(payload)) { + provider.injectBatchResults([[{ + address: address, + topics: [ + '0x' + sha3(signature), + '0x0000000000000000000000001234567890123456789012345678901234567890', + '0x0000000000000000000000000000000000000000000000000000000000000001' + ], + number: 2, + data: '0x0000000000000000000000000000000000000000000000000000000000000001' + + '0000000000000000000000000000000000000000000000000000000000000008' + }]]); + var r = payload.filter(function (p) { + return p.jsonrpc === '2.0' && p.method === 'eth_getFilterChanges' && p.params[0] === '0x3'; + }); + assert.equal(r.length > 0, true); + } + }); + + var contract = web3.eth.contract(desc).at(address); + + var res = 0; + var event = contract.Changed({from: address}, function(err, result) { + assert.equal(result.args.from, address); + assert.equal(result.args.amount, 1); + assert.equal(result.args.t1, 1); + assert.equal(result.args.t2, 8); + res++; + if (res === 2) { + done(); + } + }); + }); + + it('should create all event filter', function (done) { + var provider = new FakeHttpProvider(); + web3.setProvider(provider); + web3.reset(); // reset different polls + var signature = 'Changed(address,uint256,uint256,uint256)'; + var step = 0; + provider.injectValidation(function (payload) { + if (step === 0) { + step = 1; + provider.injectResult('0x3'); + assert.equal(payload.jsonrpc, '2.0'); + assert.equal(payload.method, 'eth_newFilter'); + assert.deepEqual(payload.params[0], { + topics: [ + null, + null, + null, + null, + null + ], + address: '0x1234567890123456789012345678901234567890' + }); + } else if (step === 1) { + step = 2; + provider.injectResult([{ + address: address, + topics: [ + '0x' + sha3(signature), + '0x0000000000000000000000001234567890123456789012345678901234567890', + '0x0000000000000000000000000000000000000000000000000000000000000001' + ], + number: 2, + data: '0x0000000000000000000000000000000000000000000000000000000000000001' + + '0000000000000000000000000000000000000000000000000000000000000008' + }]); + assert.equal(payload.jsonrpc, '2.0'); + assert.equal(payload.method, 'eth_getFilterLogs'); + } else if (step === 2 && utils.isArray(payload)) { + provider.injectBatchResults([[{ + address: address, + topics: [ + '0x' + sha3(signature), + '0x0000000000000000000000001234567890123456789012345678901234567890', + '0x0000000000000000000000000000000000000000000000000000000000000001' + ], + number: 2, + data: '0x0000000000000000000000000000000000000000000000000000000000000001' + + '0000000000000000000000000000000000000000000000000000000000000008' + }]]); + var r = payload.filter(function (p) { + return p.jsonrpc === '2.0' && p.method === 'eth_getFilterChanges' && p.params[0] === '0x3'; + }); + assert.equal(r.length > 0, true); + } + }); + + var contract = web3.eth.contract(desc).at(address); + + var res = 0; + var event = contract.allEvents(); + event.watch(function(err, result) { + assert.equal(result.args.from, address); + assert.equal(result.args.amount, 1); + assert.equal(result.args.t1, 1); + assert.equal(result.args.t2, 8); + res++; + if (res === 2) { + done(); + } + }); + }); + it('should call constant function', function () { var provider = new FakeHttpProvider(); web3.setProvider(provider); diff --git a/test/polling.js b/test/polling.js index 8bd2b041c..88cfee4cc 100644 --- a/test/polling.js +++ b/test/polling.js @@ -63,6 +63,42 @@ var testPolling = function (tests) { var filter = web3[test.protocol].filter.apply(null, test.args); provider.injectBatchResults([test.secondResult]); filter.watch(function (err, result) { + console.log(err, result); + + if (test.err) { + // todo + } else { + assert.equal(result, test.secondResult[0]); + } + done(); + + }); + }); + it('should create && successfully poll filter when passed as callback', function (done) { + + // given + var provider = new FakeHttpProvider(); + web3.setProvider(provider); + web3.reset(); + provider.injectResult(test.firstResult); + var step = 0; + provider.injectValidation(function (payload) { + if (step === 0) { + step = 1; + assert.equal(payload.jsonrpc, '2.0'); + assert.equal(payload.method, test.firstPayload.method); + assert.deepEqual(payload.params, test.firstPayload.params); + } else if (step === 1 && utils.isArray(payload)) { + var r = payload.filter(function (p) { + return p.jsonrpc === '2.0' && p.method === test.secondPayload.method && p.params[0] === test.firstResult; + }); + assert.equal(r.length > 0, true); + } + + }); + + // add callback + test.args.push(function (err, result) { if (test.err) { // todo } else { @@ -71,6 +107,10 @@ var testPolling = function (tests) { done(); }); + + // when + var filter = web3[test.protocol].filter.apply(null, test.args); + provider.injectBatchResults([test.secondResult]); }); }); }); diff --git a/test/utils.toHex.js b/test/utils.toHex.js index 0a328e345..fdf88cd38 100644 --- a/test/utils.toHex.js +++ b/test/utils.toHex.js @@ -14,6 +14,7 @@ var tests = [ { value: '-0x1', expected: '-0x1'}, { value: '-15', expected: '-0xf'}, { value: '-0xf', expected: '-0xf'}, + { value: '0x657468657265756d', expected: '0x657468657265756d'}, { value: '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd', expected: '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd'}, { value: '-0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', expected: '-0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}, { value: '-0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd', expected: '-0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd'}, diff --git a/test/web3.eth.filter.methods.js b/test/web3.eth.filter.methods.js index f40f3d0ac..c15d720e2 100644 --- a/test/web3.eth.filter.methods.js +++ b/test/web3.eth.filter.methods.js @@ -14,10 +14,10 @@ var implementation = { describe('web3.eth.filter', function () { describe('methods', function () { - //var f = filter({}, implementation); + // var f = filter({}, implementation); - //u.methodExists(f, 'watch'); - //u.methodExists(f, 'stopWatching'); - //u.methodExists(f, 'get'); + // u.methodExists(f, 'watch'); + // u.methodExists(f, 'stopWatching'); + // u.methodExists(f, 'get'); }); }); From f03c12ca240efa0f371f3a26a0cbf3e971b451ec Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 26 Jun 2015 15:06:01 +0200 Subject: [PATCH 066/290] Adjust CL miner work batch size properly We are now propery adjusting the batch size of the OpenCL miner properly depending on the execution time of the last search. --- libethash-cl/ethash_cl_miner.cpp | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 3a72810fa..59a4b4f90 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -456,8 +456,7 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook uint64_t start_nonce = uniform_int_distribution()(engine); for (;; start_nonce += m_batchSize) { -// chrono::high_resolution_clock::time_point t = chrono::high_resolution_clock::now(); - + chrono::high_resolution_clock::time_point t = chrono::high_resolution_clock::now(); // supply output buffer to kernel m_searchKernel.setArg(0, m_searchBuffer[buf]); if (m_dagChunksCount == 1) @@ -497,19 +496,23 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook pending.pop(); } -/* chrono::high_resolution_clock::duration d = chrono::high_resolution_clock::now() - t; - if (d > chrono::milliseconds(_msPerBatch * 10 / 9)) + // adjust batch size depending on last search time + auto d = chrono::duration_cast(chrono::high_resolution_clock::now() - t); + if (d != chrono::milliseconds(0)) // if duration is zero, we did not get in the actual search so adjust nothing { - cerr << "Batch of" << m_batchSize << "took" << chrono::duration_cast(d).count() << "ms, >>" << _msPerBatch << "ms."; - m_batchSize = max(128, m_batchSize * 9 / 10); - cerr << "New batch size" << m_batchSize; + if (d > chrono::milliseconds(_msPerBatch * 10 / 9)) + { + // cerr << "Batch of " << m_batchSize << " took " << chrono::duration_cast(d).count() << " ms, >> " << _msPerBatch << " ms." << endl; + m_batchSize = max(128, m_batchSize * 9 / 10); + // cerr << "New batch size" << m_batchSize << endl; + } + else if (d < chrono::milliseconds(_msPerBatch * 9 / 10)) + { + // cerr << "Batch of " << m_batchSize << " took " << chrono::duration_cast(d).count() << " ms, << " << _msPerBatch << " ms." << endl; + m_batchSize = m_batchSize * 10 / 9; + // cerr << "New batch size" << m_batchSize << endl; + } } - else if (d < chrono::milliseconds(_msPerBatch * 9 / 10)) - { - cerr << "Batch of" << m_batchSize << "took" << chrono::duration_cast(d).count() << "ms, <<" << _msPerBatch << "ms."; - m_batchSize = m_batchSize * 10 / 9; - cerr << "New batch size" << m_batchSize; - }*/ } // not safe to return until this is ready From f51033dc75a766e0e2f71b58f1d690c02f98b3f0 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 29 Jun 2015 13:05:11 +0200 Subject: [PATCH 067/290] CL Global and local work size adjustments - Giving names to the variables that properly reflect the API - Making sure that the limitations that are stated in clEnqueueNDRangeKernel() documentation are adhered to --- libethash-cl/ethash_cl_miner.cpp | 30 +++++++++++++++++++----------- libethash-cl/ethash_cl_miner.h | 3 ++- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 59a4b4f90..893c1be9c 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -301,6 +301,11 @@ bool ethash_cl_miner::init( // use requested workgroup size, but we require multiple of 8 m_workgroupSize = ((_workgroupSize + 7) / 8) * 8; + // make sure that global work size is evenly divisible by the local workgroup size + if (m_globalWorkSize % m_workgroupSize != 0) + m_globalWorkSize = ((m_globalWorkSize / m_workgroupSize) + 1) * m_workgroupSize; + // remember the device's address bits + m_deviceBits = device.getInfo(); // patch source code // note: ETHASH_CL_MINER_KERNEL is simply ethash_cl_miner_kernel.cl compiled @@ -454,7 +459,7 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook unsigned buf = 0; random_device engine; uint64_t start_nonce = uniform_int_distribution()(engine); - for (;; start_nonce += m_batchSize) + for (;; start_nonce += m_globalWorkSize) { chrono::high_resolution_clock::time_point t = chrono::high_resolution_clock::now(); // supply output buffer to kernel @@ -465,7 +470,7 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook m_searchKernel.setArg(6, start_nonce); // execute it! - m_queue.enqueueNDRangeKernel(m_searchKernel, cl::NullRange, m_batchSize, m_workgroupSize); + m_queue.enqueueNDRangeKernel(m_searchKernel, cl::NullRange, m_globalWorkSize, m_workgroupSize); pending.push({ start_nonce, buf }); buf = (buf + 1) % c_bufferCount; @@ -485,7 +490,7 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook m_queue.enqueueUnmapMemObject(m_searchBuffer[batch.buf], results); bool exit = num_found && hook.found(nonces, num_found); - exit |= hook.searched(batch.start_nonce, m_batchSize); // always report searched before exit + exit |= hook.searched(batch.start_nonce, m_globalWorkSize); // always report searched before exit if (exit) break; @@ -496,21 +501,24 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook pending.pop(); } - // adjust batch size depending on last search time + // adjust global work size depending on last search time + // Global work size must be: + // - less than or equal to 2 ^ DEVICE_BITS - 1 + // - divisible by lobal work size (workgroup size) auto d = chrono::duration_cast(chrono::high_resolution_clock::now() - t); - if (d != chrono::milliseconds(0)) // if duration is zero, we did not get in the actual search so adjust nothing + if (d != chrono::milliseconds(0)) // if duration is zero, we did not get in the actual searh/or search not finished { if (d > chrono::milliseconds(_msPerBatch * 10 / 9)) { - // cerr << "Batch of " << m_batchSize << " took " << chrono::duration_cast(d).count() << " ms, >> " << _msPerBatch << " ms." << endl; - m_batchSize = max(128, m_batchSize * 9 / 10); - // cerr << "New batch size" << m_batchSize << endl; + // cerr << "Batch of " << m_globalWorkSize << " took " << chrono::duration_cast(d).count() << " ms, >> " << _msPerBatch << " ms." << endl; + m_globalWorkSize = max(128, m_globalWorkSize + m_workgroupSize); + // cerr << "New global work size" << m_globalWorkSize << endl; } else if (d < chrono::milliseconds(_msPerBatch * 9 / 10)) { - // cerr << "Batch of " << m_batchSize << " took " << chrono::duration_cast(d).count() << " ms, << " << _msPerBatch << " ms." << endl; - m_batchSize = m_batchSize * 10 / 9; - // cerr << "New batch size" << m_batchSize << endl; + // cerr << "Batch of " << m_globalWorkSize << " took " << chrono::duration_cast(d).count() << " ms, << " << _msPerBatch << " ms." << endl; + m_globalWorkSize = min(pow(2, m_deviceBits) - 1, m_globalWorkSize - m_workgroupSize); + // cerr << "New global work size" << m_globalWorkSize << endl; } } } diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h index 73bf7e94a..16d0b52de 100644 --- a/libethash-cl/ethash_cl_miner.h +++ b/libethash-cl/ethash_cl_miner.h @@ -77,8 +77,9 @@ private: cl::Buffer m_hashBuffer[c_bufferCount]; cl::Buffer m_searchBuffer[c_bufferCount]; unsigned m_workgroupSize; - unsigned m_batchSize = c_searchBatchSize; + unsigned m_globalWorkSize = c_searchBatchSize; bool m_openclOnePointOne; + unsigned m_deviceBits; /// Allow CPU to appear as an OpenCL device or not. Default is false static bool s_allowCPU; From 7501191b405e73685d21cb14ba11c8bd1ed43710 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 29 Jun 2015 15:37:38 +0200 Subject: [PATCH 068/290] GlobalWork size should never be less than local size --- libethash-cl/ethash_cl_miner.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 893c1be9c..7132cc04d 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -461,7 +461,7 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook uint64_t start_nonce = uniform_int_distribution()(engine); for (;; start_nonce += m_globalWorkSize) { - chrono::high_resolution_clock::time_point t = chrono::high_resolution_clock::now(); + auto t = chrono::high_resolution_clock::now(); // supply output buffer to kernel m_searchKernel.setArg(0, m_searchBuffer[buf]); if (m_dagChunksCount == 1) @@ -518,6 +518,8 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook { // cerr << "Batch of " << m_globalWorkSize << " took " << chrono::duration_cast(d).count() << " ms, << " << _msPerBatch << " ms." << endl; m_globalWorkSize = min(pow(2, m_deviceBits) - 1, m_globalWorkSize - m_workgroupSize); + // Global work size should never be less than the workgroup size + m_globalWorkSize = max(m_workgroupSize, m_globalWorkSize); // cerr << "New global work size" << m_globalWorkSize << endl; } } From 15fc63d6a255de5f8c5a4e93edada90bf2ccccce Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 30 Jun 2015 13:49:12 +0200 Subject: [PATCH 069/290] New OpenCL arguments - Adding an argument to specify OpenCL global work size. - Adding an argument to specify milliseconds per global work size (msPerBatch). If this is 0 then no adjustment of the global work size happens. --- ethminer/MinerAux.h | 25 +++++++++++++++++ libethash-cl/ethash_cl_miner.cpp | 47 +++++++++++++++++++------------- libethash-cl/ethash_cl_miner.h | 13 +++++++-- libethcore/Ethash.cpp | 4 ++- libethcore/Ethash.h | 4 ++- 5 files changed, 70 insertions(+), 23 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index ec6ee57e7..50ff93070 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #if ETH_JSONRPC || !ETH_TRUE #include @@ -128,6 +129,24 @@ public: cerr << "Bad " << arg << " option: " << argv[i] << endl; BOOST_THROW_EXCEPTION(BadArgument()); } + else if (arg == "--cl-global-work-size" && i + 1 < argc) + try { + m_globalWorkSize = stol(argv[++i]); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + BOOST_THROW_EXCEPTION(BadArgument()); + } + else if (arg == "--cl-ms-per-batch" && i + 1 < argc) + try { + m_msPerBatch = stol(argv[++i]); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + BOOST_THROW_EXCEPTION(BadArgument()); + } else if (arg == "--list-devices") m_shouldListDevices = true; else if (arg == "--allow-opencl-cpu") @@ -266,6 +285,8 @@ public: else if (m_minerType == MinerType::GPU) { if (!ProofOfWork::GPUMiner::configureGPU( + m_globalWorkSize, + m_msPerBatch, m_openclPlatform, m_openclDevice, m_clAllowCPU, @@ -318,6 +339,8 @@ public: << " --list-devices List the detected OpenCL devices and exit." << endl << " --current-block Let the miner know the current block number at configuration time. Will help determine DAG size and required GPU memory." << endl << " --cl-extragpu-mem Set the memory (in MB) you believe your GPU requires for stuff other than mining. Windows rendering e.t.c.." << endl + << " --cl-global-work Set the OpenCL global work size. Default is " << toString(CL_DEFAULT_GLOBAL_WORK_SIZE) << endl + << " --cl-ms-per-batch Set the OpenCL target milliseconds per batch (global workgroup size). Default is " << toString(CL_DEFAULT_MS_PER_BATCH) << ". If 0 is given then no autoadjustment of global work size will happen" << endl ; } @@ -506,6 +529,8 @@ private: unsigned m_miningThreads = UINT_MAX; bool m_shouldListDevices = false; bool m_clAllowCPU = false; + unsigned m_globalWorkSize = CL_DEFAULT_GLOBAL_WORK_SIZE; + unsigned m_msPerBatch = CL_DEFAULT_MS_PER_BATCH; boost::optional m_currentBlock; // default value is 350MB of GPU memory for other stuff (windows system rendering, e.t.c.) unsigned m_extraGPUMemory = 350000000; diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 7132cc04d..02c9609fa 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -140,11 +140,15 @@ unsigned ethash_cl_miner::getNumDevices(unsigned _platformId) bool ethash_cl_miner::configureGPU( unsigned _platformId, + unsigned _globalWorkSize, + unsigned _msPerBatch, bool _allowCPU, unsigned _extraGPUMemory, boost::optional _currentBlock ) { + s_initialGlobalWorkSize = _globalWorkSize; + s_msPerBatch = _msPerBatch; s_allowCPU = _allowCPU; s_extraRequiredGPUMem = _extraGPUMemory; // by default let's only consider the DAG of the first epoch @@ -175,6 +179,8 @@ bool ethash_cl_miner::configureGPU( bool ethash_cl_miner::s_allowCPU = false; unsigned ethash_cl_miner::s_extraRequiredGPUMem; +unsigned ethash_cl_miner::s_msPerBatch = CL_DEFAULT_MS_PER_BATCH; +unsigned ethash_cl_miner::s_initialGlobalWorkSize = CL_DEFAULT_GLOBAL_WORK_SIZE; bool ethash_cl_miner::searchForAllDevices(function _callback) { @@ -302,6 +308,7 @@ bool ethash_cl_miner::init( // use requested workgroup size, but we require multiple of 8 m_workgroupSize = ((_workgroupSize + 7) / 8) * 8; // make sure that global work size is evenly divisible by the local workgroup size + m_globalWorkSize = s_initialGlobalWorkSize; if (m_globalWorkSize % m_workgroupSize != 0) m_globalWorkSize = ((m_globalWorkSize / m_workgroupSize) + 1) * m_workgroupSize; // remember the device's address bits @@ -420,9 +427,8 @@ bool ethash_cl_miner::init( return true; } -void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook& hook, unsigned _msPerBatch) +void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook& hook) { - (void)_msPerBatch; try { struct pending_batch @@ -502,25 +508,28 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook } // adjust global work size depending on last search time - // Global work size must be: - // - less than or equal to 2 ^ DEVICE_BITS - 1 - // - divisible by lobal work size (workgroup size) - auto d = chrono::duration_cast(chrono::high_resolution_clock::now() - t); - if (d != chrono::milliseconds(0)) // if duration is zero, we did not get in the actual searh/or search not finished + if (s_msPerBatch) { - if (d > chrono::milliseconds(_msPerBatch * 10 / 9)) + // Global work size must be: + // - less than or equal to 2 ^ DEVICE_BITS - 1 + // - divisible by lobal work size (workgroup size) + auto d = chrono::duration_cast(chrono::high_resolution_clock::now() - t); + if (d != chrono::milliseconds(0)) // if duration is zero, we did not get in the actual searh/or search not finished { - // cerr << "Batch of " << m_globalWorkSize << " took " << chrono::duration_cast(d).count() << " ms, >> " << _msPerBatch << " ms." << endl; - m_globalWorkSize = max(128, m_globalWorkSize + m_workgroupSize); - // cerr << "New global work size" << m_globalWorkSize << endl; - } - else if (d < chrono::milliseconds(_msPerBatch * 9 / 10)) - { - // cerr << "Batch of " << m_globalWorkSize << " took " << chrono::duration_cast(d).count() << " ms, << " << _msPerBatch << " ms." << endl; - m_globalWorkSize = min(pow(2, m_deviceBits) - 1, m_globalWorkSize - m_workgroupSize); - // Global work size should never be less than the workgroup size - m_globalWorkSize = max(m_workgroupSize, m_globalWorkSize); - // cerr << "New global work size" << m_globalWorkSize << endl; + if (d > chrono::milliseconds(s_msPerBatch * 10 / 9)) + { + // cerr << "Batch of " << m_globalWorkSize << " took " << chrono::duration_cast(d).count() << " ms, >> " << _msPerBatch << " ms." << endl; + m_globalWorkSize = max(128, m_globalWorkSize + m_workgroupSize); + // cerr << "New global work size" << m_globalWorkSize << endl; + } + else if (d < chrono::milliseconds(s_msPerBatch * 9 / 10)) + { + // cerr << "Batch of " << m_globalWorkSize << " took " << chrono::duration_cast(d).count() << " ms, << " << _msPerBatch << " ms." << endl; + m_globalWorkSize = min(pow(2, m_deviceBits) - 1, m_globalWorkSize - m_workgroupSize); + // Global work size should never be less than the workgroup size + m_globalWorkSize = max(m_workgroupSize, m_globalWorkSize); + // cerr << "New global work size" << m_globalWorkSize << endl; + } } } } diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h index 16d0b52de..e78108288 100644 --- a/libethash-cl/ethash_cl_miner.h +++ b/libethash-cl/ethash_cl_miner.h @@ -17,6 +17,9 @@ #include #include +#define CL_DEFAULT_GLOBAL_WORK_SIZE 1024 * 16 +#define CL_DEFAULT_MS_PER_BATCH 100 + class ethash_cl_miner { private: @@ -45,6 +48,8 @@ public: static void listDevices(); static bool configureGPU( unsigned _platformId, + unsigned _globalWorkSize, + unsigned _msPerBatch, bool _allowCPU, unsigned _extraGPUMemory, boost::optional _currentBlock @@ -58,7 +63,7 @@ public: unsigned _deviceId = 0 ); void finish(); - void search(uint8_t const* _header, uint64_t _target, search_hook& _hook, unsigned _msPerBatch = 100); + void search(uint8_t const* _header, uint64_t _target, search_hook& _hook); void hash_chunk(uint8_t* _ret, uint8_t const* _header, uint64_t _nonce, unsigned _count); void search_chunk(uint8_t const*_header, uint64_t _target, search_hook& _hook); @@ -77,10 +82,14 @@ private: cl::Buffer m_hashBuffer[c_bufferCount]; cl::Buffer m_searchBuffer[c_bufferCount]; unsigned m_workgroupSize; - unsigned m_globalWorkSize = c_searchBatchSize; + unsigned m_globalWorkSize; bool m_openclOnePointOne; unsigned m_deviceBits; + /// The initial global work size for the searches + static unsigned s_initialGlobalWorkSize; + /// The target milliseconds per batch for the search. If 0, then no adjustment will happen + static unsigned s_msPerBatch; /// Allow CPU to appear as an OpenCL device or not. Default is false static bool s_allowCPU; /// GPU memory required for other things, like window rendering e.t.c. diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 46d19d164..296b4a605 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -409,6 +409,8 @@ void Ethash::GPUMiner::listDevices() } bool Ethash::GPUMiner::configureGPU( + unsigned _globalWorkSize, + unsigned _msPerBatch, unsigned _platformId, unsigned _deviceId, bool _allowCPU, @@ -418,7 +420,7 @@ bool Ethash::GPUMiner::configureGPU( { s_platformId = _platformId; s_deviceId = _deviceId; - return ethash_cl_miner::configureGPU(_platformId, _allowCPU, _extraGPUMemory, _currentBlock); + return ethash_cl_miner::configureGPU(_globalWorkSize, _msPerBatch, _allowCPU, _extraGPUMemory, _currentBlock); } #endif diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 11e012df5..4106229ed 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -88,7 +88,7 @@ public: static unsigned instances() { return s_numInstances > 0 ? s_numInstances : std::thread::hardware_concurrency(); } static std::string platformInfo(); static void listDevices() {} - static bool configureGPU(unsigned, unsigned, bool, unsigned, boost::optional) { return false; } + static bool configureGPU(unsigned, unsigned, unsigned, unsigned, bool, unsigned, boost::optional) { return false; } static void setNumInstances(unsigned _instances) { s_numInstances = std::min(_instances, std::thread::hardware_concurrency()); } protected: void kickOff() override @@ -118,6 +118,8 @@ public: static unsigned getNumDevices(); static void listDevices(); static bool configureGPU( + unsigned _globalWorkSize, + unsigned _msPerBatch, unsigned _platformId, unsigned _deviceId, bool _allowCPU, From db54ff3b4a9ca7ba7c0d1697d4741c4e3c0511f8 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 30 Jun 2015 14:56:30 +0200 Subject: [PATCH 070/290] CL Argument for local work size - Now the user can also set the local work size (workgroup size) - In addition the global work size is specified in the command line only as a multiplier of the local work size. --- ethminer/MinerAux.h | 25 +++++++++++++++++-------- libethash-cl/ethash_cl_miner.cpp | 22 +++++++++++----------- libethash-cl/ethash_cl_miner.h | 11 ++++++++--- libethcore/Ethash.cpp | 26 +++++++++++++++++++++++--- libethcore/Ethash.h | 5 +++-- 5 files changed, 62 insertions(+), 27 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 50ff93070..9c199cecb 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -129,9 +129,18 @@ public: cerr << "Bad " << arg << " option: " << argv[i] << endl; BOOST_THROW_EXCEPTION(BadArgument()); } - else if (arg == "--cl-global-work-size" && i + 1 < argc) + else if (arg == "--cl-global-work" && i + 1 < argc) try { - m_globalWorkSize = stol(argv[++i]); + m_globalWorkSizeMultiplier = stol(argv[++i]); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + BOOST_THROW_EXCEPTION(BadArgument()); + } + else if (arg == "--cl-local-work" && i + 1 < argc) + try { + m_localWorkSize = stol(argv[++i]); } catch (...) { @@ -285,7 +294,8 @@ public: else if (m_minerType == MinerType::GPU) { if (!ProofOfWork::GPUMiner::configureGPU( - m_globalWorkSize, + m_localWorkSize, + m_globalWorkSizeMultiplier, m_msPerBatch, m_openclPlatform, m_openclDevice, @@ -293,10 +303,7 @@ public: m_extraGPUMemory, m_currentBlock )) - { - cout << "No GPU device with sufficient memory was found. Can't GPU mine. Remove the -G argument" << endl; exit(1); - } ProofOfWork::GPUMiner::setNumInstances(m_miningThreads); } if (mode == OperationMode::DAGInit) @@ -339,7 +346,8 @@ public: << " --list-devices List the detected OpenCL devices and exit." << endl << " --current-block Let the miner know the current block number at configuration time. Will help determine DAG size and required GPU memory." << endl << " --cl-extragpu-mem Set the memory (in MB) you believe your GPU requires for stuff other than mining. Windows rendering e.t.c.." << endl - << " --cl-global-work Set the OpenCL global work size. Default is " << toString(CL_DEFAULT_GLOBAL_WORK_SIZE) << endl + << " --cl-local-work Set the OpenCL local work size. Default is " << toString(CL_DEFAULT_LOCAL_WORK_SIZE) << endl + << " --cl-global-work Set the OpenCL global work size as a multiple of the local work size. Default is " << toString(CL_DEFAULT_GLOBAL_WORK_SIZE_MULTIPLIER) << " * " << toString(CL_DEFAULT_LOCAL_WORK_SIZE) << endl << " --cl-ms-per-batch Set the OpenCL target milliseconds per batch (global workgroup size). Default is " << toString(CL_DEFAULT_MS_PER_BATCH) << ". If 0 is given then no autoadjustment of global work size will happen" << endl ; } @@ -529,7 +537,8 @@ private: unsigned m_miningThreads = UINT_MAX; bool m_shouldListDevices = false; bool m_clAllowCPU = false; - unsigned m_globalWorkSize = CL_DEFAULT_GLOBAL_WORK_SIZE; + unsigned m_globalWorkSizeMultiplier = CL_DEFAULT_GLOBAL_WORK_SIZE_MULTIPLIER; + unsigned m_localWorkSize = CL_DEFAULT_LOCAL_WORK_SIZE; unsigned m_msPerBatch = CL_DEFAULT_MS_PER_BATCH; boost::optional m_currentBlock; // default value is 350MB of GPU memory for other stuff (windows system rendering, e.t.c.) diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 02c9609fa..8c22f7f1b 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -140,6 +140,7 @@ unsigned ethash_cl_miner::getNumDevices(unsigned _platformId) bool ethash_cl_miner::configureGPU( unsigned _platformId, + unsigned _localWorkSize, unsigned _globalWorkSize, unsigned _msPerBatch, bool _allowCPU, @@ -147,6 +148,7 @@ bool ethash_cl_miner::configureGPU( boost::optional _currentBlock ) { + s_workgroupSize = _localWorkSize; s_initialGlobalWorkSize = _globalWorkSize; s_msPerBatch = _msPerBatch; s_allowCPU = _allowCPU; @@ -180,7 +182,8 @@ bool ethash_cl_miner::configureGPU( bool ethash_cl_miner::s_allowCPU = false; unsigned ethash_cl_miner::s_extraRequiredGPUMem; unsigned ethash_cl_miner::s_msPerBatch = CL_DEFAULT_MS_PER_BATCH; -unsigned ethash_cl_miner::s_initialGlobalWorkSize = CL_DEFAULT_GLOBAL_WORK_SIZE; +unsigned ethash_cl_miner::s_workgroupSize = CL_DEFAULT_LOCAL_WORK_SIZE; +unsigned ethash_cl_miner::s_initialGlobalWorkSize = CL_DEFAULT_GLOBAL_WORK_SIZE_MULTIPLIER * CL_DEFAULT_LOCAL_WORK_SIZE; bool ethash_cl_miner::searchForAllDevices(function _callback) { @@ -260,7 +263,6 @@ void ethash_cl_miner::finish() bool ethash_cl_miner::init( uint8_t const* _dag, uint64_t _dagSize, - unsigned _workgroupSize, unsigned _platformId, unsigned _deviceId ) @@ -305,12 +307,10 @@ bool ethash_cl_miner::init( m_context = cl::Context(vector(&device, &device + 1)); m_queue = cl::CommandQueue(m_context, device); - // use requested workgroup size, but we require multiple of 8 - m_workgroupSize = ((_workgroupSize + 7) / 8) * 8; // make sure that global work size is evenly divisible by the local workgroup size m_globalWorkSize = s_initialGlobalWorkSize; - if (m_globalWorkSize % m_workgroupSize != 0) - m_globalWorkSize = ((m_globalWorkSize / m_workgroupSize) + 1) * m_workgroupSize; + if (m_globalWorkSize % s_workgroupSize != 0) + m_globalWorkSize = ((m_globalWorkSize / s_workgroupSize) + 1) * s_workgroupSize; // remember the device's address bits m_deviceBits = device.getInfo(); @@ -318,7 +318,7 @@ bool ethash_cl_miner::init( // note: ETHASH_CL_MINER_KERNEL is simply ethash_cl_miner_kernel.cl compiled // into a byte array by bin2h.cmake. There is no need to load the file by hand in runtime string code(ETHASH_CL_MINER_KERNEL, ETHASH_CL_MINER_KERNEL + ETHASH_CL_MINER_KERNEL_SIZE); - addDefinition(code, "GROUP_SIZE", m_workgroupSize); + addDefinition(code, "GROUP_SIZE", s_workgroupSize); addDefinition(code, "DAG_SIZE", (unsigned)(_dagSize / ETHASH_MIX_BYTES)); addDefinition(code, "ACCESSES", ETHASH_ACCESSES); addDefinition(code, "MAX_OUTPUTS", c_maxSearchResults); @@ -476,7 +476,7 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook m_searchKernel.setArg(6, start_nonce); // execute it! - m_queue.enqueueNDRangeKernel(m_searchKernel, cl::NullRange, m_globalWorkSize, m_workgroupSize); + m_queue.enqueueNDRangeKernel(m_searchKernel, cl::NullRange, m_globalWorkSize, s_workgroupSize); pending.push({ start_nonce, buf }); buf = (buf + 1) % c_bufferCount; @@ -519,15 +519,15 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook if (d > chrono::milliseconds(s_msPerBatch * 10 / 9)) { // cerr << "Batch of " << m_globalWorkSize << " took " << chrono::duration_cast(d).count() << " ms, >> " << _msPerBatch << " ms." << endl; - m_globalWorkSize = max(128, m_globalWorkSize + m_workgroupSize); + m_globalWorkSize = max(128, m_globalWorkSize + s_workgroupSize); // cerr << "New global work size" << m_globalWorkSize << endl; } else if (d < chrono::milliseconds(s_msPerBatch * 9 / 10)) { // cerr << "Batch of " << m_globalWorkSize << " took " << chrono::duration_cast(d).count() << " ms, << " << _msPerBatch << " ms." << endl; - m_globalWorkSize = min(pow(2, m_deviceBits) - 1, m_globalWorkSize - m_workgroupSize); + m_globalWorkSize = min(pow(2, m_deviceBits) - 1, m_globalWorkSize - s_workgroupSize); // Global work size should never be less than the workgroup size - m_globalWorkSize = max(m_workgroupSize, m_globalWorkSize); + m_globalWorkSize = max(s_workgroupSize, m_globalWorkSize); // cerr << "New global work size" << m_globalWorkSize << endl; } } diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h index e78108288..c60ee1881 100644 --- a/libethash-cl/ethash_cl_miner.h +++ b/libethash-cl/ethash_cl_miner.h @@ -17,7 +17,11 @@ #include #include -#define CL_DEFAULT_GLOBAL_WORK_SIZE 1024 * 16 +/// Default value of the local work size. Also known as workgroup size. +#define CL_DEFAULT_LOCAL_WORK_SIZE 64 +/// Default value of the global work size as a multiplier of the local work size +#define CL_DEFAULT_GLOBAL_WORK_SIZE_MULTIPLIER 512 // * CL_DEFAULT_LOCAL_WORK_SIZE +/// Default value of the milliseconds per global work size (per batch) #define CL_DEFAULT_MS_PER_BATCH 100 class ethash_cl_miner @@ -48,6 +52,7 @@ public: static void listDevices(); static bool configureGPU( unsigned _platformId, + unsigned _localWorkSize, unsigned _globalWorkSize, unsigned _msPerBatch, bool _allowCPU, @@ -58,7 +63,6 @@ public: bool init( uint8_t const* _dag, uint64_t _dagSize, - unsigned _workgroupSize = 64, unsigned _platformId = 0, unsigned _deviceId = 0 ); @@ -81,11 +85,12 @@ private: cl::Buffer m_header; cl::Buffer m_hashBuffer[c_bufferCount]; cl::Buffer m_searchBuffer[c_bufferCount]; - unsigned m_workgroupSize; unsigned m_globalWorkSize; bool m_openclOnePointOne; unsigned m_deviceBits; + /// The local work size for the search + static unsigned s_workgroupSize; /// The initial global work size for the searches static unsigned s_initialGlobalWorkSize; /// The target milliseconds per batch for the search. If 0, then no adjustment will happen diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 296b4a605..6c1f7d856 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -373,7 +373,7 @@ void Ethash::GPUMiner::workLoop() this_thread::sleep_for(chrono::milliseconds(500)); } bytesConstRef dagData = dag->data(); - m_miner->init(dagData.data(), dagData.size(), 32, s_platformId, device); + m_miner->init(dagData.data(), dagData.size(), s_platformId, device); } uint64_t upper64OfBoundary = (uint64_t)(u64)((u256)w.boundary >> 192); @@ -409,7 +409,8 @@ void Ethash::GPUMiner::listDevices() } bool Ethash::GPUMiner::configureGPU( - unsigned _globalWorkSize, + unsigned _localWorkSize, + unsigned _globalWorkSizeMultiplier, unsigned _msPerBatch, unsigned _platformId, unsigned _deviceId, @@ -420,7 +421,26 @@ bool Ethash::GPUMiner::configureGPU( { s_platformId = _platformId; s_deviceId = _deviceId; - return ethash_cl_miner::configureGPU(_globalWorkSize, _msPerBatch, _allowCPU, _extraGPUMemory, _currentBlock); + + if (_localWorkSize != 32 && _localWorkSize != 64 && _localWorkSize != 128) + { + cout << "Given localWorkSize of " << toString(_localWorkSize) << "is invalid. Must be either 32,64, or 128" << endl; + return false; + } + + if (!ethash_cl_miner::configureGPU( + _localWorkSize, + _globalWorkSizeMultiplier * _localWorkSize, + _msPerBatch, + _allowCPU, + _extraGPUMemory, + _currentBlock) + ) + { + cout << "No GPU device with sufficient memory was found. Can't GPU mine. Remove the -G argument" << endl; + return false; + } + return true; } #endif diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 4106229ed..e9ddf16ca 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -88,7 +88,7 @@ public: static unsigned instances() { return s_numInstances > 0 ? s_numInstances : std::thread::hardware_concurrency(); } static std::string platformInfo(); static void listDevices() {} - static bool configureGPU(unsigned, unsigned, unsigned, unsigned, bool, unsigned, boost::optional) { return false; } + static bool configureGPU(unsigned, unsigned, unsigned, unsigned, unsigned, bool, unsigned, boost::optional) { return false; } static void setNumInstances(unsigned _instances) { s_numInstances = std::min(_instances, std::thread::hardware_concurrency()); } protected: void kickOff() override @@ -118,7 +118,8 @@ public: static unsigned getNumDevices(); static void listDevices(); static bool configureGPU( - unsigned _globalWorkSize, + unsigned _localWorkSize, + unsigned _globalWorkSizeMultiplier, unsigned _msPerBatch, unsigned _platformId, unsigned _deviceId, From e1391fa187022205180e8e875338b2a639f1246c Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 30 Jun 2015 16:25:15 +0200 Subject: [PATCH 071/290] OpenCL Fixes after rebasing --- libethcore/Ethash.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 6c1f7d856..fc0e07f12 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -429,6 +429,7 @@ bool Ethash::GPUMiner::configureGPU( } if (!ethash_cl_miner::configureGPU( + _platformId, _localWorkSize, _globalWorkSizeMultiplier * _localWorkSize, _msPerBatch, From 5ed44a51b923ba355aee1e724c09e83df085c730 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Fri, 26 Jun 2015 17:28:47 +0200 Subject: [PATCH 072/290] Distribution Rate test introduced --- test/libwhisper/bloomFilter.cpp | 49 +++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/test/libwhisper/bloomFilter.cpp b/test/libwhisper/bloomFilter.cpp index 814990d52..386be2f6b 100644 --- a/test/libwhisper/bloomFilter.cpp +++ b/test/libwhisper/bloomFilter.cpp @@ -244,4 +244,53 @@ BOOST_AUTO_TEST_CASE(bloomFilterRaw) BOOST_REQUIRE(!f.contains(b00110111)); } +enum { DistributionTestSize = 8 }; + +void updateDistribution(FixedHash const& _h, unsigned* _distribution) +{ + unsigned bits = 0; + for (unsigned i = 0; i < DistributionTestSize; ++i) + if (_h[i]) + for (unsigned j = 0; j < 8; ++j) + if (_h[i] & c_powerOfTwoBitMmask[j]) + { + _distribution[i * 8 + j]++; + if (++bits >= TopicBloomFilterTest::BitsPerBloom) + return; + } +} + +BOOST_AUTO_TEST_CASE(distributionRate) +{ + cnote << "Testing Bloom Filter Distribution Rate..."; + + unsigned const c_arrSize = DistributionTestSize * 8; + unsigned distribution[c_arrSize]; + memset(distribution, 0, c_arrSize * sizeof(unsigned)); + Topic x(0xC0FFEE); // deterministic pseudorandom value + + for (unsigned i = 0; i < 22000; ++i) + { + x = sha3(x); + FixedHash h = x.template bloomPart(); + updateDistribution(h, distribution); + } + + unsigned average = 0; + for (unsigned i = 0; i < c_arrSize; ++i) + average += distribution[i]; + + average /= c_arrSize; + unsigned deviation = average / 10; // approx. 10% + unsigned maxAllowed = average + deviation; + unsigned minAllowed = average - deviation; + + for (unsigned i = 0; i < c_arrSize; ++i) + { + //cnote << i << ":" << distribution[i]; + BOOST_REQUIRE(distribution[i] > minAllowed); + BOOST_REQUIRE(distribution[i] < maxAllowed); + } +} + BOOST_AUTO_TEST_SUITE_END() From 6d37304d05a404c7ef7fd788f1b7f6ae49f5c90a Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Tue, 30 Jun 2015 18:31:00 +0200 Subject: [PATCH 073/290] style fix --- test/libwhisper/bloomFilter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libwhisper/bloomFilter.cpp b/test/libwhisper/bloomFilter.cpp index 386be2f6b..10e34df2d 100644 --- a/test/libwhisper/bloomFilter.cpp +++ b/test/libwhisper/bloomFilter.cpp @@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(bloomFilterRaw) BOOST_REQUIRE(!f.contains(b00110111)); } -enum { DistributionTestSize = 8 }; +static unsigned const DistributionTestSize = 8; void updateDistribution(FixedHash const& _h, unsigned* _distribution) { From ab86f1fdf2f8b9d649e96e29553014f561f4a119 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Wed, 1 Jul 2015 11:49:04 +0200 Subject: [PATCH 074/290] mega enhanced style fix --- test/libwhisper/bloomFilter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libwhisper/bloomFilter.cpp b/test/libwhisper/bloomFilter.cpp index 10e34df2d..f6c191abc 100644 --- a/test/libwhisper/bloomFilter.cpp +++ b/test/libwhisper/bloomFilter.cpp @@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(bloomFilterRaw) BOOST_REQUIRE(!f.contains(b00110111)); } -static unsigned const DistributionTestSize = 8; +static const unsigned DistributionTestSize = 8; void updateDistribution(FixedHash const& _h, unsigned* _distribution) { From a8197d867c860a50f5e2dfa9bc2dc59b56df58ea Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Wed, 1 Jul 2015 14:41:02 +0200 Subject: [PATCH 075/290] super mega enhanced update --- test/libwhisper/bloomFilter.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/test/libwhisper/bloomFilter.cpp b/test/libwhisper/bloomFilter.cpp index f6c191abc..299fd3f5b 100644 --- a/test/libwhisper/bloomFilter.cpp +++ b/test/libwhisper/bloomFilter.cpp @@ -245,8 +245,9 @@ BOOST_AUTO_TEST_CASE(bloomFilterRaw) } static const unsigned DistributionTestSize = 8; +static const unsigned TestArrSize = 8 * DistributionTestSize; -void updateDistribution(FixedHash const& _h, unsigned* _distribution) +void updateDistribution(FixedHash const& _h, array& _distribution) { unsigned bits = 0; for (unsigned i = 0; i < DistributionTestSize; ++i) @@ -264,28 +265,29 @@ BOOST_AUTO_TEST_CASE(distributionRate) { cnote << "Testing Bloom Filter Distribution Rate..."; - unsigned const c_arrSize = DistributionTestSize * 8; - unsigned distribution[c_arrSize]; - memset(distribution, 0, c_arrSize * sizeof(unsigned)); + array distribution; + for (unsigned i = 0; i < TestArrSize; ++i) + distribution[i] = 0; + Topic x(0xC0FFEE); // deterministic pseudorandom value for (unsigned i = 0; i < 22000; ++i) { x = sha3(x); - FixedHash h = x.template bloomPart(); + FixedHash h = x.template bloomPart(); updateDistribution(h, distribution); } unsigned average = 0; - for (unsigned i = 0; i < c_arrSize; ++i) + for (unsigned i = 0; i < TestArrSize; ++i) average += distribution[i]; - average /= c_arrSize; + average /= TestArrSize; unsigned deviation = average / 10; // approx. 10% unsigned maxAllowed = average + deviation; unsigned minAllowed = average - deviation; - for (unsigned i = 0; i < c_arrSize; ++i) + for (unsigned i = 0; i < TestArrSize; ++i) { //cnote << i << ":" << distribution[i]; BOOST_REQUIRE(distribution[i] > minAllowed); From 56be35830a0d688e73ef28bb444b51d6b8232eab Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 1 Jul 2015 15:45:10 +0200 Subject: [PATCH 076/290] Debug compile fix. --- libdevcore/Common.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libdevcore/Common.h b/libdevcore/Common.h index a3ab374a6..c7fdb6dab 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -41,6 +41,7 @@ #include #include #include +#include #include #pragma warning(push) #pragma GCC diagnostic push @@ -186,7 +187,7 @@ private: /// Scope guard for invariant check in a class derived from HasInvariants. #if ETH_DEBUG -#define DEV_INVARIANT_CHECK { ::dev::InvariantChecker __dev_invariantCheck(this, BOOST_THROW_EXCEPTION_CURRENT_FUNCTION, __FILE__, __LINE__); } +#define DEV_INVARIANT_CHECK { ::dev::InvariantChecker __dev_invariantCheck(this, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__); } #else #define DEV_INVARIANT_CHECK (void)0; #endif From b4ee363394b3183887f2a27f4883f16e128f46a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 1 Jul 2015 16:04:55 +0200 Subject: [PATCH 077/290] Cleanups. --- evmjit/include/evmjit/JIT.h | 8 +++++--- evmjit/libevmjit-cpp/JitVM.cpp | 2 ++ evmjit/libevmjit/Arith256.cpp | 4 ++-- evmjit/libevmjit/Optimizer.cpp | 2 +- evmjit/libevmjit/RuntimeManager.h | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/evmjit/include/evmjit/JIT.h b/evmjit/include/evmjit/JIT.h index 0a938fae9..fcb0db4e7 100644 --- a/evmjit/include/evmjit/JIT.h +++ b/evmjit/include/evmjit/JIT.h @@ -20,12 +20,13 @@ namespace evmjit using byte = uint8_t; using bytes_ref = std::tuple; +/// Representation of 256-bit hash value struct h256 { uint64_t words[4]; }; -inline bool operator==(h256 _h1, h256 _h2) +inline bool operator==(h256 const& _h1, h256 const& _h2) { return _h1.words[0] == _h2.words[0] && _h1.words[1] == _h2.words[1] && @@ -39,7 +40,7 @@ struct i256 uint64_t words[4]; i256() = default; - i256(h256 _h) { std::memcpy(this, &_h, sizeof(*this)); } + i256(h256 const& _h) { std::memcpy(this, &_h, sizeof(*this)); } }; // TODO: Merge with ExecutionContext @@ -68,6 +69,8 @@ struct RuntimeData ReturnDataSize = CallDataSize, ///< Return data size (set only in case of RETURN) }; + static size_t const numElements = CodeSize + 1; + int64_t gas = 0; int64_t gasPrice = 0; byte const* callData = nullptr; @@ -170,4 +173,3 @@ template<> struct hash }; }; } - diff --git a/evmjit/libevmjit-cpp/JitVM.cpp b/evmjit/libevmjit-cpp/JitVM.cpp index 169ce68ae..2fb2a0e67 100644 --- a/evmjit/libevmjit-cpp/JitVM.cpp +++ b/evmjit/libevmjit-cpp/JitVM.cpp @@ -50,6 +50,8 @@ bytesConstRef JitVM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _on m_data.codeSize = _ext.code.size(); m_data.codeHash = eth2jit(_ext.codeHash); + // Pass pointer to ExtVMFace casted to evmjit::Env* opaque type. + // JIT will do nothing with the pointer, just pass it to Env callback functions implemented in Env.cpp. m_context.init(m_data, reinterpret_cast(&_ext)); auto exitCode = evmjit::JIT::exec(m_context); switch (exitCode) diff --git a/evmjit/libevmjit/Arith256.cpp b/evmjit/libevmjit/Arith256.cpp index 066596e4c..76c53c78d 100644 --- a/evmjit/libevmjit/Arith256.cpp +++ b/evmjit/libevmjit/Arith256.cpp @@ -132,7 +132,7 @@ namespace llvm::Function* createUDivRemFunc(llvm::Type* _type, llvm::Module& _module, char const* _funcName) { // Based of "Improved shift divisor algorithm" from "Software Integer Division" by Microsoft Research - // The following algorithm also handles divisor of value 0 returning 0 for both quotient and reminder + // The following algorithm also handles divisor of value 0 returning 0 for both quotient and remainder auto retType = llvm::VectorType::get(_type, 2); auto func = llvm::Function::Create(llvm::FunctionType::get(retType, {_type, _type}, false), llvm::Function::PrivateLinkage, _funcName, &_module); @@ -327,7 +327,7 @@ llvm::Function* Arith256::getSDivRem256Func(llvm::Module& _module) auto qAbs = builder.CreateExtractElement(res, uint64_t(0)); auto rAbs = builder.CreateExtractElement(res, 1); - // the reminder has the same sign as dividend + // the remainder has the same sign as dividend auto rNeg = builder.CreateSub(Constant::get(0), rAbs); auto r = builder.CreateSelect(xIsNeg, rNeg, rAbs); diff --git a/evmjit/libevmjit/Optimizer.cpp b/evmjit/libevmjit/Optimizer.cpp index b097a2e3f..dea3ea2a0 100644 --- a/evmjit/libevmjit/Optimizer.cpp +++ b/evmjit/libevmjit/Optimizer.cpp @@ -32,7 +32,7 @@ bool optimize(llvm::Module& _module) namespace { -class LowerEVMPass : public llvm::BasicBlockPass +class LowerEVMPass: public llvm::BasicBlockPass { static char ID; diff --git a/evmjit/libevmjit/RuntimeManager.h b/evmjit/libevmjit/RuntimeManager.h index 98d5b3132..8c0728aaf 100644 --- a/evmjit/libevmjit/RuntimeManager.h +++ b/evmjit/libevmjit/RuntimeManager.h @@ -63,7 +63,7 @@ private: llvm::Value* m_memPtr = nullptr; llvm::Value* m_envPtr = nullptr; - std::array(RuntimeData::Index::CodeSize) + 1> m_dataElts; + std::array m_dataElts; llvm::Value* m_stackSize = nullptr; llvm::Function* m_checkStackLimit = nullptr; From 9d59ebb64568b6a9fc370690019c3c86f70d7d11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 1 Jul 2015 16:14:53 +0200 Subject: [PATCH 078/290] Cleanups. --- evmjit/libevmjit/Compiler.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index e51df0245..a44e4e890 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -51,10 +51,8 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn // Skip all STOPs in the end for (; _codeEnd != _codeBegin; --_codeEnd) - { if (*(_codeEnd - 1) != static_cast(Instruction::STOP)) break; - } auto begin = _codeBegin; // begin of current block bool nextJumpDest = false; @@ -977,4 +975,3 @@ void Compiler::dump() } } } - From befae80d10febaa45f2587405683475a31325b26 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 1 Jul 2015 17:10:22 +0200 Subject: [PATCH 079/290] more diagnostics --- libethereum/BlockChainSync.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 7368d7632..9dda66b7d 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -284,7 +284,7 @@ void BlockChainSync::onPeerNewBlock(std::shared_ptr _peer, RLP con case ImportResult::FutureTimeUnknown: case ImportResult::UnknownParent: logNewBlock(h); - clog(NetMessageSummary) << "Received block with no known parent. Resyncing..."; + clog(NetMessageDetail) << "Received block with no known parent. Resyncing..."; resetSyncFor(_peer, h, _r[1].toInt()); break; default:; @@ -788,8 +788,12 @@ void PV60Sync::onPeerAborting() { RecursiveGuard l(x_sync); // Can't check invariants here since the peers is already removed from the list and the state is not updated yet. - if (m_syncer.expired()) + if (m_syncer.expired() && m_state != SyncState::Idle) + { + clog(NetWarn) << "Syncing peer disconnected, restarting sync"; + m_syncer.reset(); abortSync(); + } DEV_INVARIANT_CHECK; } @@ -1051,8 +1055,12 @@ void PV61Sync::onPeerAborting() else ++s; } - if (m_syncer.expired()) + if (m_syncer.expired() && m_state != SyncState::Idle) + { + clog(NetWarn) << "Syncing peer disconnected, restarting sync"; + m_syncer.reset(); abortSync(); + } else if (isPV61Syncing()) requestSubchains(); DEV_INVARIANT_CHECK; From 679143c23317cac2d08bb3344303559c585ceb21 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 1 Jul 2015 17:16:51 +0200 Subject: [PATCH 080/290] Fix pow check and style. --- eth/main.cpp | 16 ---------------- ethminer/MinerAux.h | 2 +- rlp/main.cpp | 7 +++++++ 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 0ccba6fca..2c11e4bf3 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -668,9 +668,7 @@ int main(int argc, char** argv) } #if ETH_EVMJIT else if (arg == "-J" || arg == "--jit") - { jit = true; - } #endif else if (arg == "-h" || arg == "--help") help(); @@ -994,17 +992,11 @@ int main(int argc, char** argv) web3.addNode(p2p::NodeId(), addrPort); } else if (cmd == "netstop") - { web3.stopNetwork(); - } else if (c && cmd == "minestart") - { c->startMining(); - } else if (c && cmd == "minestop") - { c->stopMining(); - } else if (c && cmd == "mineforce") { string enable; @@ -1127,13 +1119,9 @@ int main(int argc, char** argv) } } else if (c && cmd == "block") - { cout << "Current block: " << c->blockChain().details().number << endl; - } else if (c && cmd == "blockqueue") - { cout << "Current blockqueue status: " << endl << c->blockQueueStatus() << endl; - } else if (c && cmd == "findblock") { if (iss.peek() != -1) @@ -1182,13 +1170,9 @@ int main(int argc, char** argv) cwarn << "Require parameter: findblock HASH"; } else if (c && cmd == "firstunknown") - { cout << "first unknown blockhash: " << c->blockQueue().firstUnknown().hex() << endl; - } else if (c && cmd == "retryunknown") - { c->retryUnknown(); - } else if (cmd == "peers") { for (auto it: web3.peers()) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index ec6ee57e7..b8305370c 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -217,7 +217,7 @@ public: auto boundary = bi.boundary(); m = boost::to_lower_copy(string(argv[++i])); bi.nonce = h64(m); - auto r = EthashAux::eval(bi.seedHash(), powHash, bi.nonce); + auto r = EthashAux::eval(seedHash, powHash, bi.nonce); bool valid = r.value < boundary; cout << (valid ? "VALID :-)" : "INVALID :-(") << endl; cout << r.value << (valid ? " < " : " >= ") << boundary << endl; diff --git a/rlp/main.cpp b/rlp/main.cpp index 3924f9c44..400a0cb70 100644 --- a/rlp/main.cpp +++ b/rlp/main.cpp @@ -49,6 +49,7 @@ void help() << "General options:" << endl << " -L,--lenience Try not to bomb out early if possible." << endl << " -x,--hex,--base-16 Treat input RLP as hex encoded data." << endl + << " -k,--keccak Output Keccak-256 hash only." << endl << " --64,--base-64 Treat input RLP as base-64 encoded data." << endl << " -b,--bin,--base-256 Treat input RLP as raw binary data." << endl << " -h,--help Print this help message and exit." << endl @@ -75,6 +76,7 @@ enum class Encoding { Hex, Base64, Binary, + Keccak, }; bool isAscii(string const& _s) @@ -186,6 +188,8 @@ int main(int argc, char** argv) version(); else if (arg == "-x" || arg == "--hex" || arg == "--base-16") encoding = Encoding::Hex; + else if (arg == "-k" || arg == "--keccak") + encoding = Encoding::Keccak; else if (arg == "--64" || arg == "--base-64") encoding = Encoding::Base64; else if (arg == "-b" || arg == "--bin" || arg == "--base-256") @@ -371,6 +375,9 @@ int main(int argc, char** argv) case Encoding::Binary: cout.write((char const*)out.out().data(), out.out().size()); break; + case Encoding::Keccak: + cout << sha3(out.out()).hex() << endl; + break; } break; } From d557ca537067385be1ede772ba7b1b5dbd8bb0bc Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 1 Jul 2015 14:10:00 +0200 Subject: [PATCH 081/290] Add hashrate command to interactive CLI mode --- eth/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/eth/main.cpp b/eth/main.cpp index 2c11e4bf3..6ac52a974 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -115,6 +115,7 @@ void interactiveHelp() << " reprocess Reprocess a given block." << endl << " dumptrace Dumps a transaction trace" << endl << "to . should be one of pretty, standard, standard+." << endl << " dumpreceipt Dumps a transation receipt." << endl + << " hashrate Print the current hashrate in hashes per second if the client is mining." << endl << " exit Exits the application." << endl; } @@ -1122,6 +1123,8 @@ int main(int argc, char** argv) cout << "Current block: " << c->blockChain().details().number << endl; else if (c && cmd == "blockqueue") cout << "Current blockqueue status: " << endl << c->blockQueueStatus() << endl; + else if (c && cmd == "hashrate") + cout << "Current hash rate: " << toString(c->hashrate()) << " hashes per second." << endl; else if (c && cmd == "findblock") { if (iss.peek() != -1) From f3850a5e8a437b0107e8427276e9de55a97ad18f Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 1 Jul 2015 17:34:40 +0200 Subject: [PATCH 082/290] even more diagnostics --- libethereum/EthereumHost.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 5bd16ac12..dc6e46ad4 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -317,8 +317,15 @@ void EthereumHost::onPeerTransactions(std::shared_ptr _peer, RLP c void EthereumHost::onPeerAborting() { Guard l(x_sync); - if (m_sync) - m_sync->onPeerAborting(); + try + { + if (m_sync) + m_sync->onPeerAborting(); + } + catch (Exception&) + { + cwarn << "Exception on peer destruciton: " << boost::current_exception_diagnostic_information(); + } } bool EthereumHost::isSyncing() const From d036c6dc16b3713941092e8f4d52f7b71d82493c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 1 Jul 2015 18:15:18 +0200 Subject: [PATCH 083/290] Separate compile and execute jobs in JIT. --- evmjit/include/evmjit/JIT.h | 4 +- evmjit/libevmjit/JIT.cpp | 82 ++++++++++++++++++------------------- 2 files changed, 42 insertions(+), 44 deletions(-) diff --git a/evmjit/include/evmjit/JIT.h b/evmjit/include/evmjit/JIT.h index fcb0db4e7..8d6f9bbd0 100644 --- a/evmjit/include/evmjit/JIT.h +++ b/evmjit/include/evmjit/JIT.h @@ -107,9 +107,7 @@ enum class ReturnCode Rejected = -5, ///< Input data (code, gas, block info, etc.) does not meet JIT requirement and execution request has been rejected // Internal error codes - LLVMConfigError = -101, - LLVMCompileError = -102, - LLVMLinkError = -103, + LLVMError = -101, UnexpectedException = -111, diff --git a/evmjit/libevmjit/JIT.cpp b/evmjit/libevmjit/JIT.cpp index 6a9b7f932..89d2e63eb 100644 --- a/evmjit/libevmjit/JIT.cpp +++ b/evmjit/libevmjit/JIT.cpp @@ -97,6 +97,8 @@ public: ExecFunc getExecFunc(h256 const& _codeHash) const; void mapExecFunc(h256 _codeHash, ExecFunc _funcAddr); + + ExecFunc compile(byte const* _code, uint64_t _codeSize, h256 const& _codeHash); }; JITImpl::JITImpl() @@ -145,6 +147,33 @@ void JITImpl::mapExecFunc(h256 _codeHash, ExecFunc _funcAddr) m_codeMap.emplace(std::move(_codeHash), _funcAddr); } +ExecFunc JITImpl::compile(byte const* _code, uint64_t _codeSize, h256 const& _codeHash) +{ + auto name = hash2str(_codeHash); + auto module = Cache::getObject(name); + if (!module) + { + // TODO: Listener support must be redesigned. These should be a feature of JITImpl + //listener->stateChanged(ExecState::Compilation); + assert(_code || !_codeSize); //TODO: Is it good idea to execute empty code? + module = Compiler{{}}.compile(_code, _code + _codeSize, name); + + if (g_optimize) + { + //listener->stateChanged(ExecState::Optimization); + optimize(*module); + } + + prepare(*module); + } + if (g_dump) + module->dump(); + + m_engine->addModule(std::move(module)); + //listener->stateChanged(ExecState::CodeGen); + return (ExecFunc)m_engine->getFunctionAddress(name); +} + } // anonymous namespace bool JIT::isCodeReady(h256 const& _codeHash) @@ -154,60 +183,31 @@ bool JIT::isCodeReady(h256 const& _codeHash) ReturnCode JIT::exec(ExecutionContext& _context) { - auto& jit = JITImpl::instance(); - - std::unique_ptr listener{new ExecStats}; - listener->stateChanged(ExecState::Started); + //std::unique_ptr listener{new ExecStats}; + //listener->stateChanged(ExecState::Started); + //static StatsCollector statsCollector; - auto code = _context.code(); - auto codeSize = _context.codeSize(); + auto& jit = JITImpl::instance(); auto codeHash = _context.codeHash(); - - static StatsCollector statsCollector; - - auto mainFuncName = hash2str(codeHash); - - // TODO: Remove cast auto execFunc = jit.getExecFunc(codeHash); if (!execFunc) { - auto module = Cache::getObject(mainFuncName); - if (!module) - { - listener->stateChanged(ExecState::Compilation); - assert(code || !codeSize); //TODO: Is it good idea to execute empty code? - module = Compiler{{}}.compile(code, code + codeSize, mainFuncName); - - if (g_optimize) - { - listener->stateChanged(ExecState::Optimization); - optimize(*module); - } - - prepare(*module); - } - if (g_dump) - module->dump(); - - jit.engine().addModule(std::move(module)); - listener->stateChanged(ExecState::CodeGen); - execFunc = (ExecFunc)jit.engine().getFunctionAddress(mainFuncName); - if (!CHECK(execFunc)) - return ReturnCode::LLVMLinkError; + execFunc = jit.compile(_context.code(), _context.codeSize(), codeHash); + if (!execFunc) + return ReturnCode::LLVMError; jit.mapExecFunc(codeHash, execFunc); } - listener->stateChanged(ExecState::Execution); + //listener->stateChanged(ExecState::Execution); auto returnCode = execFunc(&_context); - listener->stateChanged(ExecState::Return); + //listener->stateChanged(ExecState::Return); if (returnCode == ReturnCode::Return) _context.returnData = _context.getReturnData(); // Save reference to return data - listener->stateChanged(ExecState::Finished); - - if (g_stats) - statsCollector.stats.push_back(std::move(listener)); + //listener->stateChanged(ExecState::Finished); + // if (g_stats) + // statsCollector.stats.push_back(std::move(listener)); return returnCode; } From 485a9105233bfcee019a8f43cf33275819005317 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 1 Jul 2015 13:53:53 +0200 Subject: [PATCH 084/290] Documentation and tests for RangeMask. --- libdevcore/RangeMask.h | 146 ++++++++++++++++++++------------- libethereum/BlockChainSync.h | 1 - libethereum/EthereumHost.h | 1 - libethereum/EthereumPeer.h | 1 - libp2p/Host.h | 1 - libp2p/Session.h | 1 - test/libdevcore/RangeMask.cpp | 148 ++++++++++++++++++++++++++++++++++ 7 files changed, 239 insertions(+), 60 deletions(-) create mode 100644 test/libdevcore/RangeMask.cpp diff --git a/libdevcore/RangeMask.h b/libdevcore/RangeMask.h index 7c402fc98..d87b81a3a 100644 --- a/libdevcore/RangeMask.h +++ b/libdevcore/RangeMask.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,12 @@ class RLPStream; using UnsignedRange = std::pair; using UnsignedRanges = std::vector; +/** + * Set of elements of a certain "ground range" representable by unions of ranges inside this + * ground range. + * Ranges are given as pairs (begin, end), denoting the interval [begin, end), i.e. end is excluded. + * Supports set-theoretic operators, size and iteration. + */ template class RangeMask { @@ -44,14 +51,19 @@ public: using Range = std::pair; using Ranges = std::vector; + /// Constructs an empty range mask with empty ground range. RangeMask(): m_all(0, 0) {} + /// Constructs an empty range mask with ground range [_begin, _end). RangeMask(T _begin, T _end): m_all(_begin, _end) {} + /// Constructs an empty range mask with ground range _c. RangeMask(Range const& _c): m_all(_c) {} + /// @returns the union with the range mask _m, taking also the union of the ground ranges. RangeMask unionedWith(RangeMask const& _m) const { return operator+(_m); } RangeMask operator+(RangeMask const& _m) const { return RangeMask(*this) += _m; } - RangeMask lowest(T _items) const + /// @returns a new range mask containing the smallest _items elements (not ranges). + RangeMask lowest(decltype(T{} - T{}) _items) const { RangeMask ret(m_all); for (auto i = m_ranges.begin(); i != m_ranges.end() && _items; ++i) @@ -59,8 +71,10 @@ public: return ret; } + /// @returns the complement of the range mask relative to the ground range. RangeMask operator~() const { return inverted(); } + /// @returns a copy of this range mask representing the complement relative to the ground range. RangeMask inverted() const { RangeMask ret(m_all); @@ -76,6 +90,8 @@ public: return ret; } + /// Changes the range mask to its complement relative to the ground range and returns a + /// reference to itself. RangeMask& invert() { return *this = inverted(); } template RangeMask operator-(S const& _m) const { auto ret = *this; return ret -= _m; } @@ -92,61 +108,13 @@ public: return *this; } RangeMask& operator+=(Range const& _m) { return unionWith(_m); } - RangeMask& unionWith(Range const& _m) - { - for (auto i = _m.first; i < _m.second;) - { - assert(i >= m_all.first); - assert(i < m_all.second); - // for each number, we find the element equal or next lower. this, if any, must contain the value. - auto uit = m_ranges.upper_bound(i); - auto it = uit == m_ranges.begin() ? m_ranges.end() : std::prev(uit); - if (it == m_ranges.end() || it->second < i) - // lower range is too low to merge. - // if the next higher range is too high. - if (uit == m_ranges.end() || uit->first > _m.second) - { - // just create a new range - m_ranges[i] = _m.second; - break; - } - else - { - if (uit->first == i) - // move i to end of range - i = uit->second; - else - { - // merge with the next higher range - // move i to end of range - i = m_ranges[i] = uit->second; - i = uit->second; - m_ranges.erase(uit); - } - } - else if (it->second == i) - { - // if the next higher range is too high. - if (uit == m_ranges.end() || uit->first > _m.second) - { - // merge with the next lower range - m_ranges[it->first] = _m.second; - break; - } - else - { - // merge with both next lower & next higher. - i = m_ranges[it->first] = uit->second; - m_ranges.erase(uit); - } - } - else - i = it->second; - } - return *this; - } + /// Modifies this range mask to also include the range _m, which has to be a subset of + /// the ground range. + RangeMask& unionWith(Range const& _m); + /// Adds the single element _i to the range mask. RangeMask& operator+=(T _m) { return unionWith(_m); } + /// Adds the single element _i to the range mask. RangeMask& unionWith(T _i) { return operator+=(Range(_i, _i + 1)); @@ -181,10 +149,12 @@ public: m_all = std::make_pair(0, 0); } + /// @returns the ground range. std::pair const& all() const { return m_all; } + /// Extends the ground range to include _i. void extendAll(T _i) { m_all = std::make_pair(std::min(m_all.first, _i), std::max(m_all.second, _i + 1)); } - class const_iterator + class const_iterator: public std::iterator { friend class RangeMask; @@ -208,6 +178,8 @@ public: const_iterator begin() const { return const_iterator(*this, false); } const_iterator end() const { return const_iterator(*this, true); } + /// @returns the smallest element in the range mask that is larger than _t or the end of the + /// base range if such an element does not exist. T next(T _t) const { _t++; @@ -219,6 +191,7 @@ public: return uit == m_ranges.end() ? m_all.second : uit->first; } + /// @returns the number of elements (not ranges) in the range mask. size_t size() const { size_t c = 0; @@ -228,7 +201,9 @@ public: } private: + /// The ground range. UnsignedRange m_all; + /// Mapping begin -> end containing the ranges. std::map m_ranges; }; @@ -241,4 +216,65 @@ template inline std::ostream& operator<<(std::ostream& _out, RangeMask return _out; } +template +RangeMask& RangeMask::unionWith(RangeMask::Range const& _m) +{ + for (auto i = _m.first; i < _m.second;) + { + assert(i >= m_all.first); + assert(i < m_all.second); + // For each number, we find the element equal or next lower. this, if any, must contain the value. + // First range that starts after i. + auto rangeAfter = m_ranges.upper_bound(i); + // Range before rangeAfter or "end" if the rangeAfter is the first ever... + auto it = rangeAfter == m_ranges.begin() ? m_ranges.end() : std::prev(rangeAfter); + if (it == m_ranges.end() || it->second < i) + { + // i is either before the first range or between two ranges (with some distance + // so that we cannot merge it onto "it"). + // lower range is too low to merge. + // if the next higher range is too high. + if (rangeAfter == m_ranges.end() || rangeAfter->first > _m.second) + { + // just create a new range + m_ranges[i] = _m.second; + break; + } + else + { + if (rangeAfter->first == i) + // move i to end of range + i = rangeAfter->second; + else + { + // merge with the next higher range + // move i to end of range + i = m_ranges[i] = rangeAfter->second; + m_ranges.erase(rangeAfter); + } + } + } + else if (it->second == i) + { + // The range before i ends with i. + // if the next higher range is too high. + if (rangeAfter == m_ranges.end() || rangeAfter->first > _m.second) + { + // merge with the next lower range + m_ranges[it->first] = _m.second; + break; + } + else + { + // merge with both next lower & next higher. + i = m_ranges[it->first] = rangeAfter->second; + m_ranges.erase(rangeAfter); + } + } + else + i = it->second; + } + return *this; +} + } diff --git a/libethereum/BlockChainSync.h b/libethereum/BlockChainSync.h index 449dd49d1..793b05b5b 100644 --- a/libethereum/BlockChainSync.h +++ b/libethereum/BlockChainSync.h @@ -24,7 +24,6 @@ #include #include -#include #include #include #include "CommonNet.h" diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index 182c3d4cd..a4b9d0006 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -31,7 +31,6 @@ #include #include -#include #include #include #include "CommonNet.h" diff --git a/libethereum/EthereumPeer.h b/libethereum/EthereumPeer.h index d506ffb3f..e8842c8af 100644 --- a/libethereum/EthereumPeer.h +++ b/libethereum/EthereumPeer.h @@ -31,7 +31,6 @@ #include #include -#include #include #include #include "CommonNet.h" diff --git a/libp2p/Host.h b/libp2p/Host.h index 9523d0cca..b7ebb3951 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -33,7 +33,6 @@ #include #include -#include #include #include #include "NodeTable.h" diff --git a/libp2p/Session.h b/libp2p/Session.h index 0a55b2653..8d8c3ea1e 100644 --- a/libp2p/Session.h +++ b/libp2p/Session.h @@ -31,7 +31,6 @@ #include #include -#include #include #include "RLPXFrameCoder.h" #include "RLPXSocket.h" diff --git a/test/libdevcore/RangeMask.cpp b/test/libdevcore/RangeMask.cpp new file mode 100644 index 000000000..05f58963a --- /dev/null +++ b/test/libdevcore/RangeMask.cpp @@ -0,0 +1,148 @@ +/* + 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 RangeMask.cpp + * @author Christian + * @date 2015 + */ + +#include +#include "../TestHelper.h" + +using namespace std; +using namespace dev; + +namespace dev +{ +namespace test +{ + +BOOST_AUTO_TEST_SUITE(RangeMaskTest) + +BOOST_AUTO_TEST_CASE(constructor) +{ + using RM = RangeMask; + using Range = pair; + for (RM r: {RM(), RM(1, 10), RM(Range(2, 10))}) + { + BOOST_CHECK(r.empty()); + BOOST_CHECK(!r.contains(0)); + BOOST_CHECK(!r.contains(1)); + BOOST_CHECK_EQUAL(0, r.size()); + } + BOOST_CHECK(RM().full()); + BOOST_CHECK(!RM(1, 10).full()); + BOOST_CHECK(!RM(Range(2, 10)).full()); +} + +BOOST_AUTO_TEST_CASE(simple_unions) +{ + using RM = RangeMask; + using Range = pair; + RM m(Range(0, 2000)); + m.unionWith(Range(1, 2)); + BOOST_CHECK_EQUAL(m.size(), 1); + m.unionWith(Range(50, 250)); + BOOST_CHECK_EQUAL(m.size(), 201); + m.unionWith(Range(10, 16)); + BOOST_CHECK_EQUAL(m.size(), 207); + BOOST_CHECK(m.contains(1)); + BOOST_CHECK(m.contains(11)); + BOOST_CHECK(m.contains(51)); + BOOST_CHECK(m.contains(200)); + BOOST_CHECK(!m.contains(2)); + BOOST_CHECK(!m.contains(7)); + BOOST_CHECK(!m.contains(17)); + BOOST_CHECK(!m.contains(258)); +} + +BOOST_AUTO_TEST_CASE(empty_union) +{ + using RM = RangeMask; + using Range = pair; + RM m(Range(0, 2000)); + m.unionWith(Range(3, 6)); + BOOST_CHECK_EQUAL(m.size(), 3); + m.unionWith(Range(50, 50)); + BOOST_CHECK_EQUAL(m.size(), 3); + m.unionWith(Range(0, 0)); + BOOST_CHECK_EQUAL(m.size(), 3); + m.unionWith(Range(1, 1)); + BOOST_CHECK_EQUAL(m.size(), 3); + m.unionWith(Range(2, 2)); + BOOST_CHECK_EQUAL(m.size(), 3); + m.unionWith(Range(3, 3)); + BOOST_CHECK_EQUAL(m.size(), 3); +} + +BOOST_AUTO_TEST_CASE(overlapping_unions) +{ + using RM = RangeMask; + using Range = pair; + RM m(Range(0, 2000)); + m.unionWith(Range(10, 20)); + BOOST_CHECK_EQUAL(10, m.size()); + m.unionWith(Range(30, 40)); + BOOST_CHECK_EQUAL(20, m.size()); + m.unionWith(Range(15, 30)); + BOOST_CHECK_EQUAL(40 - 10, m.size()); + m.unionWith(Range(50, 60)); + m.unionWith(Range(45, 55)); + // [40, 45) still missing here + BOOST_CHECK_EQUAL(60 - 10 - 5, m.size()); + m.unionWith(Range(15, 56)); + BOOST_CHECK_EQUAL(60 - 10, m.size()); + m.unionWith(Range(15, 65)); + BOOST_CHECK_EQUAL(65 - 10, m.size()); + m.unionWith(Range(5, 70)); + BOOST_CHECK_EQUAL(70 - 5, m.size()); +} + +BOOST_AUTO_TEST_CASE(complement) +{ + using RM = RangeMask; + using Range = pair; + RM m(Range(0, 2000)); + m.unionWith(7).unionWith(9); + m = ~m; + m.unionWith(7).unionWith(9); + m = ~m; + BOOST_CHECK(m.empty()); + + m += Range(0, 10); + m += Range(1000, 2000); + m.invert(); + BOOST_CHECK_EQUAL(m.size(), 1000 - 10); +} + +BOOST_AUTO_TEST_CASE(iterator) +{ + using RM = RangeMask; + using Range = pair; + RM m(Range(0, 2000)); + m.unionWith(Range(7, 9)); + m.unionWith(11); + m.unionWith(Range(200, 205)); + + vector elements; + copy(m.begin(), m.end(), back_inserter(elements)); + BOOST_CHECK(elements == (vector{7, 8, 11, 200, 201, 202, 203, 204})); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} From 75795be23188e91000f2d2a631562ce5f6923f1e Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 1 Jul 2015 19:36:20 +0200 Subject: [PATCH 085/290] Fixed typo. --- eth/main.cpp | 2 +- libdevcore/RLP.cpp | 2 +- libdevcore/RLP.h | 2 +- libethereum/EthereumPeer.cpp | 2 +- rlp/main.cpp | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 6ac52a974..b4f0326a9 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -801,7 +801,7 @@ int main(int argc, char** argv) { bytes block(8); in.read((char*)block.data(), 8); - block.resize(RLP(block, RLP::LaisezFaire).actualSize()); + block.resize(RLP(block, RLP::LaissezFaire).actualSize()); in.read((char*)block.data() + 8, block.size() - 8); switch (web3.ethereum()->queueBlock(block, safeImport)) diff --git a/libdevcore/RLP.cpp b/libdevcore/RLP.cpp index 330893c76..92d97aec4 100644 --- a/libdevcore/RLP.cpp +++ b/libdevcore/RLP.cpp @@ -320,7 +320,7 @@ std::ostream& dev::operator<<(std::ostream& _out, RLP const& _d) if (_d.isNull()) _out << "null"; else if (_d.isInt()) - _out << std::showbase << std::hex << std::nouppercase << _d.toInt(RLP::LaisezFaire) << dec; + _out << std::showbase << std::hex << std::nouppercase << _d.toInt(RLP::LaissezFaire) << dec; else if (_d.isData()) _out << escaped(_d.toString(), false); else if (_d.isList()) diff --git a/libdevcore/RLP.h b/libdevcore/RLP.h index dee438be4..67f464b9d 100644 --- a/libdevcore/RLP.h +++ b/libdevcore/RLP.h @@ -71,7 +71,7 @@ public: FailIfTooSmall = 16, Strict = ThrowOnFail | FailIfTooBig, VeryStrict = ThrowOnFail | FailIfTooBig | FailIfTooSmall, - LaisezFaire = AllowNonCanon + LaissezFaire = AllowNonCanon }; using Strictness = int; diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp index 88878334c..eea5d23dc 100644 --- a/libethereum/EthereumPeer.cpp +++ b/libethereum/EthereumPeer.cpp @@ -86,7 +86,7 @@ unsigned EthereumPeer::askOverride() const if (s->info().clientVersion.substr(0, badGeth.size()) == badGeth) return 1; bytes const& d = repMan().data(*s, name()); - return d.empty() ? c_maxBlocksAsk : RLP(d).toInt(RLP::LaisezFaire); + return d.empty() ? c_maxBlocksAsk : RLP(d).toInt(RLP::LaissezFaire); } void EthereumPeer::setRude() diff --git a/rlp/main.cpp b/rlp/main.cpp index 400a0cb70..8ff7202c3 100644 --- a/rlp/main.cpp +++ b/rlp/main.cpp @@ -113,9 +113,9 @@ public: m_out << "null"; else if (_d.isInt() && !m_prefs.stringInts) if (m_prefs.hexInts) - m_out << (m_prefs.hexPrefix ? "0x" : "") << toHex(toCompactBigEndian(_d.toInt(RLP::LaisezFaire), 1), 1); + m_out << (m_prefs.hexPrefix ? "0x" : "") << toHex(toCompactBigEndian(_d.toInt(RLP::LaissezFaire), 1), 1); else - m_out << _d.toInt(RLP::LaisezFaire); + m_out << _d.toInt(RLP::LaissezFaire); else if (_d.isData() || (_d.isInt() && m_prefs.stringInts)) if (m_prefs.forceString || (!m_prefs.forceHex && isAscii(_d.toString()))) m_out << escaped(_d.toString(), m_prefs.escapeAll); From 447ba77006138cfd04a3ff99bc75fe41778fe494 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Wed, 1 Jul 2015 11:24:09 +0200 Subject: [PATCH 086/290] initial rating introduction --- libwhisper/WhisperHost.cpp | 28 +++++++++++++++++++--------- libwhisper/WhisperPeer.cpp | 10 +++++++++- libwhisper/WhisperPeer.h | 2 +- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/libwhisper/WhisperHost.cpp b/libwhisper/WhisperHost.cpp index 150d5cd63..9d97816f2 100644 --- a/libwhisper/WhisperHost.cpp +++ b/libwhisper/WhisperHost.cpp @@ -66,21 +66,31 @@ void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p) m_expiryQueue.insert(make_pair(_m.expiry(), h)); } - DEV_GUARDED(m_filterLock) - { - for (auto const& f: m_filters) - if (f.second.filter.matches(_m)) - for (auto& i: m_watches) - if (i.second.id == f.first) - i.second.changes.push_back(h); - } + int rating = 1; // rating is based upon: 1. installed watch; 2. proof of work + + //if (bloomfilter.check) + //{ + // rating *= 10; + if (_p) // originated externally + DEV_GUARDED(m_filterLock) + { + for (auto const& f: m_filters) + if (f.second.filter.matches(_m)) + for (auto& i: m_watches) + if (i.second.id == f.first) + { + i.second.changes.push_back(h); + rating *= 10; + } + } + //} // TODO p2p: capability-based rating for (auto i: peerSessions()) { auto w = i.first->cap().get(); if (w == _p) - w->addRating(1); + w->addRating(rating); else w->noteNewMessage(h, _m); } diff --git a/libwhisper/WhisperPeer.cpp b/libwhisper/WhisperPeer.cpp index d749aa26e..feae5b72c 100644 --- a/libwhisper/WhisperPeer.cpp +++ b/libwhisper/WhisperPeer.cpp @@ -114,8 +114,16 @@ void WhisperPeer::sendMessages() void WhisperPeer::noteNewMessage(h256 _h, Envelope const& _m) { + unsigned rate = rating(_m); Guard l(x_unseen); - m_unseen.insert(make_pair(rating(_m), _h)); + m_unseen.insert(make_pair(rate, _h)); +} + +unsigned WhisperPeer::rating(Envelope const&) const +{ + // rated by: 1. installed watch; 2. proof of work + + return 0; } void WhisperPeer::sendTopicsOfInterest(TopicBloomFilterHash const& _bloom) diff --git a/libwhisper/WhisperPeer.h b/libwhisper/WhisperPeer.h index 48f984013..313cec28d 100644 --- a/libwhisper/WhisperPeer.h +++ b/libwhisper/WhisperPeer.h @@ -62,7 +62,7 @@ public: private: virtual bool interpret(unsigned _id, RLP const&) override; void sendMessages(); - unsigned rating(Envelope const&) const { return 0; } // TODO + unsigned rating(Envelope const&) const; void noteNewMessage(h256 _h, Envelope const& _m); void setBloom(TopicBloomFilterHash const& _b) { dev::Guard g(x_bloom); m_bloom = _b; } From ed858347118e867a90891ee02d824a3f680de9a5 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Wed, 1 Jul 2015 20:11:30 +0200 Subject: [PATCH 087/290] Message rating for peers introduced --- libwhisper/BloomFilter.h | 6 ++---- libwhisper/Common.cpp | 2 +- libwhisper/Common.h | 7 ++++--- libwhisper/Message.cpp | 9 +++++++++ libwhisper/Message.h | 2 ++ libwhisper/WhisperHost.cpp | 4 +++- libwhisper/WhisperHost.h | 2 +- libwhisper/WhisperPeer.cpp | 41 +++++++++++++++++++++++--------------- libwhisper/WhisperPeer.h | 4 ++-- 9 files changed, 49 insertions(+), 28 deletions(-) diff --git a/libwhisper/BloomFilter.h b/libwhisper/BloomFilter.h index a624be157..7b5d179c6 100644 --- a/libwhisper/BloomFilter.h +++ b/libwhisper/BloomFilter.h @@ -42,14 +42,12 @@ public: void addRaw(FixedHash const& _h); void removeRaw(FixedHash const& _h); bool containsRaw(FixedHash const& _h) const { return this->contains(_h); } - - enum { BitsPerBloom = 3 }; private: void init() { for (unsigned i = 0; i < CounterSize; ++i) m_refCounter[i] = 0; } static bool isBitSet(FixedHash const& _h, unsigned _index); - enum { CounterSize = 8 * TopicBloomFilterBase::size }; + static const unsigned CounterSize = N * 8; std::array m_refCounter; }; @@ -91,7 +89,7 @@ bool TopicBloomFilterBase::isBitSet(FixedHash const& _h, unsigned _index) return (_h[iByte] & c_powerOfTwoBitMmask[iBit]) != 0; } -using TopicBloomFilter = TopicBloomFilterBase; +using TopicBloomFilter = TopicBloomFilterBase; } } diff --git a/libwhisper/Common.cpp b/libwhisper/Common.cpp index 748180647..7c7a9801b 100644 --- a/libwhisper/Common.cpp +++ b/libwhisper/Common.cpp @@ -100,7 +100,7 @@ TopicBloomFilterHash TopicFilter::exportBloom() const TopicBloomFilterHash ret; for (TopicMask const& t: m_topicMasks) for (auto const& i: t) - ret |= i.first.template bloomPart(); + ret |= i.first.template bloomPart(); return ret; } diff --git a/libwhisper/Common.h b/libwhisper/Common.h index d5d926291..277ce0902 100644 --- a/libwhisper/Common.h +++ b/libwhisper/Common.h @@ -58,8 +58,9 @@ enum WhisperPacket PacketCount }; -static const int c_topicBloomFilterSize = 64; -static const int c_whisperProtocolVersion = 3; +static const unsigned TopicBloomFilterSize = 64; +static const unsigned BitsPerBloom = 3; +static const unsigned WhisperProtocolVersion = 3; using AbridgedTopic = FixedHash<4>; using Topic = h256; @@ -67,7 +68,7 @@ using Topic = h256; using AbridgedTopics = std::vector; using Topics = h256s; -using TopicBloomFilterHash = FixedHash; +using TopicBloomFilterHash = FixedHash; AbridgedTopic abridge(Topic const& _topic); AbridgedTopics abridge(Topics const& _topics); diff --git a/libwhisper/Message.cpp b/libwhisper/Message.cpp index 50020b783..0b235b984 100644 --- a/libwhisper/Message.cpp +++ b/libwhisper/Message.cpp @@ -181,3 +181,12 @@ void Envelope::proveWork(unsigned _ms) } } } + +bool Envelope::matchesBloomFilter(TopicBloomFilterHash const& f) const +{ + for (AbridgedTopic t: m_topic) + if (f.contains(t.template bloomPart())) + return true; + + return false; +} diff --git a/libwhisper/Message.h b/libwhisper/Message.h index 3529054e0..ae61f210a 100644 --- a/libwhisper/Message.h +++ b/libwhisper/Message.h @@ -80,6 +80,8 @@ public: unsigned workProved() const; void proveWork(unsigned _ms); + bool matchesBloomFilter(TopicBloomFilterHash const& f) const; + private: Envelope(unsigned _exp, unsigned _ttl, AbridgedTopics const& _topic): m_expiry(_exp), m_ttl(_ttl), m_topic(_topic) {} diff --git a/libwhisper/WhisperHost.cpp b/libwhisper/WhisperHost.cpp index 9d97816f2..9ee772ba5 100644 --- a/libwhisper/WhisperHost.cpp +++ b/libwhisper/WhisperHost.cpp @@ -51,6 +51,8 @@ void WhisperHost::streamMessage(h256 _m, RLPStream& _s) const void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p) { + // this function processes messages originated both by local host (_p == null), and by remote peers (_p != null) + cnote << this << ": inject: " << _m.expiry() << _m.ttl() << _m.topic() << toHex(_m.data()); if (_m.expiry() <= (unsigned)time(0)) @@ -66,7 +68,7 @@ void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p) m_expiryQueue.insert(make_pair(_m.expiry(), h)); } - int rating = 1; // rating is based upon: 1. installed watch; 2. proof of work + int rating = 1; // rating for local host is based upon: 1. installed watch; 2. proof of work //if (bloomfilter.check) //{ diff --git a/libwhisper/WhisperHost.h b/libwhisper/WhisperHost.h index a6de09c38..fc1bcb557 100644 --- a/libwhisper/WhisperHost.h +++ b/libwhisper/WhisperHost.h @@ -50,7 +50,7 @@ class WhisperHost: public HostCapability, public Interface, public public: WhisperHost(); virtual ~WhisperHost(); - unsigned protocolVersion() const { return c_whisperProtocolVersion; } + unsigned protocolVersion() const { return WhisperProtocolVersion; } /// remove old messages void cleanup(); std::map all() const { dev::ReadGuard l(x_messages); return m_messages; } diff --git a/libwhisper/WhisperPeer.cpp b/libwhisper/WhisperPeer.cpp index feae5b72c..13df87ea3 100644 --- a/libwhisper/WhisperPeer.cpp +++ b/libwhisper/WhisperPeer.cpp @@ -91,19 +91,17 @@ void WhisperPeer::sendMessages() if (m_advertiseTopicsOfInterest) sendTopicsOfInterest(host()->bloom()); + multimap available; + DEV_GUARDED(x_unseen) + m_unseen.swap(available); + RLPStream amalg; - unsigned msgCount = 0; - { - Guard l(x_unseen); - msgCount = m_unseen.size(); - while (m_unseen.size()) - { - auto p = *m_unseen.begin(); - m_unseen.erase(m_unseen.begin()); - host()->streamMessage(p.second, amalg); - } - } - + + // send the highest rated messages first + for (auto i = available.rbegin(); i != available.rend(); ++i) + host()->streamMessage(i->second, amalg); + + unsigned msgCount = available.size(); if (msgCount) { RLPStream s; @@ -114,16 +112,27 @@ void WhisperPeer::sendMessages() void WhisperPeer::noteNewMessage(h256 _h, Envelope const& _m) { - unsigned rate = rating(_m); + unsigned rate = ratingForPeer(_m); Guard l(x_unseen); m_unseen.insert(make_pair(rate, _h)); } -unsigned WhisperPeer::rating(Envelope const&) const +unsigned WhisperPeer::ratingForPeer(Envelope const& e) const { - // rated by: 1. installed watch; 2. proof of work + // we try to estimate, how valuable this nessage will be for the remote peer, + // according to the following criteria: + // 1. bloom filter + // 2. proof of work - return 0; + static const unsigned BloomFilterMatchReward = 256; // vlad todo: move to common.h + unsigned rating = 0; + + DEV_GUARDED(x_bloom) + if (e.matchesBloomFilter(m_bloom)) + rating += BloomFilterMatchReward; + + rating += e.sha3().firstBitSet(); // proof of work assessment + return rating; } void WhisperPeer::sendTopicsOfInterest(TopicBloomFilterHash const& _bloom) diff --git a/libwhisper/WhisperPeer.h b/libwhisper/WhisperPeer.h index 313cec28d..4d093d259 100644 --- a/libwhisper/WhisperPeer.h +++ b/libwhisper/WhisperPeer.h @@ -53,7 +53,7 @@ public: virtual ~WhisperPeer(); WhisperHost* host() const; static std::string name() { return "shh"; } - static u256 version() { return c_whisperProtocolVersion; } + static u256 version() { return WhisperProtocolVersion; } static unsigned messageCount() { return PacketCount; } TopicBloomFilterHash bloom() const { dev::Guard g(x_bloom); return m_bloom; } void sendTopicsOfInterest(TopicBloomFilterHash const& _bloom); ///< sends our bloom filter to remote peer @@ -62,7 +62,7 @@ public: private: virtual bool interpret(unsigned _id, RLP const&) override; void sendMessages(); - unsigned rating(Envelope const&) const; + unsigned ratingForPeer(Envelope const& e) const; void noteNewMessage(h256 _h, Envelope const& _m); void setBloom(TopicBloomFilterHash const& _b) { dev::Guard g(x_bloom); m_bloom = _b; } From 16eab6d8820c1d6b6056a7ca8f38d33a7bcd776e Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Wed, 1 Jul 2015 20:21:35 +0200 Subject: [PATCH 088/290] cleanup --- libwhisper/BloomFilter.cpp | 28 ---------------------------- libwhisper/WhisperPeer.cpp | 2 +- 2 files changed, 1 insertion(+), 29 deletions(-) delete mode 100644 libwhisper/BloomFilter.cpp diff --git a/libwhisper/BloomFilter.cpp b/libwhisper/BloomFilter.cpp deleted file mode 100644 index 554274011..000000000 --- a/libwhisper/BloomFilter.cpp +++ /dev/null @@ -1,28 +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 BloomFilter.cpp -* @author Vladislav Gluhovsky -* @date June 2015 -*/ - -#include "BloomFilter.h" - -using namespace std; -using namespace dev; -using namespace dev::shh; - - diff --git a/libwhisper/WhisperPeer.cpp b/libwhisper/WhisperPeer.cpp index 13df87ea3..393c3749c 100644 --- a/libwhisper/WhisperPeer.cpp +++ b/libwhisper/WhisperPeer.cpp @@ -131,7 +131,7 @@ unsigned WhisperPeer::ratingForPeer(Envelope const& e) const if (e.matchesBloomFilter(m_bloom)) rating += BloomFilterMatchReward; - rating += e.sha3().firstBitSet(); // proof of work assessment + rating += e.sha3().firstBitSet(); return rating; } From c5ffcad47b21fd8008ecc552208abeb123ca751c Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Wed, 1 Jul 2015 20:49:18 +0200 Subject: [PATCH 089/290] build fix --- libp2p/Session.cpp | 2 +- test/libwhisper/bloomFilter.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp index 6827a27d9..6a8c98071 100644 --- a/libp2p/Session.cpp +++ b/libp2p/Session.cpp @@ -382,7 +382,7 @@ void Session::doRead() } catch (std::exception const& _e) { - clog(NetWarn) << "Exception decoding frame header RLP:" << bytesConstRef(m_data.data(), h128::size).cropped(3); + clog(NetWarn) << _e.what() << "Exception decoding frame header RLP:" << bytesConstRef(m_data.data(), h128::size).cropped(3); drop(BadProtocol); return; } diff --git a/test/libwhisper/bloomFilter.cpp b/test/libwhisper/bloomFilter.cpp index 299fd3f5b..197a7258d 100644 --- a/test/libwhisper/bloomFilter.cpp +++ b/test/libwhisper/bloomFilter.cpp @@ -28,7 +28,7 @@ using namespace dev; using namespace dev::shh; using TopicBloomFilterShort = TopicBloomFilterBase<4>; -using TopicBloomFilterTest = TopicBloomFilterBase; +using TopicBloomFilterTest = TopicBloomFilterBase; void testAddNonExisting(TopicBloomFilterShort& _f, AbridgedTopic const& _h) { @@ -61,7 +61,7 @@ void testRemoveExistingBloom(TopicBloomFilterShort& _f, AbridgedTopic const& _h) double calculateExpected(TopicBloomFilterTest const& f, int n) { int const m = f.size * 8; // number of bits in the bloom - int const k = f.BitsPerBloom; // number of hash functions (e.g. bits set to 1 in every bloom) + int const k = BitsPerBloom; // number of hash functions (e.g. bits set to 1 in every bloom) double singleBitSet = 1.0 / m; // probability of any bit being set after inserting a single bit double singleBitNotSet = (1.0 - singleBitSet); @@ -256,7 +256,7 @@ void updateDistribution(FixedHash const& _h, array= TopicBloomFilterTest::BitsPerBloom) + if (++bits >= BitsPerBloom) return; } } @@ -274,7 +274,7 @@ BOOST_AUTO_TEST_CASE(distributionRate) for (unsigned i = 0; i < 22000; ++i) { x = sha3(x); - FixedHash h = x.template bloomPart(); + FixedHash h = x.template bloomPart(); updateDistribution(h, distribution); } From 382c4768261c2bdef7110f70d4066b1e1c2fe5c4 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 2 Jul 2015 09:18:16 +0200 Subject: [PATCH 090/290] removed incorrect invariants (subject to race condition) --- libethereum/BlockChainSync.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 9dda66b7d..282a3d564 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -805,10 +805,6 @@ bool PV60Sync::invariants() const BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("Active while peer not syncing")); if (m_state == SyncState::Hashes) { - bool hashes = false; - host().foreachPeer([&](std::shared_ptr _p) { if (_p->m_asking == Asking::Hashes) hashes = true; return !hashes; }); - if (!hashes) - BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("No peers asking for hashes")); if (!m_syncingLatestHash) BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("m_syncingLatestHash is not set while downloading hashes")); if (m_syncingNeededBlocks.empty() != (!m_syncingLastReceivedHash)) @@ -816,10 +812,6 @@ bool PV60Sync::invariants() const } if (m_state == SyncState::Blocks || m_state == SyncState::NewBlocks) { - bool blocks = false; - host().foreachPeer([&](std::shared_ptr _p) { if (_p->m_asking == Asking::Blocks) blocks = true; return !blocks; }); - if (!blocks) - BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("No peers asking for blocks")); if (downloadMan().isComplete()) BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("Block download complete but the state is still Blocks")); } @@ -1095,10 +1087,6 @@ bool PV61Sync::invariants() const BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("m_downloadingChainMap and m_chainSyncPeers out of sync")); if (m_state == SyncState::Hashes) { - bool hashes = false; - host().foreachPeer([&](std::shared_ptr _p) { if (_p->m_asking == Asking::Hashes) hashes = true; return !hashes; }); - if (!hashes) - BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("No peers asking for hashes")); if (isPV61Syncing() && !m_syncingBlockNumber) BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("Syncing in PV61 with no block number set")); } From e6cfbe582454d5a4934ec37b721d8554275ec4f7 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 2 Jul 2015 10:38:02 +0200 Subject: [PATCH 091/290] ethkey can sign & recover transaction information. AZ can have sentinel set. Split up Transaction and move most to ethcore. --- alethzero/Main.ui | 22 +++-- alethzero/MainWin.cpp | 8 ++ alethzero/MainWin.h | 1 + ethkey/KeyAux.h | 171 +++++++++++++++++++++++++++++++--- libethcore/CMakeLists.txt | 2 +- libethcore/Transaction.cpp | 118 ++++++++++++++++++++++++ libethcore/Transaction.h | 177 ++++++++++++++++++++++++++++++++++++ libethereum/Client.cpp | 3 +- libethereum/Client.h | 2 + libethereum/Transaction.cpp | 87 +----------------- libethereum/Transaction.h | 126 +------------------------ 11 files changed, 484 insertions(+), 233 deletions(-) create mode 100644 libethcore/Transaction.cpp create mode 100644 libethcore/Transaction.h diff --git a/alethzero/Main.ui b/alethzero/Main.ui index f798437e6..e12756d6e 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -44,14 +44,14 @@ 0 bytes used - - - - - - - - + + + + + + + + @@ -224,6 +224,7 @@ &Config + @@ -1782,6 +1783,11 @@ font-size: 14pt &Gas Prices... + + + &Sentinel... + + diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 821022abc..445b5fdac 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -296,6 +296,14 @@ void Main::on_gasPrices_triggered() } } +void Main::on_sentinel_triggered() +{ + bool ok; + QString sentinel = QInputDialog::getText(nullptr, "Enter sentinel address", "Enter the sentinel address for bad block reporting (e.g. http://badblockserver.com:8080). Enter nothing to disable.", QLineEdit::Normal, QString::fromStdString(ethereum()->sentinel()), &ok); + if (ok) + ethereum()->setSentinel(sentinel.toStdString()); +} + void Main::on_newIdentity_triggered() { KeyPair kp = KeyPair::create(); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index f8a6fa6c7..a3f6328cd 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -196,6 +196,7 @@ private slots: // Config void on_gasPrices_triggered(); + void on_sentinel_triggered(); void refreshWhisper(); void refreshBlockChain(); diff --git a/ethkey/KeyAux.h b/ethkey/KeyAux.h index ae8eaed92..af7d8e048 100644 --- a/ethkey/KeyAux.h +++ b/ethkey/KeyAux.h @@ -32,6 +32,7 @@ #include #include #include +#include #include "BuildInfo.h" using namespace std; using namespace dev; @@ -105,7 +106,9 @@ public: ImportWithAddress, Export, Recode, - Kill + Kill, + SignTx, + DecodeTx, }; KeyCLI(OperationMode _mode = OperationMode::None): m_mode(_mode) {} @@ -131,8 +134,13 @@ public: auto v = argv[++i]; m_kdfParams[n] = v; } - else if (arg == "--new-bare") - m_mode = OperationMode::NewBare; + else if (arg == "--sign-tx" && i + 1 < argc) + { + m_mode = OperationMode::SignTx; + m_signKey = argv[++i]; + } + else if (arg == "--decode-tx") + m_mode = OperationMode::DecodeTx; else if (arg == "--import-bare") m_mode = OperationMode::ImportBare; else if (arg == "--list-bare") @@ -173,7 +181,7 @@ public: m_mode = OperationMode::Recode; else if (arg == "--no-icap") m_icap = false; - else if (m_mode == OperationMode::ImportBare || m_mode == OperationMode::InspectBare || m_mode == OperationMode::KillBare || m_mode == OperationMode::Recode || m_mode == OperationMode::Export || m_mode == OperationMode::RecodeBare || m_mode == OperationMode::ExportBare) + else if (m_mode == OperationMode::DecodeTx || m_mode == OperationMode::SignTx || m_mode == OperationMode::ImportBare || m_mode == OperationMode::InspectBare || m_mode == OperationMode::KillBare || m_mode == OperationMode::Recode || m_mode == OperationMode::Export || m_mode == OperationMode::RecodeBare || m_mode == OperationMode::ExportBare) m_inputs.push_back(arg); else return false; @@ -209,6 +217,127 @@ public: } } } + else if (m_mode == OperationMode::DecodeTx) + { + string const& i = m_inputs[0]; + bytes b = fromHex(i); + if (b.empty()) + { + std::string s = contentsString(i); + b = fromHex(s); + if (b.empty()) + b = asBytes(s); + } + if (b.empty()) + cerr << "Unknown file or bad hex: " << i << endl; + else + try + { + TransactionBase t(b, CheckTransaction::Everything); + cout << "Transaction " << t.sha3().hex() << endl; + if (t.isCreation()) + { + cout << " type: creation" << endl; + cout << " code: " << toHex(t.data()) << endl; + } + else + { + cout << " type: message" << endl; + cout << " to: " << t.to().hex() << endl; + cout << " data: " << (t.data().empty() ? "none" : toHex(t.data())) << endl; + } + cout << " from: " << t.from().hex() << endl; + cout << " value: " << formatBalance(t.value()) << " (" << t.value() << " wei)" << endl; + cout << " nonce: " << t.nonce() << endl; + cout << " gas: " << t.gas() << endl; + cout << " gas price: " << formatBalance(t.gasPrice()) << " (" << t.gasPrice() << " wei)" << endl; + cout << " signing hash: " << t.sha3(WithoutSignature).hex() << endl; + cout << " v: " << (int)t.signature().v << endl; + cout << " r: " << t.signature().r << endl; + cout << " s: " << t.signature().s << endl; + } + catch (Exception& ex) + { + cerr << "Invalid transaction: " << ex.what() << endl; + } + } + else if (m_mode == OperationMode::SignTx) + { + Secret s; + + string json = contentsString(m_signKey); + if (!json.empty()) + { + SecretStore store(m_secretsPath); + s = Secret(store.secret(store.readKeyContent(json), [&](){ return getPassword("Enter password for key: "); })); + } + else + { + if (h128 u = fromUUID(m_signKey)) + { + SecretStore store(m_secretsPath); + s = Secret(store.secret(u, [&](){ return getPassword("Enter password for key: "); })); + } + else if (Address a = Address(m_signKey)) + { + KeyManager wallet(m_walletPath, m_secretsPath); + if (wallet.exists()) + { + openWallet(wallet); + s = wallet.secret(a, [&](){ return getPassword("Enter password for key: "); }); + } + else + { + cerr << "Wallet doesn't exist." << endl; + exit(-1); + } + } + else + { + cerr << "Bad file, UUID and address: " << m_signKey << endl; + exit(-1); + } + } + if (!s) + { + cerr << "UUID/address not found: " << m_signKey << endl; + exit(-1); + } + + for (string const& i: m_inputs) + { + bytes b = fromHex(i); + bool isFile = false; + if (b.empty()) + { + isFile = true; + std::string s = contentsString(i); + b = fromHex(s); + if (b.empty()) + b = asBytes(s); + } + if (b.empty()) + cerr << "Unknown file or bad hex: " << i << endl; + else + try + { + TransactionBase t(b, CheckTransaction::None); + t.sign(s); + cout << t.sha3() << ": "; + if (isFile) + { + writeFile(i + ".signed", t.data()); + cout << i + ".signed" << endl; + } + else + cout << toHex(t.data()) << endl; + } + catch (Exception& ex) + { + cerr << "Invalid transaction: " << ex.what() << endl; + } + } + } else if (m_mode < OperationMode::CreateWallet) { SecretStore store(m_secretsPath); @@ -297,17 +426,7 @@ public: { KeyManager wallet(m_walletPath, m_secretsPath); if (wallet.exists()) - while (true) - { - if (wallet.load(m_masterPassword)) - break; - if (!m_masterPassword.empty()) - { - cout << "Password invalid. Try again." << endl; - m_masterPassword.clear(); - } - m_masterPassword = getPassword("Please enter your MASTER password: "); - } + openWallet(wallet); else { cerr << "Couldn't open wallet. Does it exist?" << endl; @@ -419,6 +538,10 @@ public: << " --wallet-path Specify Ethereum wallet path (default: " << KeyManager::defaultPath() << ")" << endl << " -m, --master Specify wallet (master) password." << endl << endl + << "Transaction operating modes:" << endl + << " -d,--decode-tx [|] Decode given transaction." << endl + << " -s,--sign-tx [
|| ] [ | , ... ] (Re-)Sign given transaction." << endl + << endl << "Encryption configuration:" << endl << " --kdf Specify KDF to use when encrypting (default: sc rypt)" << endl << " --kdf-param Specify a parameter for the KDF." << endl @@ -445,6 +568,21 @@ public: } private: + void openWallet(KeyManager& _w) + { + while (true) + { + if (_w.load(m_masterPassword)) + break; + if (!m_masterPassword.empty()) + { + cout << "Password invalid. Try again." << endl; + m_masterPassword.clear(); + } + m_masterPassword = getPassword("Please enter your MASTER password: "); + } + } + KDF kdf() const { return m_kdf == "pbkdf2" ? KDF::PBKDF2_SHA256 : KDF::Scrypt; } /// Operating mode. @@ -468,6 +606,9 @@ private: /// Importing strings m_inputs; + /// Signing + string m_signKey; + string m_kdf = "scrypt"; map m_kdfParams; // string m_cipher; diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt index a527ad1f4..4dd626642 100644 --- a/libethcore/CMakeLists.txt +++ b/libethcore/CMakeLists.txt @@ -28,7 +28,7 @@ add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} ethash) target_link_libraries(${EXECUTABLE} devcrypto) -#target_link_libraries(${EXECUTABLE} evmcore) +target_link_libraries(${EXECUTABLE} evmcore) if (ETHASHCL) target_link_libraries(${EXECUTABLE} ethash-cl) diff --git a/libethcore/Transaction.cpp b/libethcore/Transaction.cpp new file mode 100644 index 000000000..5e08acd4d --- /dev/null +++ b/libethcore/Transaction.cpp @@ -0,0 +1,118 @@ +/* + 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 TransactionBase.cpp + * @author Gav Wood + * @date 2014 + */ + +#include +#include +#include +#include +#include +#include "Transaction.h" +using namespace std; +using namespace dev; +using namespace dev::eth; + +TransactionBase::TransactionBase(bytesConstRef _rlpData, CheckTransaction _checkSig) +{ + int field = 0; + RLP rlp(_rlpData); + try + { + if (!rlp.isList()) + BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("transaction RLP must be a list")); + + m_nonce = rlp[field = 0].toInt(); + m_gasPrice = rlp[field = 1].toInt(); + m_gas = rlp[field = 2].toInt(); + m_type = rlp[field = 3].isEmpty() ? ContractCreation : MessageCall; + m_receiveAddress = rlp[field = 3].isEmpty() ? Address() : rlp[field = 3].toHash
(RLP::VeryStrict); + m_value = rlp[field = 4].toInt(); + + if (!rlp[field = 5].isData()) + BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("transaction data RLP must be an array")); + + m_data = rlp[field = 5].toBytes(); + byte v = rlp[field = 6].toInt() - 27; + h256 r = rlp[field = 7].toInt(); + h256 s = rlp[field = 8].toInt(); + + if (rlp.itemCount() > 9) + BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("to many fields in the transaction RLP")); + + m_vrs = SignatureStruct{ r, s, v }; + if (_checkSig >= CheckTransaction::Cheap && !m_vrs.isValid()) + BOOST_THROW_EXCEPTION(InvalidSignature()); + if (_checkSig == CheckTransaction::Everything) + m_sender = sender(); + } + catch (Exception& _e) + { + _e << errinfo_name("invalid transaction format") << BadFieldError(field, toHex(rlp[field].data().toBytes())); + throw; + } +} + +Address const& TransactionBase::safeSender() const noexcept +{ + try + { + return sender(); + } + catch (...) + { + cwarn << "safeSender() did throw an exception: " << boost::current_exception_diagnostic_information(); + return ZeroAddress; + } +} + +Address const& TransactionBase::sender() const +{ + if (!m_sender) + { + auto p = recover(m_vrs, sha3(WithoutSignature)); + if (!p) + BOOST_THROW_EXCEPTION(InvalidSignature()); + m_sender = right160(dev::sha3(bytesConstRef(p.data(), sizeof(p)))); + } + return m_sender; +} + +void TransactionBase::sign(Secret const& _priv) +{ + auto sig = dev::sign(_priv, sha3(WithoutSignature)); + SignatureStruct sigStruct = *(SignatureStruct const*)&sig; + if (sigStruct.isValid()) + m_vrs = sigStruct; +} + +void TransactionBase::streamRLP(RLPStream& _s, IncludeSignature _sig) const +{ + if (m_type == NullTransaction) + return; + _s.appendList((_sig ? 3 : 0) + 6); + _s << m_nonce << m_gasPrice << m_gas; + if (m_type == MessageCall) + _s << m_receiveAddress; + else + _s << ""; + _s << m_value << m_data; + if (_sig) + _s << (m_vrs.v + 27) << (u256)m_vrs.r << (u256)m_vrs.s; +} diff --git a/libethcore/Transaction.h b/libethcore/Transaction.h new file mode 100644 index 000000000..e5eeb74b4 --- /dev/null +++ b/libethcore/Transaction.h @@ -0,0 +1,177 @@ +/* + 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 TransactionBase.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#include +#include +#include + +namespace dev +{ +namespace eth +{ + +/// Named-boolean type to encode whether a signature be included in the serialisation process. +enum IncludeSignature +{ + WithoutSignature = 0, ///< Do not include a signature. + WithSignature = 1, ///< Do include a signature. +}; + +enum class CheckTransaction +{ + None, + Cheap, + Everything +}; + +/// Encodes a transaction, ready to be exported to or freshly imported from RLP. +class TransactionBase +{ +public: + /// Constructs a null transaction. + TransactionBase() {} + + /// Constructs a signed message-call transaction. + TransactionBase(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data, u256 const& _nonce, Secret const& _secret): m_type(MessageCall), m_nonce(_nonce), m_value(_value), m_receiveAddress(_dest), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) { sign(_secret); } + + /// Constructs a signed contract-creation transaction. + TransactionBase(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data, u256 const& _nonce, Secret const& _secret): m_type(ContractCreation), m_nonce(_nonce), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) { sign(_secret); } + + /// Constructs an unsigned message-call transaction. + TransactionBase(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data, u256 const& _nonce = 0): m_type(MessageCall), m_nonce(_nonce), m_value(_value), m_receiveAddress(_dest), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {} + + /// Constructs an unsigned contract-creation transaction. + TransactionBase(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data, u256 const& _nonce = 0): m_type(ContractCreation), m_nonce(_nonce), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {} + + /// Constructs a transaction from the given RLP. + explicit TransactionBase(bytesConstRef _rlp, CheckTransaction _checkSig); + + /// Constructs a transaction from the given RLP. + explicit TransactionBase(bytes const& _rlp, CheckTransaction _checkSig): TransactionBase(&_rlp, _checkSig) {} + + + /// Checks equality of transactions. + bool operator==(TransactionBase const& _c) const { return m_type == _c.m_type && (m_type == ContractCreation || m_receiveAddress == _c.m_receiveAddress) && m_value == _c.m_value && m_data == _c.m_data; } + /// Checks inequality of transactions. + bool operator!=(TransactionBase const& _c) const { return !operator==(_c); } + + /// @returns sender of the transaction from the signature (and hash). + Address const& sender() const; + /// Like sender() but will never throw. @returns a null Address if the signature is invalid. + Address const& safeSender() const noexcept; + /// Force the sender to a particular value. This will result in an invalid transaction RLP. + void forceSender(Address const& _a) { m_sender = _a; } + + /// @returns true if transaction is non-null. + explicit operator bool() const { return m_type != NullTransaction; } + + /// @returns true if transaction is contract-creation. + bool isCreation() const { return m_type == ContractCreation; } + + /// @returns true if transaction is message-call. + bool isMessageCall() const { return m_type == MessageCall; } + + /// Serialises this transaction to an RLPStream. + void streamRLP(RLPStream& _s, IncludeSignature _sig = WithSignature) const; + + /// @returns the RLP serialisation of this transaction. + bytes rlp(IncludeSignature _sig = WithSignature) const { RLPStream s; streamRLP(s, _sig); return s.out(); } + + /// @returns the SHA3 hash of the RLP serialisation of this transaction. + h256 sha3(IncludeSignature _sig = WithSignature) const { if (_sig == WithSignature && m_hashWith) return m_hashWith; RLPStream s; streamRLP(s, _sig); auto ret = dev::sha3(s.out()); if (_sig == WithSignature) m_hashWith = ret; return ret; } + + /// @returns the amount of ETH to be transferred by this (message-call) transaction, in Wei. Synonym for endowment(). + u256 value() const { return m_value; } + /// @returns the amount of ETH to be endowed by this (contract-creation) transaction, in Wei. Synonym for value(). + u256 endowment() const { return m_value; } + + /// @returns the base fee and thus the implied exchange rate of ETH to GAS. + u256 gasPrice() const { return m_gasPrice; } + + /// @returns the total gas to convert, paid for from sender's account. Any unused gas gets refunded once the contract is ended. + u256 gas() const { return m_gas; } + + /// @returns the receiving address of the message-call transaction (undefined for contract-creation transactions). + Address receiveAddress() const { return m_receiveAddress; } + + /// Synonym for receiveAddress(). + Address to() const { return m_receiveAddress; } + + /// Synonym for safeSender(). + Address from() const { return safeSender(); } + + /// @returns the data associated with this (message-call) transaction. Synonym for initCode(). + bytes const& data() const { return m_data; } + /// @returns the initialisation code associated with this (contract-creation) transaction. Synonym for data(). + bytes const& initCode() const { return m_data; } + + /// @returns the transaction-count of the sender. + u256 nonce() const { return m_nonce; } + + /// @returns the signature of the transaction. Encodes the sender. + SignatureStruct const& signature() const { return m_vrs; } + + void sign(Secret const& _priv); ///< Sign the transaction. + +protected: + /// Type of transaction. + enum Type + { + NullTransaction, ///< Null transaction. + ContractCreation, ///< Transaction to create contracts - receiveAddress() is ignored. + MessageCall ///< Transaction to invoke a message call - receiveAddress() is used. + }; + + Type m_type = NullTransaction; ///< Is this a contract-creation transaction or a message-call transaction? + u256 m_nonce; ///< The transaction-count of the sender. + u256 m_value; ///< The amount of ETH to be transferred by this transaction. Called 'endowment' for contract-creation transactions. + Address m_receiveAddress; ///< The receiving address of the transaction. + u256 m_gasPrice; ///< The base fee and thus the implied exchange rate of ETH to GAS. + u256 m_gas; ///< The total gas to convert, paid for from sender's account. Any unused gas gets refunded once the contract is ended. + bytes m_data; ///< The data associated with the transaction, or the initialiser if it's a creation transaction. + SignatureStruct m_vrs; ///< The signature of the transaction. Encodes the sender. + + mutable h256 m_hashWith; ///< Cached hash of transaction with signature. + mutable Address m_sender; ///< Cached sender, determined from signature. + mutable bigint m_gasRequired = 0; ///< Memoised amount required for the transaction to run. +}; + +/// Nice name for vector of Transaction. +using TransactionBases = std::vector; + +/// Simple human-readable stream-shift operator. +inline std::ostream& operator<<(std::ostream& _out, TransactionBase const& _t) +{ + _out << _t.sha3().abridged() << "{"; + if (_t.receiveAddress()) + _out << _t.receiveAddress().abridged(); + else + _out << "[CREATE]"; + + _out << "/" << _t.data().size() << "$" << _t.value() << "+" << _t.gas() << "@" << _t.gasPrice(); + _out << "<-" << _t.safeSender().abridged() << " #" << _t.nonce() << "}"; + return _out; +} + +} +} diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index c7d7c60c4..1e2cbf940 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -339,7 +339,8 @@ Client::~Client() stopWorking(); } -static const Address c_canary("0x"); +static const Address c_canary("0x73c054b5865c427064641725a51032458d1d59b5"); +static const Addresses c_canaries = {}; bool Client::isChainBad() const { diff --git a/libethereum/Client.h b/libethereum/Client.h index f38c7c099..98ea253ce 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -240,6 +240,8 @@ public: ActivityReport activityReport() { ActivityReport ret; std::swap(m_report, ret); return ret; } /// Set a JSONRPC server to which we can report bad blocks. void setSentinel(std::string const& _server) { m_sentinel = _server; } + /// Get the JSONRPC server to which we report bad blocks. + std::string const& sentinel() const { return m_sentinel; } protected: /// InterfaceStub methods diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp index 40a7914d3..70f82c6d2 100644 --- a/libethereum/Transaction.cpp +++ b/libethereum/Transaction.cpp @@ -94,99 +94,16 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, TransactionException cons return _out; } -Transaction::Transaction(bytesConstRef _rlpData, CheckTransaction _checkSig) +Transaction::Transaction(bytesConstRef _rlpData, CheckTransaction _checkSig): + TransactionBase(_rlpData, _checkSig) { - int field = 0; - RLP rlp(_rlpData); - try - { - if (!rlp.isList()) - BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("transaction RLP must be a list")); - - m_nonce = rlp[field = 0].toInt(); - m_gasPrice = rlp[field = 1].toInt(); - m_gas = rlp[field = 2].toInt(); - m_type = rlp[field = 3].isEmpty() ? ContractCreation : MessageCall; - m_receiveAddress = rlp[field = 3].isEmpty() ? Address() : rlp[field = 3].toHash
(RLP::VeryStrict); - m_value = rlp[field = 4].toInt(); - - if (!rlp[field = 5].isData()) - BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("transaction data RLP must be an array")); - - m_data = rlp[field = 5].toBytes(); - byte v = rlp[field = 6].toInt() - 27; - h256 r = rlp[field = 7].toInt(); - h256 s = rlp[field = 8].toInt(); - - if (rlp.itemCount() > 9) - BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("to many fields in the transaction RLP")); - - m_vrs = SignatureStruct{ r, s, v }; - if (_checkSig >= CheckTransaction::Cheap && !m_vrs.isValid()) - BOOST_THROW_EXCEPTION(InvalidSignature()); - if (_checkSig == CheckTransaction::Everything) - m_sender = sender(); - } - catch (Exception& _e) - { - _e << errinfo_name("invalid transaction format") << BadFieldError(field, toHex(rlp[field].data().toBytes())); - throw; - } if (_checkSig >= CheckTransaction::Cheap && !checkPayment()) BOOST_THROW_EXCEPTION(OutOfGasIntrinsic() << RequirementError(gasRequired(), (bigint)gas())); } -Address const& Transaction::safeSender() const noexcept -{ - try - { - return sender(); - } - catch (...) - { - cwarn << "safeSender() did throw an exception: " << boost::current_exception_diagnostic_information(); - return ZeroAddress; - } -} - -Address const& Transaction::sender() const -{ - if (!m_sender) - { - auto p = recover(m_vrs, sha3(WithoutSignature)); - if (!p) - BOOST_THROW_EXCEPTION(InvalidSignature()); - m_sender = right160(dev::sha3(bytesConstRef(p.data(), sizeof(p)))); - } - return m_sender; -} - bigint Transaction::gasRequired() const { if (!m_gasRequired) m_gasRequired = Transaction::gasRequired(m_data); return m_gasRequired; } - -void Transaction::sign(Secret _priv) -{ - auto sig = dev::sign(_priv, sha3(WithoutSignature)); - SignatureStruct sigStruct = *(SignatureStruct const*)&sig; - if (sigStruct.isValid()) - m_vrs = sigStruct; -} - -void Transaction::streamRLP(RLPStream& _s, IncludeSignature _sig) const -{ - if (m_type == NullTransaction) - return; - _s.appendList((_sig ? 3 : 0) + 6); - _s << m_nonce << m_gasPrice << m_gas; - if (m_type == MessageCall) - _s << m_receiveAddress; - else - _s << ""; - _s << m_value << m_data; - if (_sig) - _s << (m_vrs.v + 27) << (u256)m_vrs.r << (u256)m_vrs.s; -} diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h index 4de9d7e92..95e1619fe 100644 --- a/libethereum/Transaction.h +++ b/libethereum/Transaction.h @@ -24,6 +24,7 @@ #include #include #include +#include #include namespace dev @@ -31,20 +32,6 @@ namespace dev namespace eth { -/// Named-boolean type to encode whether a signature be included in the serialisation process. -enum IncludeSignature -{ - WithoutSignature = 0, ///< Do not include a signature. - WithSignature = 1, ///< Do include a signature. -}; - -enum class CheckTransaction -{ - None, - Cheap, - Everything -}; - enum class TransactionException { None = 0, @@ -92,23 +79,13 @@ struct ExecutionResult std::ostream& operator<<(std::ostream& _out, ExecutionResult const& _er); /// Encodes a transaction, ready to be exported to or freshly imported from RLP. -class Transaction +class Transaction: public TransactionBase { public: /// Constructs a null transaction. Transaction() {} - /// Constructs a signed message-call transaction. - Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data, u256 const& _nonce, Secret const& _secret): m_type(MessageCall), m_nonce(_nonce), m_value(_value), m_receiveAddress(_dest), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) { sign(_secret); } - - /// Constructs a signed contract-creation transaction. - Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data, u256 const& _nonce, Secret const& _secret): m_type(ContractCreation), m_nonce(_nonce), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) { sign(_secret); } - - /// Constructs an unsigned message-call transaction. - Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data, u256 const& _nonce = 0): m_type(MessageCall), m_nonce(_nonce), m_value(_value), m_receiveAddress(_dest), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {} - - /// Constructs an unsigned contract-creation transaction. - Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data, u256 const& _nonce = 0): m_type(ContractCreation), m_nonce(_nonce), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {} + using TransactionBase::TransactionBase; /// Constructs a transaction from the given RLP. explicit Transaction(bytesConstRef _rlp, CheckTransaction _checkSig); @@ -116,68 +93,6 @@ public: /// Constructs a transaction from the given RLP. explicit Transaction(bytes const& _rlp, CheckTransaction _checkSig): Transaction(&_rlp, _checkSig) {} - - /// Checks equality of transactions. - bool operator==(Transaction const& _c) const { return m_type == _c.m_type && (m_type == ContractCreation || m_receiveAddress == _c.m_receiveAddress) && m_value == _c.m_value && m_data == _c.m_data; } - /// Checks inequality of transactions. - bool operator!=(Transaction const& _c) const { return !operator==(_c); } - - /// @returns sender of the transaction from the signature (and hash). - Address const& sender() const; - /// Like sender() but will never throw. @returns a null Address if the signature is invalid. - Address const& safeSender() const noexcept; - /// Force the sender to a particular value. This will result in an invalid transaction RLP. - void forceSender(Address const& _a) { m_sender = _a; } - - /// @returns true if transaction is non-null. - explicit operator bool() const { return m_type != NullTransaction; } - - /// @returns true if transaction is contract-creation. - bool isCreation() const { return m_type == ContractCreation; } - - /// @returns true if transaction is message-call. - bool isMessageCall() const { return m_type == MessageCall; } - - /// Serialises this transaction to an RLPStream. - void streamRLP(RLPStream& _s, IncludeSignature _sig = WithSignature) const; - - /// @returns the RLP serialisation of this transaction. - bytes rlp(IncludeSignature _sig = WithSignature) const { RLPStream s; streamRLP(s, _sig); return s.out(); } - - /// @returns the SHA3 hash of the RLP serialisation of this transaction. - h256 sha3(IncludeSignature _sig = WithSignature) const { if (_sig == WithSignature && m_hashWith) return m_hashWith; RLPStream s; streamRLP(s, _sig); auto ret = dev::sha3(s.out()); if (_sig == WithSignature) m_hashWith = ret; return ret; } - - /// @returns the amount of ETH to be transferred by this (message-call) transaction, in Wei. Synonym for endowment(). - u256 value() const { return m_value; } - /// @returns the amount of ETH to be endowed by this (contract-creation) transaction, in Wei. Synonym for value(). - u256 endowment() const { return m_value; } - - /// @returns the base fee and thus the implied exchange rate of ETH to GAS. - u256 gasPrice() const { return m_gasPrice; } - - /// @returns the total gas to convert, paid for from sender's account. Any unused gas gets refunded once the contract is ended. - u256 gas() const { return m_gas; } - - /// @returns the receiving address of the message-call transaction (undefined for contract-creation transactions). - Address receiveAddress() const { return m_receiveAddress; } - - /// Synonym for receiveAddress(). - Address to() const { return m_receiveAddress; } - - /// Synonym for safeSender(). - Address from() const { return safeSender(); } - - /// @returns the data associated with this (message-call) transaction. Synonym for initCode(). - bytes const& data() const { return m_data; } - /// @returns the initialisation code associated with this (contract-creation) transaction. Synonym for data(). - bytes const& initCode() const { return m_data; } - - /// @returns the transaction-count of the sender. - u256 nonce() const { return m_nonce; } - - /// @returns the signature of the transaction. Encodes the sender. - SignatureStruct const& signature() const { return m_vrs; } - /// @returns true if the transaction contains enough gas for the basic payment. bool checkPayment() const { return m_gas >= gasRequired(); } @@ -188,46 +103,11 @@ public: template static bigint gasRequired(T const& _data, u256 _gas = 0) { bigint ret = c_txGas + _gas; for (auto i: _data) ret += i ? c_txDataNonZeroGas : c_txDataZeroGas; return ret; } private: - /// Type of transaction. - enum Type - { - NullTransaction, ///< Null transaction. - ContractCreation, ///< Transaction to create contracts - receiveAddress() is ignored. - MessageCall ///< Transaction to invoke a message call - receiveAddress() is used. - }; - - void sign(Secret _priv); ///< Sign the transaction. - - Type m_type = NullTransaction; ///< Is this a contract-creation transaction or a message-call transaction? - u256 m_nonce; ///< The transaction-count of the sender. - u256 m_value; ///< The amount of ETH to be transferred by this transaction. Called 'endowment' for contract-creation transactions. - Address m_receiveAddress; ///< The receiving address of the transaction. - u256 m_gasPrice; ///< The base fee and thus the implied exchange rate of ETH to GAS. - u256 m_gas; ///< The total gas to convert, paid for from sender's account. Any unused gas gets refunded once the contract is ended. - bytes m_data; ///< The data associated with the transaction, or the initialiser if it's a creation transaction. - SignatureStruct m_vrs; ///< The signature of the transaction. Encodes the sender. - - mutable h256 m_hashWith; ///< Cached hash of transaction with signature. - mutable Address m_sender; ///< Cached sender, determined from signature. mutable bigint m_gasRequired = 0; ///< Memoised amount required for the transaction to run. }; /// Nice name for vector of Transaction. using Transactions = std::vector; -/// Simple human-readable stream-shift operator. -inline std::ostream& operator<<(std::ostream& _out, Transaction const& _t) -{ - _out << _t.sha3().abridged() << "{"; - if (_t.receiveAddress()) - _out << _t.receiveAddress().abridged(); - else - _out << "[CREATE]"; - - _out << "/" << _t.data().size() << "$" << _t.value() << "+" << _t.gas() << "@" << _t.gasPrice(); - _out << "<-" << _t.safeSender().abridged() << " #" << _t.nonce() << "}"; - return _out; -} - } } From 4ce9fe8ed07d5fd4416782ba9c2925d72527b6f4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 2 Jul 2015 11:29:31 +0200 Subject: [PATCH 092/290] Windwos fix. --- libdevcore/RangeMask.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcore/RangeMask.h b/libdevcore/RangeMask.h index d87b81a3a..eccc8305d 100644 --- a/libdevcore/RangeMask.h +++ b/libdevcore/RangeMask.h @@ -217,7 +217,7 @@ template inline std::ostream& operator<<(std::ostream& _out, RangeMask } template -RangeMask& RangeMask::unionWith(RangeMask::Range const& _m) +RangeMask& RangeMask::unionWith(typename RangeMask::Range const& _m) { for (auto i = _m.first; i < _m.second;) { From 603218dc6ef79f63b90b974da6b3f4c94491f8a3 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 2 Jul 2015 11:48:57 +0200 Subject: [PATCH 093/290] Fix deadlocks. --- libethereum/BlockQueue.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index 89de9ccf1..e5ff5fa8d 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -336,7 +336,6 @@ void BlockQueue::updateBad_WITH_LOCK(h256 const& _bad) void BlockQueue::collectUnknownBad_WITH_BOTH_LOCKS(h256 const& _bad) { - DEV_INVARIANT_CHECK; list badQueue(1, _bad); while (!badQueue.empty()) { @@ -504,7 +503,6 @@ void BlockQueue::noteReady_WITH_LOCK(h256 const& _good) } if (notify) m_moreToVerify.notify_all(); - DEV_INVARIANT_CHECK; } void BlockQueue::retryAllUnknown() From e83e3b6cb60b5d888d5b3ba2f5c28942f1676bfc Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 2 Jul 2015 11:49:05 +0200 Subject: [PATCH 094/290] Testnet canaries. --- libethereum/Client.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 1e2cbf940..0031c8a60 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -339,17 +339,26 @@ Client::~Client() stopWorking(); } -static const Address c_canary("0x73c054b5865c427064641725a51032458d1d59b5"); -static const Addresses c_canaries = {}; +static const Addresses c_canaries = +{ + Address("4bb7e8ae99b645c2b7860b8f3a2328aae28bd80a"), + Address("1baf27b88c48dd02b744999cf3522766929d2b2a"), + Address("a8edb1ac2c86d3d9d78f96cd18001f60df29e52c"), + Address("60d11b58744784dc97f878f7e3749c0f1381a004") +}; bool Client::isChainBad() const { - return stateAt(c_canary, 0) != 0; + unsigned numberBad = 0; + for (auto const& a: c_canaries) + if (!!stateAt(a, 0)) + numberBad++; + return numberBad >= 2; } bool Client::isUpgradeNeeded() const { - return stateAt(c_canary, 0) == 2; + return stateAt(c_canaries[0], 0) == 2; } void Client::setNetworkId(u256 _n) From 4983db8e58086c8e287c503e7be4f5aedfdc95bb Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 2 Jul 2015 12:26:29 +0200 Subject: [PATCH 095/290] removed unneeded invariant checks, fixed disconnect message priority --- libethereum/BlockChainSync.cpp | 2 -- libp2p/Session.cpp | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 9dda66b7d..30dbf2964 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -92,7 +92,6 @@ void BlockChainSync::onPeerStatus(std::shared_ptr _peer) _peer->m_expectedHashes = hashes; onNewPeer(_peer); } - DEV_INVARIANT_CHECK; } unsigned BlockChainSync::estimatedHashes() const @@ -293,7 +292,6 @@ void BlockChainSync::onPeerNewBlock(std::shared_ptr _peer, RLP con DEV_GUARDED(_peer->x_knownBlocks) _peer->m_knownBlocks.insert(h); } - DEV_INVARIANT_CHECK; } PV60Sync::PV60Sync(EthereumHost& _host): diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp index e44c365f4..f28d25e88 100644 --- a/libp2p/Session.cpp +++ b/libp2p/Session.cpp @@ -315,7 +315,7 @@ void Session::drop(DisconnectReason _reason) if (socket.is_open()) try { - clog(NetWarn) << "Closing " << socket.remote_endpoint() << "(" << reasonOf(_reason) << ")"; + clog(NetConnect) << "Closing " << socket.remote_endpoint() << "(" << reasonOf(_reason) << ")"; boost::system::error_code ec; socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); socket.close(); From 9e0cde38d0a832ea1656d1bfea835feb4a534d22 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 2 Jul 2015 13:04:40 +0200 Subject: [PATCH 096/290] Who are they? --- libethereum/Client.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 0031c8a60..803fa7265 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -341,10 +341,10 @@ Client::~Client() static const Addresses c_canaries = { - Address("4bb7e8ae99b645c2b7860b8f3a2328aae28bd80a"), - Address("1baf27b88c48dd02b744999cf3522766929d2b2a"), - Address("a8edb1ac2c86d3d9d78f96cd18001f60df29e52c"), - Address("60d11b58744784dc97f878f7e3749c0f1381a004") + Address("4bb7e8ae99b645c2b7860b8f3a2328aae28bd80a"), // gav + Address("1baf27b88c48dd02b744999cf3522766929d2b2a"), // vitalik + Address("a8edb1ac2c86d3d9d78f96cd18001f60df29e52c"), // jeff + Address("60d11b58744784dc97f878f7e3749c0f1381a004") // christoph }; bool Client::isChainBad() const From 56ed8a920702169ad1a2e9e39acb29ea506e6dce Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 2 Jul 2015 13:48:39 +0200 Subject: [PATCH 097/290] Extra data. --- libethereum/Client.cpp | 2 +- libethereum/Client.h | 3 +++ libethereum/State.cpp | 3 ++- libethereum/State.h | 2 +- libwebthree/WebThree.cpp | 3 +++ 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 803fa7265..172a45983 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -803,7 +803,7 @@ void Client::rejigMining() { clog(ClientTrace) << "Rejigging mining..."; DEV_WRITE_GUARDED(x_working) - m_working.commitToMine(m_bc); + m_working.commitToMine(m_bc, m_extraData); DEV_READ_GUARDED(x_working) { DEV_WRITE_GUARDED(x_postMine) diff --git a/libethereum/Client.h b/libethereum/Client.h index 98ea253ce..8deeb3353 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -242,6 +242,8 @@ public: void setSentinel(std::string const& _server) { m_sentinel = _server; } /// Get the JSONRPC server to which we report bad blocks. std::string const& sentinel() const { return m_sentinel; } + /// Set the extra data that goes into mined blocks. + void setExtraData(bytes const& _extraData) { m_extraData = _extraData; } protected: /// InterfaceStub methods @@ -359,6 +361,7 @@ private: std::atomic m_syncBlockQueue = {false}; std::string m_sentinel; + bytes m_extraData; }; } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 19640b09e..3f9978569 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -883,7 +883,7 @@ LogBloom State::logBloom() const return ret; } -void State::commitToMine(BlockChain const& _bc) +void State::commitToMine(BlockChain const& _bc, bytes const& _extraData) { uncommitToMine(); @@ -966,6 +966,7 @@ void State::commitToMine(BlockChain const& _bc) m_currentBlock.gasUsed = gasUsed(); m_currentBlock.stateRoot = m_state.root(); m_currentBlock.parentHash = m_previousBlock.hash(); + m_currentBlock.extraData = _extraData; m_committedToMine = true; } diff --git a/libethereum/State.h b/libethereum/State.h index 6ad8fed09..6c54cedf7 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -194,7 +194,7 @@ public: /// The only thing left to do after this is to actually mine(). /// /// This may be called multiple times and without issue. - void commitToMine(BlockChain const& _bc); + void commitToMine(BlockChain const& _bc, bytes const& _extraData = {}); /// @returns true iff commitToMine() has been called without any subsequest transactions added &c. bool isCommittedToMine() const { return m_committedToMine; } diff --git a/libwebthree/WebThree.cpp b/libwebthree/WebThree.cpp index 513581841..3c1dea40f 100644 --- a/libwebthree/WebThree.cpp +++ b/libwebthree/WebThree.cpp @@ -51,7 +51,10 @@ WebThreeDirect::WebThreeDirect( if (_dbPath.size()) Defaults::setDBPath(_dbPath); if (_interfaces.count("eth")) + { m_ethereum.reset(new eth::Client(&m_net, _dbPath, _we, 0)); + m_ethereum->setExtraData(rlpList(0, _clientVersion, m_net.id())); + } if (_interfaces.count("shh")) m_whisper = m_net.registerCapability(new WhisperHost); From 784fed9a322c915c8e9f445fffdb41cb4ba27b18 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Thu, 2 Jul 2015 14:32:16 +0200 Subject: [PATCH 098/290] minor update --- libp2p/Session.cpp | 2 +- libwhisper/WhisperHost.cpp | 26 ++++++++++---------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp index 6a8c98071..08c411ca0 100644 --- a/libp2p/Session.cpp +++ b/libp2p/Session.cpp @@ -382,7 +382,7 @@ void Session::doRead() } catch (std::exception const& _e) { - clog(NetWarn) << _e.what() << "Exception decoding frame header RLP:" << bytesConstRef(m_data.data(), h128::size).cropped(3); + clog(NetWarn) << "Exception decoding frame header RLP:" << _e.what() << bytesConstRef(m_data.data(), h128::size).cropped(3); drop(BadProtocol); return; } diff --git a/libwhisper/WhisperHost.cpp b/libwhisper/WhisperHost.cpp index 9ee772ba5..f9ff33658 100644 --- a/libwhisper/WhisperHost.cpp +++ b/libwhisper/WhisperHost.cpp @@ -70,22 +70,16 @@ void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p) int rating = 1; // rating for local host is based upon: 1. installed watch; 2. proof of work - //if (bloomfilter.check) - //{ - // rating *= 10; - if (_p) // originated externally - DEV_GUARDED(m_filterLock) - { - for (auto const& f: m_filters) - if (f.second.filter.matches(_m)) - for (auto& i: m_watches) - if (i.second.id == f.first) - { - i.second.changes.push_back(h); - rating *= 10; - } - } - //} + if (_p) // incoming message from remote peer + DEV_GUARDED(m_filterLock) + for (auto const& f: m_filters) + if (f.second.filter.matches(_m)) + for (auto& i: m_watches) + if (i.second.id == f.first) + { + i.second.changes.push_back(h); + rating += 10; // subject to review + } // TODO p2p: capability-based rating for (auto i: peerSessions()) From e5d32849ddd934a5ed61ced4ac8b2b9dd40cf6f1 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 2 Jul 2015 15:17:20 +0200 Subject: [PATCH 099/290] add transactionQueue tests --- test/libethereum/transactionqueue.cpp | 58 +++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 test/libethereum/transactionqueue.cpp diff --git a/test/libethereum/transactionqueue.cpp b/test/libethereum/transactionqueue.cpp new file mode 100644 index 000000000..b7071d640 --- /dev/null +++ b/test/libethereum/transactionqueue.cpp @@ -0,0 +1,58 @@ +/* + 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 transaction.cpp + * @author Christoph Jentzsch + * @date 2015 + * Transaaction test functions. + */ + +#include +#include "../TestHelper.h" + +using namespace std; +using namespace dev; +using namespace dev::eth; + +BOOST_AUTO_TEST_SUITE(TransactionQueue) + +BOOST_AUTO_TEST_CASE(maxNonce) +{ + + dev::eth::TransactionQueue txq; + + // from a94f5374fce5edbc8e2a8697c15331677e6ebf0b + Transaction tx0(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 0, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); + Transaction tx0_1(1, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 0, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); + Transaction tx1(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 1, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); + Transaction tx2(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 2, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); + Transaction tx9(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 9, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); + + txq.import(tx0); + BOOST_CHECK_EQUAL(1, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + txq.import(tx0); + BOOST_CHECK_EQUAL(1, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + txq.import(tx0_1); + BOOST_CHECK_EQUAL(1, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + txq.import(tx1); + BOOST_CHECK_EQUAL(2, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + txq.import(tx9); + BOOST_CHECK_EQUAL(10, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + txq.import(tx2); + BOOST_CHECK_EQUAL(10, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); +} + +BOOST_AUTO_TEST_SUITE_END() From 7825c207583e82755ebc2444af05088462d18cf7 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 2 Jul 2015 15:38:45 +0200 Subject: [PATCH 100/290] Event and Watchers.qml --- mix/ClientModel.cpp | 42 ++++-- mix/ClientModel.h | 12 +- mix/qml.qrc | 2 + mix/qml/Block.qml | 234 +++++++++++++--------------------- mix/qml/BlockChain.qml | 51 ++++---- mix/qml/KeyValuePanel.qml | 106 ++++++++++++--- mix/qml/MainContent.qml | 2 +- mix/qml/ScenarioExecution.qml | 131 +++++++++++-------- mix/qml/ScenarioLoader.qml | 1 - mix/qml/StateListModel.qml | 4 +- mix/qml/Watchers.qml | 191 ++++++++++++++++++++++----- 11 files changed, 488 insertions(+), 288 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 931f53e20..89a836893 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -206,6 +206,21 @@ QVariantList ClientModel::gasCosts() const return res; } +void ClientModel::addAccount(QString const& _secret, QString const& _amount) +{ + KeyPair key(Secret(_secret.toStdString())); + m_accountsSecret.push_back(key); + Address address = key.address(); + m_accounts[address] = Account(u256(_amount.toStdString()), Account::NormalCreation); + m_ethAccounts->setAccounts(m_accountsSecret); +} + +QString ClientModel::resolveAddress(QString const& _secret) +{ + KeyPair key(Secret(_secret.toStdString())); + return "0x" + QString::fromStdString(key.address().hex()); +} + void ClientModel::setupScenario(QVariantMap _scenario) { onStateReset(); @@ -336,6 +351,7 @@ void ClientModel::executeSequence(vector const& _sequence) if (!transaction.isFunctionCall) { callAddress(Address(address.toStdString()), bytes(), transaction); + onNewTransaction(); continue; } @@ -674,7 +690,7 @@ RecordLogEntry* ClientModel::lastBlock() const strGas << blockInfo.gasUsed; stringstream strNumber; strNumber << blockInfo.number; - RecordLogEntry* record = new RecordLogEntry(0, QString::fromStdString(strNumber.str()), tr(" - Block - "), tr("Hash: ") + QString(QString::fromStdString(dev::toHex(blockInfo.hash().ref()))), QString(), QString(), QString(), false, RecordLogEntry::RecordType::Block, QString::fromStdString(strGas.str()), QString(), tr("Block"), QVariantMap(), QVariantList()); + RecordLogEntry* record = new RecordLogEntry(0, QString::fromStdString(strNumber.str()), tr(" - Block - "), tr("Hash: ") + QString(QString::fromStdString(dev::toHex(blockInfo.hash().ref()))), QString(), QString(), QString(), false, RecordLogEntry::RecordType::Block, QString::fromStdString(strGas.str()), QString(), tr("Block"), QVariantMap(), QVariantMap(), QVariantList()); QQmlEngine::setObjectOwnership(record, QQmlEngine::JavaScriptOwnership); return record; } @@ -735,6 +751,7 @@ void ClientModel::onNewTransaction() Address contractAddress = (bool)tr.address ? tr.address : tr.contractAddress; auto contractAddressIter = m_contractNames.find(contractAddress); QVariantMap inputParameters; + QVariantMap returnParameters; QVariantList logs; if (contractAddressIter != m_contractNames.end()) { @@ -754,6 +771,11 @@ void ClientModel::onNewTransaction() returned += "("; returned += returnValues.join(", "); returned += ")"; + + QStringList returnParams = encoder.decode(funcDef->returnParameters(), tr.result.output); + for (int k = 0; k < returnParams.length(); ++k) + returnParameters.insert(funcDef->returnParameters().at(k)->name(), returnParams.at(k)); + bytes data = tr.inputParameters; data.erase(data.begin(), data.begin() + 4); QStringList parameters = encoder.decode(funcDef->parametersList(), data); @@ -837,21 +859,25 @@ void ClientModel::onNewTransaction() } RecordLogEntry* log = new RecordLogEntry(recordIndex, transactionIndex, contract, function, value, address, returned, tr.isCall(), RecordLogEntry::RecordType::Transaction, - gasUsed, sender, label, inputParameters, logs); + gasUsed, sender, label, inputParameters, returnParameters, logs); QQmlEngine::setObjectOwnership(log, QQmlEngine::JavaScriptOwnership); emit newRecord(log); + + // retrieving all accounts balance + QVariantMap state; QVariantMap accountBalances; for (auto const& ctr : m_contractAddresses) { - u256 wei = m_client.balanceAt(ctr); - accountBalances.insert(ctr, wei); + u256 wei = m_client->balanceAt(ctr.second, PendingBlock); + accountBalances.insert("0x" + QString::fromStdString(ctr.second.hex()), QEther(wei, QEther::Wei).format()); } - for (auto const& account : m_account) + for (auto const& account : m_accounts) { - u256 wei = m_client.balanceAt(account); - accountBalances.insert(ctr, wei); + u256 wei = m_client->balanceAt(account.first, PendingBlock); + accountBalances.insert("0x" + QString::fromStdString(account.first.hex()), QEther(wei, QEther::Wei).format()); } - emit newState(recordIndex, accountBalances); + state.insert("accounts", accountBalances); + emit newState(recordIndex, state); } } diff --git a/mix/ClientModel.h b/mix/ClientModel.h index b63489ddf..e14c3c486 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -32,6 +32,7 @@ #include #include #include "MachineStates.h" +#include "QEther.h" namespace dev { @@ -115,6 +116,8 @@ class RecordLogEntry: public QObject Q_PROPERTY(QString label MEMBER m_label CONSTANT) /// input parameters Q_PROPERTY(QVariantMap parameters MEMBER m_inputParameters CONSTANT) + /// return parameters + Q_PROPERTY(QVariantMap returnParameters MEMBER m_returnParameters CONSTANT) /// logs Q_PROPERTY(QVariantList logs MEMBER m_logs CONSTANT) @@ -128,9 +131,9 @@ public: RecordLogEntry(): m_recordIndex(0), m_call(false), m_type(RecordType::Transaction) {} RecordLogEntry(unsigned _recordIndex, QString _transactionIndex, QString _contract, QString _function, QString _value, QString _address, QString _returned, bool _call, RecordType _type, QString _gasUsed, - QString _sender, QString _label, QVariantMap _inputParameters, QVariantList _logs): + QString _sender, QString _label, QVariantMap _inputParameters, QVariantMap _returnParameters, QVariantList _logs): m_recordIndex(_recordIndex), m_transactionIndex(_transactionIndex), m_contract(_contract), m_function(_function), m_value(_value), m_address(_address), m_returned(_returned), m_call(_call), m_type(_type), m_gasUsed(_gasUsed), - m_sender(_sender), m_label(_label), m_inputParameters(_inputParameters), m_logs(_logs) {} + m_sender(_sender), m_label(_label), m_inputParameters(_inputParameters), m_returnParameters(_returnParameters), m_logs(_logs) {} private: unsigned m_recordIndex; @@ -146,6 +149,7 @@ private: QString m_sender; QString m_label; QVariantMap m_inputParameters; + QVariantMap m_returnParameters; QVariantList m_logs; }; @@ -183,6 +187,10 @@ public: Q_INVOKABLE QString encodeStringParam(QString const& _param); /// To Hex number Q_INVOKABLE QString toHex(QString const& _int); + /// Add new account to the model + Q_INVOKABLE void addAccount(QString const& _secret, QString const& _amount); + /// Return the address associated with the current secret + Q_INVOKABLE QString resolveAddress(QString const& _secret); public slots: /// Setup scenario, run transaction sequence, show debugger for the last transaction diff --git a/mix/qml.qrc b/mix/qml.qrc index 16bb01b83..34295b022 100644 --- a/mix/qml.qrc +++ b/mix/qml.qrc @@ -69,5 +69,7 @@ qml/ScenarioExecution.qml qml/ScenarioLoader.qml qml/ScenarioButton.qml + qml/Watchers.qml + qml/KeyValuePanel.qml diff --git a/mix/qml/Block.qml b/mix/qml/Block.qml index 47edd8388..cb6737292 100644 --- a/mix/qml/Block.qml +++ b/mix/qml/Block.qml @@ -37,6 +37,13 @@ ColumnLayout return trHeight } + function editTx(txIndex) + { + transactionDialog.stateAccounts = scenario.accounts + transactionDialog.execute = false + transactionDialog.open(txIndex, blockIndex, transactions.get(txIndex)) + } + onOpenedTrChanged: { Layout.preferredHeight = calculateHeight() @@ -158,7 +165,7 @@ ColumnLayout anchors.top: parent.top anchors.left: parent.left anchors.leftMargin: -9 - anchors.topMargin: -9 + anchors.topMargin: -4 id: saveStatusImage source: "qrc:/qml/img/recyclediscard@2x.png" width: statusWidth + 20 @@ -195,177 +202,115 @@ ColumnLayout Rectangle { Layout.preferredWidth: blockWidth - Layout.preferredHeight: parent.height + Layout.preferredHeight: trHeight + height: trHeight color: "#DEDCDC" id: rowContentTr anchors.top: parent.top + property bool selected: false + Connections + { + target: blockChainPanel + onTxSelected: { + if (root.blockIndex !== blockIndex || index !== txIndex) + rowContentTr.deselect() + } + } + + function deselect() + { + rowContentTr.selected = false + rowContentTr.color = "#DEDCDC" + hash.color = labelColor + func.color = labelColor + } + MouseArea { anchors.fill: parent + onClicked: { + if (!rowContentTr.selected) + { + rowContentTr.selected = true + rowContentTr.color = "#4F4F4F" + hash.color = "#EAB920" + func.color = "#EAB920" + txSelected(index) + } + else + rowContentTr.deselect() + + } onDoubleClicked: { - /* - transactionDialog.stateAccounts = scenario.accounts - transactionDialog.execute = false - transactionDialog.open(index, blockIndex, transactions.get(index)) - */ - txSelected(index) + root.editTx(index) } } - ColumnLayout + RowLayout { - anchors.top: parent.top - width: parent.width - spacing: 20 - RowLayout + Layout.fillWidth: true + Layout.preferredHeight: trHeight - 10 + anchors.verticalCenter: parent.verticalCenter + Rectangle { - anchors.top: parent.top - Layout.fillWidth: true - Rectangle + Layout.preferredWidth: fromWidth + anchors.left: parent.left + anchors.leftMargin: horizontalMargin + Text { - Layout.preferredWidth: fromWidth - anchors.left: parent.left - anchors.leftMargin: horizontalMargin - Text - { - id: hash - width: parent.width - 30 - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter - maximumLineCount: 1 - color: labelColor - font.pointSize: dbgStyle.absoluteSize(1) - font.bold: true - text: { - if (index >= 0) - return transactions.get(index).sender - else - return "" - } - } - } - - Rectangle - { - Layout.preferredWidth: toWidth - Text - { - id: func - text: { - if (index >= 0) - parent.parent.userFrienldyToken(transactions.get(index).label) - else - return "" - } - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter - color: labelColor - font.pointSize: dbgStyle.absoluteSize(1) - font.bold: true - maximumLineCount: 1 - width: parent.width - } - } - - function userFrienldyToken(value) - { - if (value && value.indexOf("<") === 0) - { - if (value.split("> ")[1] === " - ") - return value.split(" - ")[0].replace("<", "") + id: hash + width: parent.width - 30 + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + maximumLineCount: 1 + color: labelColor + font.pointSize: dbgStyle.absoluteSize(1) + font.bold: true + text: { + if (index >= 0) + return clientModel.resolveAddress(transactions.get(index).sender) else - return value.split(" - ")[0].replace("<", "") + "." + value.split("> ")[1] + "()"; - } - else - return value - } - - Rectangle - { - Layout.preferredWidth: valueWidth - Text - { - id: returnValue - elide: Text.ElideRight - anchors.verticalCenter: parent.verticalCenter - maximumLineCount: 1 - color: labelColor - font.bold: true - font.pointSize: dbgStyle.absoluteSize(1) - width: parent.width - 30 - text: { - if (index >= 0 && transactions.get(index).returned) - return transactions.get(index).returned - else - return "" - } + return "" } } + } - Rectangle + Rectangle + { + Layout.preferredWidth: toWidth + Text { - Layout.preferredWidth: logsWidth - Layout.preferredHeight: trHeight - 10 - width: logsWidth - color: "transparent" - Text - { - id: logs - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: 10 - color: labelColor - font.bold: true - font.pointSize: dbgStyle.absoluteSize(1) - text: { - if (index >= 0 && transactions.get(index).logs && transactions.get(index).logs.count) - return transactions.get(index).logs.count - else - return "" - } - } - MouseArea { - anchors.fill: parent - onClicked: { - rowTransaction.displayContent(); - } + id: func + text: { + if (index >= 0) + parent.parent.userFrienldyToken(transactions.get(index).label) + else + return "" } + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + color: labelColor + font.pointSize: dbgStyle.absoluteSize(1) + font.bold: true + maximumLineCount: 1 + width: parent.width } } - RowLayout + function userFrienldyToken(value) { - id: rowDetailedContent - visible: false - Layout.preferredHeight:{ - if (index >= 0 && transactions.get(index).logs) - return 100 * transactions.get(index).logs.count - else - return 100 - } - onVisibleChanged: + if (value && value.indexOf("<") === 0) { - var lognb = transactions.get(index).logs.count - if (visible) - { - rowContentTr.Layout.preferredHeight = trHeight + 100 * lognb - openedTr += 100 * lognb - } + if (value.split("> ")[1] === " - ") + return value.split(" - ")[0].replace("<", "") else - { - rowContentTr.Layout.preferredHeight = trHeight - openedTr -= 100 * lognb - } - } - - Text { - anchors.left: parent.left - anchors.leftMargin: horizontalMargin - id: logsText + return value.split(" - ")[0].replace("<", "") + "." + value.split("> ")[1] + "()"; } - } + else + return value + } } } @@ -374,7 +319,6 @@ ColumnLayout width: debugActionWidth height: trHeight anchors.left: rowContentTr.right - anchors.topMargin: -6 anchors.top: rowContentTr.top anchors.leftMargin: -50 color: "transparent" diff --git a/mix/qml/BlockChain.qml b/mix/qml/BlockChain.qml index 840bff766..ca7b60ce7 100644 --- a/mix/qml/BlockChain.qml +++ b/mix/qml/BlockChain.qml @@ -13,14 +13,17 @@ import "." ColumnLayout { id: blockChainPanel + property alias trDialog: transactionDialog + property alias blockChainRepeater: blockChainRepeater property variant model - property var states: {} + property var states: ({}) spacing: 0 property int previousWidth property variant debugTrRequested: [] signal chainChanged signal chainReloaded signal txSelected(var blockIndex, var txIndex) + signal rebuilding Connections { @@ -42,21 +45,21 @@ ColumnLayout { var minWidth = scenarioMinWidth - 20 // margin if (width <= minWidth || previousWidth <= minWidth) { - fromWidth = 100 - toWidth = 100 - valueWidth = 200 + fromWidth = 250 + toWidth = 240 + //valueWidth = 200 } else { var diff = (width - previousWidth) / 3; - fromWidth = fromWidth + diff < 100 ? 100 : fromWidth + diff - toWidth = toWidth + diff < 100 ? 100 : toWidth + diff - valueWidth = valueWidth + diff < 200 ? 200 : valueWidth + diff + fromWidth = fromWidth + diff < 250 ? 250 : fromWidth + diff + toWidth = toWidth + diff < 240 ? 240 : toWidth + diff + //valueWidth = valueWidth + diff < 200 ? 200 : valueWidth + diff } previousWidth = width } - function state(record) + function getState(record) { return states[record] } @@ -76,10 +79,8 @@ ColumnLayout { } property int statusWidth: 30 - property int fromWidth: 150 - property int toWidth: 100 - property int valueWidth: 200 - property int logsWidth: 40 + property int fromWidth: 250 + property int toWidth: 240 property int debugActionWidth: 40 property int horizontalMargin: 10 property int cellSpacing: 10 @@ -120,16 +121,6 @@ ColumnLayout { Layout.preferredWidth: toWidth + cellSpacing } Label - { - text: "Value" - Layout.preferredWidth: valueWidth + cellSpacing - } - Label - { - text: "Logs" - Layout.preferredWidth: logsWidth + cellSpacing - } - Label { text: "" Layout.preferredWidth: debugActionWidth @@ -170,13 +161,19 @@ ColumnLayout { { id: blockChainRepeater model: blockModel + + function editTx(blockIndex, txIndex) + { + itemAt(blockIndex).editTx(txIndex) + } + Block { Connections { target: block onTxSelected: { - txSelected(index, txIndex) + blockChainPanel.txSelected(index, txIndex) } } id: block @@ -264,6 +261,8 @@ ColumnLayout { Rectangle { Layout.preferredWidth: parent.width + Layout.preferredHeight: 70 + color: "transparent" RowLayout { anchors.horizontalCenter: parent.horizontalCenter @@ -286,6 +285,7 @@ ColumnLayout { { if (ensureNotFuturetime.running) return; + rebuilding() stopBlinking() states = [] var retBlocks = []; @@ -333,7 +333,7 @@ ColumnLayout { blockModel.append(model.blocks[j]) ensureNotFuturetime.start() - clientModel.setupScenario(model); + clientModel.setupScenario(model); } buttonShortcut: "" sourceImg: "qrc:/qml/img/recycleicon@2x.png" @@ -465,11 +465,13 @@ ColumnLayout { tr.recordIndex = _r.recordIndex tr.logs = _r.logs tr.sender = _r.sender + tr.returnParameters = _r.returnParameters var trModel = blockModel.getTransaction(blockIndex, trIndex) trModel.returned = _r.returned trModel.recordIndex = _r.recordIndex trModel.logs = _r.logs trModel.sender = _r.sender + trModel.returnParameters = _r.returnParameters blockModel.setTransaction(blockIndex, trIndex, trModel) return; } @@ -489,6 +491,7 @@ ColumnLayout { itemTr.sender = _r.sender itemTr.recordIndex = _r.recordIndex itemTr.logs = _r.logs + itemTr.returnParameters = _r.returnParameters model.blocks[model.blocks.length - 1].transactions.push(itemTr) blockModel.appendTransaction(itemTr) } diff --git a/mix/qml/KeyValuePanel.qml b/mix/qml/KeyValuePanel.qml index cf16a42aa..63baa3801 100644 --- a/mix/qml/KeyValuePanel.qml +++ b/mix/qml/KeyValuePanel.qml @@ -14,48 +14,112 @@ import "." ColumnLayout { id: root property alias title: titleLabel.text - property variant data + property variant _data + property string role + property alias model: modelKeyValue - function key(index) + function clear() { + modelKeyValue.clear() } - function value(index) + function init() { + modelKeyValue.clear() + if (typeof(computeData) !== "undefined" && computeData instanceof Function) + computeData() + else + { + console.log("--------------") + console.log(JSON.stringify(_data)) + console.log(role) + if (_data !== undefined && _data[role] !== undefined) + { + var keys = Object.keys(_data[role]) + for (var k in keys) + { + modelKeyValue.append({ "key": keys[k] === "" ? "undefined" : keys[k], "value": _data[role][keys[k]] }) + } + } + } } RowLayout { + Layout.preferredHeight: 20 + Layout.fillWidth: true Label { id: titleLabel + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + color: "white" } } RowLayout { - Repeater + Layout.fillWidth: true + Layout.preferredHeight: 100 + ListModel { - id: repeaterKeyValue - RowLayout + id: modelKeyValue + } + + Rectangle + { + Layout.fillWidth: true + Layout.fillHeight: true + color: "white" + radius: 2 + ScrollView { - Rectangle + id: columnValues + horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff + anchors.fill: parent + ColumnLayout { - id: key - Label + anchors.margins: 10 + Repeater { - text: { - return root.key(index) - } - } - } - Rectangle - { - id: value - Label - { - text: { - return root.value(index) + id: repeaterKeyValue + model: modelKeyValue + RowLayout + { + Layout.fillWidth: true + Layout.preferredHeight: 30 + spacing: 0 + Rectangle + { + Layout.preferredWidth: columnValues.width / 2 + Label + { + anchors.left: parent.left + anchors.leftMargin: 10 + text: { + if (index >= 0) + return repeaterKeyValue.model.get(index).key + else + return "" + } + } + } + + Rectangle + { + Layout.preferredWidth: columnValues.width / 2 - 10 + Label + { + anchors.right: parent.right + anchors.rightMargin: 10 + text: { + if (index >= 0) + return repeaterKeyValue.model.get(index).value + else + return "" + } + } + } } } } diff --git a/mix/qml/MainContent.qml b/mix/qml/MainContent.qml index 7f180a899..376135695 100644 --- a/mix/qml/MainContent.qml +++ b/mix/qml/MainContent.qml @@ -31,7 +31,7 @@ Rectangle { property alias codeEditor: codeEditor property bool webViewHorizontal: codeWebSplitter.orientation === Qt.Vertical //vertical splitter positions elements vertically, splits screen horizontally property bool firstCompile: true - property int scenarioMinWidth: 590 + property int scenarioMinWidth: 620 Connections { target: codeModel diff --git a/mix/qml/ScenarioExecution.qml b/mix/qml/ScenarioExecution.qml index 65e4d5d94..1eb0c3d0c 100644 --- a/mix/qml/ScenarioExecution.qml +++ b/mix/qml/ScenarioExecution.qml @@ -8,6 +8,7 @@ import "js/Debugger.js" as Debugger import "js/ErrorLocationFormater.js" as ErrorLocationFormater import "." + Rectangle { color: "#ededed" property alias bc: blockChain @@ -20,70 +21,94 @@ Rectangle { } } - Column + ScrollView { - id: scenarioColumn - anchors.margins: 10 anchors.fill: parent - spacing: 10 - ScenarioLoader - { - height: 100 - width: parent.width - id: loader + onWidthChanged: { + columnExe.width = width - 40 } - Connections + ColumnLayout { - target: blockChain - onChainChanged: - { - loader.needSaveOrReload() - } - } + id: columnExe + Layout.preferredWidth: parent.width + width: parent.width - 40 + anchors.left: parent.left + anchors.leftMargin: 15 + ColumnLayout + { + id: scenarioColumn + width: parent.width + spacing: 10 + ScenarioLoader + { + anchors.horizontalCenter: parent.horizontalCenter + height: 100 + Layout.preferredWidth: 400 + width: 400 + id: loader + } - Rectangle - { - width: parent.parent.width - height: 1 - color: "#cccccc" - } + Connections + { + target: blockChain + onChainChanged: + { + loader.needSaveOrReload() + } + } - Connections - { - target: loader - onLoaded: - { - blockChain.load(scenario) - } - } + Rectangle + { + Layout.preferredWidth: parent.width + height: 1 + color: "#cccccc" + } - BlockChain - { - id: blockChain - width: parent.width - } + Connections + { + target: loader + onLoaded: + { + watchers.clear() + blockChain.load(scenario) + } + } - Connections - { - target: blockChain - onTxSelected:{ - var tx = model.block[blockIndex].transactions[txIndex] - var state = blockChain.getState(tx.recordIndex) - watchers.updateWidthTx(tx, state) + BlockChain + { + id: blockChain + width: parent.width + } + + Connections + { + target: blockChain + onTxSelected: { + var tx = blockChain.model.blocks[blockIndex].transactions[txIndex] + var state = blockChain.getState(tx.recordIndex) + watchers.updateWidthTx(tx, state, blockIndex, txIndex) + } + onRebuilding: { + watchers.clear() + } + } } - } - } - ScrollView - { - anchors.top: scenarioColumn.bottom - width: parent.width - height: 500 - Watchers - { - id: watchers - anchors.topMargin: 10 + Watchers + { + id: watchers + bc: blockChain + Layout.fillWidth: true + Layout.preferredHeight: 740 + } + + Rectangle + { + color: "transparent" + Layout.preferredHeight: 50 + Layout.fillWidth: true + } } } } diff --git a/mix/qml/ScenarioLoader.qml b/mix/qml/ScenarioLoader.qml index bc26b103d..accdc324a 100644 --- a/mix/qml/ScenarioLoader.qml +++ b/mix/qml/ScenarioLoader.qml @@ -126,7 +126,6 @@ ColumnLayout scenarioNameEdit.save() else scenarioNameEdit.edit() - } } } diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index 992113cc6..a5e6365e0 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -257,7 +257,9 @@ Item { _secret = clientModel.newSecret(); var address = clientModel.address(_secret); var name = qsTr("Account") + "-" + address.substring(0, 4); - return { name: name, secret: _secret, balance: QEtherHelper.createEther(_balance, _unit), address: address }; + var amount = QEtherHelper.createEther(_balance, _unit) + clientModel.addAccount(_secret, amount.toWei().value()) + return { name: name, secret: _secret, balance: amount, address: address }; } function duplicateState(index) diff --git a/mix/qml/Watchers.qml b/mix/qml/Watchers.qml index 5cdc65846..2e436a634 100644 --- a/mix/qml/Watchers.qml +++ b/mix/qml/Watchers.qml @@ -11,49 +11,176 @@ import "js/TransactionHelper.js" as TransactionHelper import "js/QEtherHelper.js" as QEtherHelper import "." -ColumnLayout { - +Rectangle { + color: "#4F4F4F" + radius: 4 property variant tx - property variant state + property variant currentState + property variant bc + property var blockIndex + property var txIndex - function updateWidthTx(_tx, _state) + function clear() { - console.log("update tx") - console.log(JSON.stringify(tx)) - console.log(JSON.stringify(state)) - txLabel.text = tx.label - tx = _tx - state = _state + from.text = "" + to.text = "" + inputParams.clear() + returnParams.clear() + accounts.clear() + events.clear() } - RowLayout + function updateWidthTx(_tx, _state, _blockIndex, _txIndex) { - Label { - id: txLabel + from.text = _tx.sender + to.text = _tx.label + tx = _tx + blockIndex = _blockIndex + txIndex = _txIndex + currentState = _state + inputParams.init() + if (_tx.isContractCreation) + { + returnParams.role = "creationAddr" + returnParams._data = { + creationAddr : { + "": _tx.returned + } + } } + else + { + returnParams.role = "returnParameters" + returnParams._data = tx + } + returnParams.init() + accounts.init() + events.init() } - KeyValuePanel - { - id: inputParams - title: qsTr("INPUT PARAMETERS") - } + Column { + anchors.fill: parent + spacing: 15 + Rectangle + { + height: 20 + width: parent.width - 30 + color: "transparent" + Row + { + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + height: 5 + spacing: 5 + Label { + id: fromLabel + text: qsTr("from") + visible: from.text !== "" + color: "#EAB920" + } + Label { + id: from + color: "#EAB920" + elide: Text.ElideRight + maximumLineCount: 1 + clip: true + width: 200 + } + Label { + id: toLabel + text: qsTr("to") + visible: from.text !== "" + color: "#EAB920" + } + Label { + id: to + color: "#EAB920" + elide: Text.ElideRight + maximumLineCount: 1 + clip: true + width: 100 + } - KeyValuePanel - { - id: returnParams - title: qsTr("RETURN PARAMETERS") - } + Image { + source: "qrc:/qml/img/edit.png" + height: 15 + fillMode: Image.PreserveAspectFit + visible: from.text !== "" + MouseArea + { + anchors.fill: parent + onClicked: + { + bc.blockChainRepeater.editTx(blockIndex, txIndex) + } + } + } + } + } - KeyValuePanel - { - id: balance - title: qsTr("BALANCES") - } + Rectangle { + height: 1 + width: parent.width - 30 + anchors.horizontalCenter: parent.horizontalCenter + border.color: "#cccccc" + border.width: 1 + } - KeyValuePanel - { - id: events - title: qsTr("EVENTS") + KeyValuePanel + { + height: 150 + width: parent.width - 30 + anchors.horizontalCenter: parent.horizontalCenter + id: inputParams + title: qsTr("INPUT PARAMETERS") + role: "parameters" + _data: tx + } + + KeyValuePanel + { + height: 150 + width: parent.width - 30 + anchors.horizontalCenter: parent.horizontalCenter + id: returnParams + title: qsTr("RETURN PARAMETERS") + role: "returnParameters" + _data: tx + } + + KeyValuePanel + { + height: 150 + width: parent.width - 30 + anchors.horizontalCenter: parent.horizontalCenter + id: accounts + title: qsTr("ACCOUNTS") + role: "accounts" + _data: currentState + } + + KeyValuePanel + { + height: 150 + width: parent.width - 30 + anchors.horizontalCenter: parent.horizontalCenter + id: events + title: qsTr("EVENTS") + function computeData() + { + model.clear() + var ret = [] + for (var k in tx.logs) + { + var param = "" + for (var p in tx.logs[k].param) + { + param += " " + tx.logs[k].param[p].value + " " + } + param = "(" + param + ")" + model.append({ "key": tx.logs[k].name, "value": param }) + } + } + } } } From 9cea8c669ee2c99f5b98a606a00660735831636d Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 2 Jul 2015 16:17:33 +0200 Subject: [PATCH 101/290] keep the chain on syncer aborting during blocks downloading --- libethereum/BlockChainSync.cpp | 83 +++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 22 deletions(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 30dbf2964..647ebb4aa 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -76,15 +76,18 @@ void BlockChainSync::onPeerStatus(std::shared_ptr _peer) { RecursiveGuard l(x_sync); DEV_INVARIANT_CHECK; + std::shared_ptr session = _peer->session(); + if (!session) + return; // Expired if (_peer->m_genesisHash != host().chain().genesisHash()) _peer->disable("Invalid genesis hash"); else if (_peer->m_protocolVersion != host().protocolVersion() && _peer->m_protocolVersion != EthereumHost::c_oldProtocolVersion) _peer->disable("Invalid protocol version."); else if (_peer->m_networkId != host().networkId()) _peer->disable("Invalid network identifier."); - else if (_peer->session()->info().clientVersion.find("/v0.7.0/") != string::npos) + else if (session->info().clientVersion.find("/v0.7.0/") != string::npos) _peer->disable("Blacklisted client version."); - else if (host().isBanned(_peer->session()->id())) + else if (host().isBanned(session->id())) _peer->disable("Peer banned for previous bad behaviour."); else { @@ -345,26 +348,30 @@ void PV60Sync::restartSync() { resetSync(); host().bq().clear(); - if (isSyncing()) - transition(m_syncer.lock(), SyncState::Idle); + std::shared_ptr syncer = m_syncer.lock(); + if (syncer) + transition(syncer, SyncState::Idle); } void PV60Sync::completeSync() { - if (isSyncing()) - transition(m_syncer.lock(), SyncState::Idle); + std::shared_ptr syncer = m_syncer.lock(); + if (syncer) + transition(syncer, SyncState::Idle); } void PV60Sync::pauseSync() { - if (isSyncing()) - setState(m_syncer.lock(), SyncState::Waiting, true); + std::shared_ptr syncer = m_syncer.lock(); + if (syncer) + transition(syncer, SyncState::Waiting, true); } void PV60Sync::continueSync() { - if (isSyncing()) - transition(m_syncer.lock(), SyncState::Blocks); + std::shared_ptr syncer = m_syncer.lock(); + if (syncer) + transition(syncer, SyncState::Blocks); } void PV60Sync::onNewPeer(std::shared_ptr _peer) @@ -485,7 +492,9 @@ void PV60Sync::setNeedsSyncing(std::shared_ptr _peer, h256 const& if (_peer->m_latestHash) noteNeedsSyncing(_peer); - _peer->session()->addNote("sync", string(isSyncing(_peer) ? "ongoing" : "holding") + (needsSyncing(_peer) ? " & needed" : "")); + shared_ptr session = _peer->session(); + if (session) + session->addNote("sync", string(isSyncing(_peer) ? "ongoing" : "holding") + (needsSyncing(_peer) ? " & needed" : "")); } bool PV60Sync::needsSyncing(std::shared_ptr _peer) const @@ -778,7 +787,33 @@ void PV60Sync::onPeerNewHashes(std::shared_ptr _peer, h256s const& void PV60Sync::abortSync() { // Can't check invariants here since the peers is already removed from the list and the state is not updated yet. - setState(std::shared_ptr(), SyncState::Idle, false, true); + bool continueSync = false; + if (m_state == SyncState::Blocks) + { + // Main syncer aborted, try to find a replacement + host().foreachPeer([&](std::shared_ptr _p) + { + if (_p->m_asking == Asking::Blocks) + { + setState(_p, SyncState::Blocks, true, true); // will kick off other peers to help if available. + continueSync = true; + return false; + } + if (_p->m_asking == Asking::Nothing && shouldGrabBlocks(_p)) + { + transition(_p, SyncState::Blocks); + clog(NetMessageDetail) << "New sync peer selected"; + continueSync = true; + return false; + } + return true; + }); + } + if (!continueSync) + { + // Just set to idle. Hashchain is keept, Sync will be continued if there are more peers to sync with + setState(std::shared_ptr(), SyncState::Idle, false, true); + } DEV_INVARIANT_CHECK; } @@ -957,7 +992,7 @@ void PV61Sync::onPeerHashes(std::shared_ptr _peer, h256s const& _h { auto syncPeer = m_chainSyncPeers.find(_peer); if (syncPeer == m_chainSyncPeers.end()) - clog(NetWarn) << "Hashes response from unexpected peer"; + clog(NetMessageDetail) << "Hashes response from unexpected peer"; else { // Peer does not have request hashes, move back from downloading to ready @@ -1013,8 +1048,16 @@ void PV61Sync::onPeerHashes(std::shared_ptr _peer, h256s const& _h else if (status == QueueStatus::Bad) { cwarn << "block hash bad!" << h << ". Bailing..."; - _peer->disable("Bad blocks"); - restartSync(); + _peer->disable("Bad hashes"); + if (isSyncing(_peer)) + restartSync(); + else + { + //try with other peer + m_readyChainMap[number] = move(m_downloadingChainMap.at(number)); + m_downloadingChainMap.erase(number); + m_chainSyncPeers.erase(_peer); + } return; } else if (status == QueueStatus::Unknown) @@ -1053,13 +1096,9 @@ void PV61Sync::onPeerAborting() else ++s; } - if (m_syncer.expired() && m_state != SyncState::Idle) - { - clog(NetWarn) << "Syncing peer disconnected, restarting sync"; - m_syncer.reset(); - abortSync(); - } - else if (isPV61Syncing()) + if (m_syncer.expired()) + PV60Sync::onPeerAborting(); + else if (isPV61Syncing() && m_state == SyncState::Hashes) requestSubchains(); DEV_INVARIANT_CHECK; } From fdc40a05bf80e3225149cd89d1e6b727cfe317ea Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 2 Jul 2015 17:29:01 +0200 Subject: [PATCH 102/290] BlockQueue::import() spams only under specific verbosity I am getting the thread id even with verbosity = 0 which can make it really difficult to debug anything else if I am not interested in said thread's ID --- libethereum/BlockQueue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index e5ff5fa8d..3a5138ca3 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -184,7 +184,7 @@ void BlockQueue::drainVerified_WITH_BOTH_LOCKS() ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, bool _isOurs) { - cdebug << std::this_thread::get_id(); + clog(BlockQueueTraceChannel) << std::this_thread::get_id(); // Check if we already know this block. h256 h = BlockInfo::headerHash(_block); From 4039227faa108a385af949a0a3867c89811dca81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 2 Jul 2015 17:48:32 +0200 Subject: [PATCH 103/290] Extend JIT interface to allow only compilation of EVM code. Make code availability checking thread-safe. --- evmjit/include/evmjit/JIT.h | 3 +++ evmjit/libevmjit/JIT.cpp | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/evmjit/include/evmjit/JIT.h b/evmjit/include/evmjit/JIT.h index 8d6f9bbd0..901c351d9 100644 --- a/evmjit/include/evmjit/JIT.h +++ b/evmjit/include/evmjit/JIT.h @@ -153,6 +153,9 @@ public: /// \param _codeHash The Keccak hash of the EVM code. EXPORT static bool isCodeReady(h256 const& _codeHash); + /// Compile the given EVM code to machine code and make available for execution. + EXPORT static void compile(byte const* _code, uint64_t _codeSize, h256 const& _codeHash); + EXPORT static ReturnCode exec(ExecutionContext& _context); }; diff --git a/evmjit/libevmjit/JIT.cpp b/evmjit/libevmjit/JIT.cpp index 89d2e63eb..53c36dcb2 100644 --- a/evmjit/libevmjit/JIT.cpp +++ b/evmjit/libevmjit/JIT.cpp @@ -1,6 +1,7 @@ #include "evmjit/JIT.h" #include +#include #include "preprocessor/llvm_includes_start.h" #include @@ -82,6 +83,7 @@ void parseOptions() class JITImpl { std::unique_ptr m_engine; + mutable std::mutex x_codeMap; std::unordered_map m_codeMap; public: @@ -136,6 +138,7 @@ JITImpl::JITImpl() ExecFunc JITImpl::getExecFunc(h256 const& _codeHash) const { + std::lock_guard lock{x_codeMap}; auto it = m_codeMap.find(_codeHash); if (it != m_codeMap.end()) return it->second; @@ -144,6 +147,7 @@ ExecFunc JITImpl::getExecFunc(h256 const& _codeHash) const void JITImpl::mapExecFunc(h256 _codeHash, ExecFunc _funcAddr) { + std::lock_guard lock{x_codeMap}; m_codeMap.emplace(std::move(_codeHash), _funcAddr); } @@ -181,6 +185,14 @@ bool JIT::isCodeReady(h256 const& _codeHash) return JITImpl::instance().getExecFunc(_codeHash) != nullptr; } +void JIT::compile(byte const* _code, uint64_t _codeSize, h256 const& _codeHash) +{ + auto& jit = JITImpl::instance(); + auto execFunc = jit.compile(_code, _codeSize, _codeHash); + if (execFunc) // FIXME: What with error? + jit.mapExecFunc(_codeHash, execFunc); +} + ReturnCode JIT::exec(ExecutionContext& _context) { //std::unique_ptr listener{new ExecStats}; From 1b8fc18377dc959a3cb069bec1fb4cebe9955e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 2 Jul 2015 17:49:13 +0200 Subject: [PATCH 104/290] New strategy do SmartVM: JIT worker in the background. --- libevm/SmartVM.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 7 deletions(-) diff --git a/libevm/SmartVM.cpp b/libevm/SmartVM.cpp index f8785b6df..3fb5be8c5 100644 --- a/libevm/SmartVM.cpp +++ b/libevm/SmartVM.cpp @@ -20,6 +20,10 @@ #include "SmartVM.h" #include +#include +#include +#include +#include #include #include #include @@ -32,6 +36,8 @@ namespace eth { namespace { + struct JitInfo: LogChannel { static const char* name() { return "JIT"; }; static const int verbosity = 0; }; + using HitMap = std::unordered_map; HitMap& getHitMap() @@ -39,30 +45,97 @@ namespace static HitMap s_hitMap; return s_hitMap; } + + struct JitTask + { + bytes code; + h256 codeHash; + }; + + class JitWorker + { + bool m_finished = false; + std::mutex x_mutex; + std::condition_variable m_cv; + std::thread m_worker; + std::queue m_queue; + + bool pop(JitTask& o_task) + { + std::unique_lock lock{x_mutex}; + m_cv.wait(lock, [this]{ return m_finished || !m_queue.empty(); }); + if (m_finished) + return false; + + assert(!m_queue.empty()); + o_task = std::move(m_queue.front()); + m_queue.pop(); + return true; + } + + void work() + { + clog(JitInfo) << "JIT worker started."; + JitTask task; + while (pop(task)) + { + clog(JitInfo) << "Compilation... " << task.codeHash; + evmjit::JIT::compile(task.code.data(), task.code.size(), eth2jit(task.codeHash)); + clog(JitInfo) << " ...finished " << task.codeHash; + } + clog(JitInfo) << "JIT worker finished."; + } + + public: + JitWorker() noexcept: m_worker([this]{ work(); }) + {} + + ~JitWorker() + { + { + std::lock_guard lock{x_mutex}; + m_finished = true; + } + m_cv.notify_one(); + m_worker.join(); + } + + void push(JitTask&& _task) + { + { + std::lock_guard lock(x_mutex); + m_queue.push(std::move(_task)); + } + m_cv.notify_one(); + } + }; } bytesConstRef SmartVM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp) { - auto codeHash = sha3(_ext.code); + auto codeHash = _ext.codeHash; auto vmKind = VMKind::Interpreter; // default VM // Jitted EVM code already in memory? - if (evmjit::JIT::isCodeReady(eth2jit(codeHash))) + if (evmjit::JIT::isCodeReady(eth2jit(codeHash))) // FIXME: JIT::isCodeReady is not thread-safe { - cnote << "Jitted"; + clog(JitInfo) << "JIT: " << codeHash; vmKind = VMKind::JIT; } else { + static JitWorker s_worker; + // Check EVM code hit count - static const uint64_t c_hitTreshold = 1; + static const uint64_t c_hitTreshold = 2; auto& hits = getHitMap()[codeHash]; ++hits; - if (hits > c_hitTreshold) + if (hits == c_hitTreshold) { - cnote << "JIT selected"; - vmKind = VMKind::JIT; + clog(JitInfo) << "Schedule: " << codeHash; + s_worker.push({_ext.code, codeHash}); } + clog(JitInfo) << "Interpreter: " << codeHash; } // TODO: Selected VM must be kept only because it returns reference to its internal memory. From de121cddcf13580511f9fe6d47d55fcd45f281e5 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 2 Jul 2015 18:02:35 +0200 Subject: [PATCH 105/290] download hashes from multiple peers when starving --- libethereum/BlockChainSync.cpp | 56 ++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 82a06b3b2..97684efb1 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -902,14 +902,23 @@ void PV61Sync::requestSubchain(std::shared_ptr _peer) h256s& d = m_downloadingChainMap.at(syncPeer->second); _peer->requestHashes(d.back()); } - else if (needsSyncing(_peer) && !m_readyChainMap.empty()) + else if (needsSyncing(_peer)) { - clog(NetAllDetail) << "Helping with hashchin download"; - h256s& d = m_readyChainMap.begin()->second; - _peer->requestHashes(d.back()); - m_downloadingChainMap[m_readyChainMap.begin()->first] = move(d); - m_chainSyncPeers[_peer] = m_readyChainMap.begin()->first; - m_readyChainMap.erase(m_readyChainMap.begin()); + if (!m_readyChainMap.empty()) + { + clog(NetAllDetail) << "Helping with hashchin download"; + h256s& d = m_readyChainMap.begin()->second; + _peer->requestHashes(d.back()); + m_downloadingChainMap[m_readyChainMap.begin()->first] = move(d); + m_chainSyncPeers[_peer] = m_readyChainMap.begin()->first; + m_readyChainMap.erase(m_readyChainMap.begin()); + } + else if (!m_downloadingChainMap.empty() && !m_completeChainMap.empty()) + { + // Lead syncer is done, just grab whatever we can + h256s& d = m_downloadingChainMap.begin()->second; + _peer->requestHashes(d.back()); + } } } @@ -1016,12 +1025,24 @@ void PV61Sync::onPeerHashes(std::shared_ptr _peer, h256s const& _h else { auto syncPeer = m_chainSyncPeers.find(_peer); + unsigned number = 0; if (syncPeer == m_chainSyncPeers.end()) { - clog(NetWarn) << "Hashes response from unexpected peer"; + //check downlading peers + for (auto const& downloader: m_downloadingChainMap) + if (downloader.second.back() == _peer->m_syncHash) + { + number = downloader.first; + break; + } + } + else + number = syncPeer->second; + if (number == 0) + { + clog(NetAllDetail) << "Hashes response from unexpected/expired peer"; return; } - unsigned number = syncPeer->second; h256s& hashes = m_downloadingChainMap.at(number); unsigned knowns = 0; @@ -1089,7 +1110,22 @@ void PV61Sync::onPeerAborting() ++s; } if (m_syncer.expired()) - PV60Sync::onPeerAborting(); + { + if (m_state == SyncState::Hashes) + { + // Main syncer aborted, other peers are probably still downloading hashes, just set one of them as syncer + host().foreachPeer([&](std::shared_ptr _p) + { + if (_p->m_asking != Asking::Hashes) + return true; + setState(_p, SyncState::Hashes, true, true); + return false; + }); + } + + if (m_syncer.expired()) + PV60Sync::onPeerAborting(); + } else if (isPV61Syncing() && m_state == SyncState::Hashes) requestSubchains(); DEV_INVARIANT_CHECK; From 5a94ff0f978d4b6592aa56ce637d5f86794641e4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 2 Jul 2015 15:55:08 +0200 Subject: [PATCH 106/290] Use size_t for RLP and decode length more carefully. --- libdevcore/RLP.cpp | 75 +++++++++++++++++++++++-------------- libdevcore/RLP.h | 61 ++++++++++++++++-------------- libethereum/Transaction.cpp | 2 +- 3 files changed, 79 insertions(+), 59 deletions(-) diff --git a/libdevcore/RLP.cpp b/libdevcore/RLP.cpp index 92d97aec4..cf4218050 100644 --- a/libdevcore/RLP.cpp +++ b/libdevcore/RLP.cpp @@ -49,12 +49,12 @@ RLP::iterator& RLP::iterator::operator++() { if (m_remaining) { - m_lastItem.retarget(m_lastItem.next().data(), m_remaining); - m_lastItem = m_lastItem.cropped(0, RLP(m_lastItem, ThrowOnFail | FailIfTooSmall).actualSize()); - m_remaining -= std::min(m_remaining, m_lastItem.size()); + m_currentItem.retarget(m_currentItem.next().data(), m_remaining); + m_currentItem = m_currentItem.cropped(0, RLP(m_currentItem, ThrowOnFail | FailIfTooSmall).actualSize()); + m_remaining -= std::min(m_remaining, m_currentItem.size()); } else - m_lastItem.retarget(m_lastItem.next().data(), 0); + m_currentItem.retarget(m_currentItem.next().data(), 0); return *this; } @@ -63,17 +63,17 @@ RLP::iterator::iterator(RLP const& _parent, bool _begin) if (_begin && _parent.isList()) { auto pl = _parent.payload(); - m_lastItem = pl.cropped(0, RLP(pl, ThrowOnFail | FailIfTooSmall).actualSize()); - m_remaining = pl.size() - m_lastItem.size(); + m_currentItem = pl.cropped(0, RLP(pl, ThrowOnFail | FailIfTooSmall).actualSize()); + m_remaining = pl.size() - m_currentItem.size(); } else { - m_lastItem = _parent.data().cropped(_parent.data().size()); + m_currentItem = _parent.data().cropped(_parent.data().size()); m_remaining = 0; } } -RLP RLP::operator[](unsigned _i) const +RLP RLP::operator[](size_t _i) const { if (_i < m_lastIndex) { @@ -100,7 +100,7 @@ RLPs RLP::toList() const return ret; } -unsigned RLP::actualSize() const +size_t RLP::actualSize() const { if (isNull()) return 0; @@ -142,7 +142,7 @@ bool RLP::isInt() const } else if (n < c_rlpListStart) { - if ((int)m_data.size() <= 1 + n - c_rlpDataIndLenZero) + if (m_data.size() <= size_t(1 + n - c_rlpDataIndLenZero)) BOOST_THROW_EXCEPTION(BadRLP()); return m_data[1 + n - c_rlpDataIndLenZero] != 0; } @@ -151,48 +151,58 @@ bool RLP::isInt() const return false; } -unsigned RLP::length() const +size_t RLP::length() const { if (isNull()) return 0; requireGood(); - unsigned ret = 0; - byte n = m_data[0]; + size_t ret = 0; + byte const n = m_data[0]; if (n < c_rlpDataImmLenStart) return 1; else if (n <= c_rlpDataIndLenZero) return n - c_rlpDataImmLenStart; else if (n < c_rlpListStart) { - if ((int)m_data.size() <= n - c_rlpDataIndLenZero) + if (m_data.size() <= n - c_rlpDataIndLenZero) BOOST_THROW_EXCEPTION(BadRLP()); - if ((int)m_data.size() > 1) + if (m_data.size() > 1) if (m_data[1] == 0) BOOST_THROW_EXCEPTION(BadRLP()); - for (int i = 0; i < n - c_rlpDataIndLenZero; ++i) + if (n - c_rlpDataIndLenZero > sizeof(ret)) + // We did not check, but would most probably not fit in our memory. + BOOST_THROW_EXCEPTION(UndersizeRLP()); + for (unsigned i = 0; i < n - c_rlpDataIndLenZero; ++i) ret = (ret << 8) | m_data[i + 1]; } else if (n <= c_rlpListIndLenZero) return n - c_rlpListStart; else { - if ((int)m_data.size() <= n - c_rlpListIndLenZero) + if (m_data.size() <= n - c_rlpListIndLenZero) BOOST_THROW_EXCEPTION(BadRLP()); - if ((int)m_data.size() > 1) + if (m_data.size() > 1) if (m_data[1] == 0) BOOST_THROW_EXCEPTION(BadRLP()); - for (int i = 0; i < n - c_rlpListIndLenZero; ++i) + if (n - c_rlpListIndLenZero > sizeof(ret)) + // We did not check, but would most probably not fit in our memory. + BOOST_THROW_EXCEPTION(UndersizeRLP()); + for (unsigned i = 0; i < n - c_rlpListIndLenZero; ++i) ret = (ret << 8) | m_data[i + 1]; } + // We have to be able to add payloadOffset to length without overflow. + // This rejects roughly 4GB-sized RLPs on some platforms. + if (ret >= std::numeric_limits::max() - 0x100) + BOOST_THROW_EXCEPTION(UndersizeRLP()); return ret; } -unsigned RLP::items() const +size_t RLP::items() const { if (isList()) { bytesConstRef d = payload().cropped(0, length()); - unsigned i = 0; + size_t i = 0; for (; d.size(); ++i) d = d.cropped(RLP(d, ThrowOnFail | FailIfTooSmall).actualSize()); return i; @@ -200,14 +210,14 @@ unsigned RLP::items() const return 0; } -RLPStream& RLPStream::appendRaw(bytesConstRef _s, unsigned _itemCount) +RLPStream& RLPStream::appendRaw(bytesConstRef _s, size_t _itemCount) { m_out.insert(m_out.end(), _s.begin(), _s.end()); noteAppended(_itemCount); return *this; } -void RLPStream::noteAppended(unsigned _itemCount) +void RLPStream::noteAppended(size_t _itemCount) { if (!_itemCount) return; @@ -223,7 +233,7 @@ void RLPStream::noteAppended(unsigned _itemCount) { auto p = m_listStack.back().second; m_listStack.pop_back(); - unsigned s = m_out.size() - p; // list size + size_t s = m_out.size() - p; // list size auto brs = bytesRequired(s); unsigned encodeSize = s < c_rlpListImmLenCount ? 1 : (1 + brs); // cdebug << "s: " << s << ", p: " << p << ", m_out.size(): " << m_out.size() << ", encodeSize: " << encodeSize << " (br: " << brs << ")"; @@ -232,19 +242,22 @@ void RLPStream::noteAppended(unsigned _itemCount) memmove(m_out.data() + p + encodeSize, m_out.data() + p, os - p); if (s < c_rlpListImmLenCount) m_out[p] = (byte)(c_rlpListStart + s); - else + else if (c_rlpListIndLenZero + brs <= 0xff) { + m_out[p] = (byte)(c_rlpListIndLenZero + brs); byte* b = &(m_out[p + brs]); for (; s; s >>= 8) *(b--) = (byte)s; } + else + BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("itemCount too large for RLP")); } _itemCount = 1; // for all following iterations, we've effectively appended a single item only since we completed a list. } } -RLPStream& RLPStream::appendList(unsigned _items) +RLPStream& RLPStream::appendList(size_t _items) { // cdebug << "appendList(" << _items << ")"; if (_items) @@ -266,10 +279,10 @@ RLPStream& RLPStream::appendList(bytesConstRef _rlp) RLPStream& RLPStream::append(bytesConstRef _s, bool _compact) { - unsigned s = _s.size(); + size_t s = _s.size(); byte const* d = _s.data(); if (_compact) - for (unsigned i = 0; i < _s.size() && !*d; ++i, --s, ++d) {} + for (size_t i = 0; i < _s.size() && !*d; ++i, --s, ++d) {} if (s == 1 && *d < c_rlpDataImmLenStart) m_out.push_back(*d); @@ -299,6 +312,8 @@ RLPStream& RLPStream::append(bigint _i) else { auto brbr = bytesRequired(br); + if (c_rlpDataIndLenZero + brbr > 0xff) + BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("Number too large for RLP")); m_out.push_back((byte)(c_rlpDataIndLenZero + brbr)); pushInt(br, brbr); } @@ -308,9 +323,11 @@ RLPStream& RLPStream::append(bigint _i) return *this; } -void RLPStream::pushCount(unsigned _count, byte _base) +void RLPStream::pushCount(size_t _count, byte _base) { auto br = bytesRequired(_count); + if (int(br) + _base > 0xff) + BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("Count too large for RLP")); m_out.push_back((byte)(br + _base)); // max 8 bytes. pushInt(_count, br); } diff --git a/libdevcore/RLP.h b/libdevcore/RLP.h index 67f464b9d..1586616d8 100644 --- a/libdevcore/RLP.h +++ b/libdevcore/RLP.h @@ -113,12 +113,12 @@ public: bool isInt() const; /// @returns the number of items in the list, or zero if it isn't a list. - unsigned itemCount() const { return isList() ? items() : 0; } - unsigned itemCountStrict() const { if (!isList()) BOOST_THROW_EXCEPTION(BadCast()); return items(); } + size_t itemCount() const { return isList() ? items() : 0; } + size_t itemCountStrict() const { if (!isList()) BOOST_THROW_EXCEPTION(BadCast()); return items(); } /// @returns the number of bytes in the data, or zero if it isn't data. - unsigned size() const { return isData() ? length() : 0; } - unsigned sizeStrict() const { if (!isData()) BOOST_THROW_EXCEPTION(BadCast()); return length(); } + size_t size() const { return isData() ? length() : 0; } + size_t sizeStrict() const { if (!isData()) BOOST_THROW_EXCEPTION(BadCast()); return length(); } /// Equality operators; does best-effort conversion and checks for equality. bool operator==(char const* _s) const { return isData() && toString() == _s; } @@ -137,7 +137,7 @@ public: /// Subscript operator. /// @returns the list item @a _i if isList() and @a _i < listItems(), or RLP() otherwise. /// @note if used to access items in ascending order, this is efficient. - RLP operator[](unsigned _i) const; + RLP operator[](size_t _i) const; using element_type = RLP; @@ -152,16 +152,16 @@ public: iterator& operator++(); iterator operator++(int) { auto ret = *this; operator++(); return ret; } - RLP operator*() const { return RLP(m_lastItem); } - bool operator==(iterator const& _cmp) const { return m_lastItem == _cmp.m_lastItem; } + RLP operator*() const { return RLP(m_currentItem); } + bool operator==(iterator const& _cmp) const { return m_currentItem == _cmp.m_currentItem; } bool operator!=(iterator const& _cmp) const { return !operator==(_cmp); } private: iterator() {} iterator(RLP const& _parent, bool _begin); - unsigned m_remaining = 0; - bytesConstRef m_lastItem; + size_t m_remaining = 0; + bytesConstRef m_currentItem; }; /// @brief Iterator into beginning of sub-item list (valid only if we are a list). @@ -247,7 +247,7 @@ public: if (itemCount() != N || !isList()) BOOST_THROW_EXCEPTION(BadCast()); std::array ret; - for (unsigned i = 0; i < N; ++i) + for (size_t i = 0; i < N; ++i) { ret[i] = (T)operator[](i); } @@ -259,19 +259,21 @@ public: { requireGood(); if ((!isInt() && !(_flags & AllowNonCanon)) || isList() || isNull()) + { if (_flags & ThrowOnFail) BOOST_THROW_EXCEPTION(BadCast()); else return 0; - else {} + } auto p = payload(); if (p.size() > intTraits<_T>::maxSize && (_flags & FailIfTooBig)) + { if (_flags & ThrowOnFail) BOOST_THROW_EXCEPTION(BadCast()); else return 0; - else {} + } return fromBigEndian<_T>(p); } @@ -280,14 +282,15 @@ public: { requireGood(); if (!isData() || (length() > _N::size && (_flags & FailIfTooBig)) || (length() < _N::size && (_flags & FailIfTooSmall))) + { if (_flags & ThrowOnFail) BOOST_THROW_EXCEPTION(BadCast()); else return _N(); - else{} + } _N ret; - size_t s = std::min((size_t)_N::size, (size_t)length()); + size_t s = std::min(_N::size, length()); memcpy(ret.data() + _N::size - s, payload().data(), s); return ret; } @@ -300,7 +303,7 @@ public: /// @returns the theoretical size of this item. /// @note Under normal circumstances, is equivalent to m_data.size() - use that unless you know it won't work. - unsigned actualSize() const; + size_t actualSize() const; private: /// Disable construction from rvalue @@ -316,20 +319,20 @@ private: unsigned lengthSize() const { if (isData() && m_data[0] > c_rlpDataIndLenZero) return m_data[0] - c_rlpDataIndLenZero; if (isList() && m_data[0] > c_rlpListIndLenZero) return m_data[0] - c_rlpListIndLenZero; return 0; } /// @returns the size in bytes of the payload, as given by the RLP as opposed to as inferred from m_data. - unsigned length() const; + size_t length() const; /// @returns the number of bytes into the data that the payload starts. - unsigned payloadOffset() const { return isSingleByte() ? 0 : (1 + lengthSize()); } + size_t payloadOffset() const { return isSingleByte() ? 0 : (1 + lengthSize()); } /// @returns the number of data items. - unsigned items() const; + size_t items() const; /// Our byte data. bytesConstRef m_data; /// The list-indexing cache. - mutable unsigned m_lastIndex = (unsigned)-1; - mutable unsigned m_lastEnd = 0; + mutable size_t m_lastIndex = (size_t)-1; + mutable size_t m_lastEnd = 0; mutable bytesConstRef m_lastItem; }; @@ -343,7 +346,7 @@ public: RLPStream() {} /// Initializes the RLPStream as a list of @a _listItems items. - explicit RLPStream(unsigned _listItems) { appendList(_listItems); } + explicit RLPStream(size_t _listItems) { appendList(_listItems); } ~RLPStream() {} @@ -359,7 +362,7 @@ public: 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 unless @a _itemCount is given. - RLPStream& append(RLP const& _rlp, unsigned _itemCount = 1) { return appendRaw(_rlp.data(), _itemCount); } + RLPStream& append(RLP const& _rlp, size_t _itemCount = 1) { return appendRaw(_rlp.data(), _itemCount); } /// Appends a sequence of data to the stream as a list. template RLPStream& append(std::vector<_T> const& _s) { return appendVector(_s); } @@ -370,14 +373,14 @@ public: template RLPStream& append(std::pair const& _s) { appendList(2); append(_s.first); append(_s.second); return *this; } /// Appends a list. - RLPStream& appendList(unsigned _items); + RLPStream& appendList(size_t _items); RLPStream& appendList(bytesConstRef _rlp); RLPStream& appendList(bytes const& _rlp) { return appendList(&_rlp); } RLPStream& appendList(RLPStream const& _s) { return appendList(&_s.out()); } /// Appends raw (pre-serialised) RLP data. Use with caution. - RLPStream& appendRaw(bytesConstRef _rlp, unsigned _itemCount = 1); - RLPStream& appendRaw(bytes const& _rlp, unsigned _itemCount = 1) { return appendRaw(&_rlp, _itemCount); } + RLPStream& appendRaw(bytesConstRef _rlp, size_t _itemCount = 1); + RLPStream& appendRaw(bytes const& _rlp, size_t _itemCount = 1) { return appendRaw(&_rlp, _itemCount); } /// Shift operators for appending data items. template RLPStream& operator<<(T _data) { return append(_data); } @@ -392,14 +395,14 @@ public: void swapOut(bytes& _dest) { if(!m_listStack.empty()) BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("listStack is not empty")); swap(m_out, _dest); } private: - void noteAppended(unsigned _itemCount = 1); + void noteAppended(size_t _itemCount = 1); /// Push the node-type byte (using @a _base) along with the item count @a _count. /// @arg _count is number of characters for strings, data-bytes for ints, or items for lists. - void pushCount(unsigned _count, byte _offset); + void pushCount(size_t _count, byte _offset); /// Push an integer as a raw big-endian byte-stream. - template void pushInt(_T _i, unsigned _br) + template void pushInt(_T _i, size_t _br) { m_out.resize(m_out.size() + _br); byte* b = &m_out.back(); @@ -410,7 +413,7 @@ private: /// Our output byte stream. bytes m_out; - std::vector> m_listStack; + std::vector> m_listStack; }; template void rlpListAux(RLPStream& _out, _T _t) { _out << _t; } diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp index 70f82c6d2..b634ef1d3 100644 --- a/libethereum/Transaction.cpp +++ b/libethereum/Transaction.cpp @@ -42,7 +42,7 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, ExecutionResult const& _e TransactionException dev::eth::toTransactionException(Exception const& _e) { // Basic Transaction exceptions - if (!!dynamic_cast(&_e)) + if (!!dynamic_cast(&_e)) return TransactionException::BadRLP; if (!!dynamic_cast(&_e)) return TransactionException::OutOfGasIntrinsic; From b3dfe07c2f687779097454b8eaeb6c67e35cb3e9 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 2 Jul 2015 17:37:15 +0200 Subject: [PATCH 107/290] Helper to find the length of an RLP item. --- libdevcore/RLP.cpp | 10 +++++----- libdevcore/RLP.h | 5 ++++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libdevcore/RLP.cpp b/libdevcore/RLP.cpp index cf4218050..960843f4c 100644 --- a/libdevcore/RLP.cpp +++ b/libdevcore/RLP.cpp @@ -50,7 +50,7 @@ RLP::iterator& RLP::iterator::operator++() if (m_remaining) { m_currentItem.retarget(m_currentItem.next().data(), m_remaining); - m_currentItem = m_currentItem.cropped(0, RLP(m_currentItem, ThrowOnFail | FailIfTooSmall).actualSize()); + m_currentItem = m_currentItem.cropped(0, actualSizeOfPrefix(m_currentItem)); m_remaining -= std::min(m_remaining, m_currentItem.size()); } else @@ -63,7 +63,7 @@ RLP::iterator::iterator(RLP const& _parent, bool _begin) if (_begin && _parent.isList()) { auto pl = _parent.payload(); - m_currentItem = pl.cropped(0, RLP(pl, ThrowOnFail | FailIfTooSmall).actualSize()); + m_currentItem = pl.cropped(0, actualSizeOfPrefix(pl)); m_remaining = pl.size() - m_currentItem.size(); } else @@ -77,14 +77,14 @@ RLP RLP::operator[](size_t _i) const { if (_i < m_lastIndex) { - m_lastEnd = RLP(payload(), ThrowOnFail | FailIfTooSmall).actualSize(); + m_lastEnd = actualSizeOfPrefix(payload()); m_lastItem = payload().cropped(0, m_lastEnd); m_lastIndex = 0; } for (; m_lastIndex < _i && m_lastItem.size(); ++m_lastIndex) { m_lastItem = payload().cropped(m_lastEnd); - m_lastItem = m_lastItem.cropped(0, RLP(m_lastItem, ThrowOnFail | FailIfTooSmall).actualSize()); + m_lastItem = m_lastItem.cropped(0, actualSizeOfPrefix(m_lastItem)); m_lastEnd += m_lastItem.size(); } return RLP(m_lastItem, ThrowOnFail | FailIfTooSmall); @@ -204,7 +204,7 @@ size_t RLP::items() const bytesConstRef d = payload().cropped(0, length()); size_t i = 0; for (; d.size(); ++i) - d = d.cropped(RLP(d, ThrowOnFail | FailIfTooSmall).actualSize()); + d = d.cropped(actualSizeOfPrefix(d)); return i; } return 0; diff --git a/libdevcore/RLP.h b/libdevcore/RLP.h index 1586616d8..e124ea2b6 100644 --- a/libdevcore/RLP.h +++ b/libdevcore/RLP.h @@ -301,7 +301,7 @@ public: /// @returns the data payload. Valid for all types. bytesConstRef payload() const { auto l = length(); if (l > m_data.size()) BOOST_THROW_EXCEPTION(BadRLP()); return m_data.cropped(payloadOffset(), l); } - /// @returns the theoretical size of this item. + /// @returns the theoretical size of this item as encoded in the data. /// @note Under normal circumstances, is equivalent to m_data.size() - use that unless you know it won't work. size_t actualSize() const; @@ -327,6 +327,9 @@ private: /// @returns the number of data items. size_t items() const; + /// @returns the "actualSize" of the RLP encoded in the largest prefix of @a _data and throws on error. + static size_t actualSizeOfPrefix(bytesConstRef _data) { return RLP(_data, ThrowOnFail | FailIfTooSmall).actualSize(); } + /// Our byte data. bytesConstRef m_data; From cf54c31c3ceb7ceb653debb2bb66af616474f8de Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 2 Jul 2015 19:30:43 +0200 Subject: [PATCH 108/290] fixed starved download, removed obsolete invariant --- libethereum/BlockChainSync.cpp | 27 ++++++++++++++++++++++----- libethereum/BlockChainSync.h | 1 + libp2p/RLPXSocket.h | 4 ++-- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 97684efb1..b8c613a54 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -868,6 +868,7 @@ void PV61Sync::syncHashes(std::shared_ptr _peer) m_syncingBlockNumber = 0; m_chainSyncPeers.clear(); m_knownHashes.clear(); + m_hashScanComplete = false; PV60Sync::syncHashes(_peer); return; } @@ -913,7 +914,7 @@ void PV61Sync::requestSubchain(std::shared_ptr _peer) m_chainSyncPeers[_peer] = m_readyChainMap.begin()->first; m_readyChainMap.erase(m_readyChainMap.begin()); } - else if (!m_downloadingChainMap.empty() && !m_completeChainMap.empty()) + else if (!m_downloadingChainMap.empty() && m_hashScanComplete) { // Lead syncer is done, just grab whatever we can h256s& d = m_downloadingChainMap.begin()->second; @@ -936,6 +937,13 @@ void PV61Sync::completeSubchain(std::shared_ptr _peer, unsigned _n { m_completeChainMap[_n] = move(m_downloadingChainMap.at(_n)); m_downloadingChainMap.erase(_n); + for (auto s = m_chainSyncPeers.begin(); s != m_chainSyncPeers.end(); ++s) + if (s->second == _n) //TODO: optimize this + { + m_chainSyncPeers.erase(s); + break; + } + _peer->m_syncHashNumber = 0; auto syncer = m_syncer.lock(); @@ -945,7 +953,7 @@ void PV61Sync::completeSubchain(std::shared_ptr _peer, unsigned _n return; } - if (m_readyChainMap.empty() && m_downloadingChainMap.empty() && syncer->m_asking == Asking::Nothing) + if (m_readyChainMap.empty() && m_downloadingChainMap.empty() && m_hashScanComplete) { //Done chain-get m_syncingNeededBlocks.clear(); @@ -968,6 +976,7 @@ void PV61Sync::restartSync() m_chainSyncPeers.clear(); m_syncingBlockNumber = 0; m_knownHashes.clear(); + m_hashScanComplete = false; PV60Sync::restartSync(); } @@ -986,6 +995,7 @@ void PV61Sync::onPeerHashes(std::shared_ptr _peer, h256s const& _h { // End of hash chain, add last chunk to download m_readyChainMap.insert(make_pair(m_syncingBlockNumber, h256s { _peer->m_latestHash })); + m_hashScanComplete = true; _peer->m_syncHashNumber = 0; requestSubchain(_peer); } @@ -1043,8 +1053,17 @@ void PV61Sync::onPeerHashes(std::shared_ptr _peer, h256s const& _h clog(NetAllDetail) << "Hashes response from unexpected/expired peer"; return; } - h256s& hashes = m_downloadingChainMap.at(number); + auto downloadingPeer = m_downloadingChainMap.find(number); + if (downloadingPeer == m_downloadingChainMap.end() || downloadingPeer->second.back() != _peer->m_syncHash) + { + // Too late, other peer has already downloaded our hashes + m_chainSyncPeers.erase(_peer); + requestSubchain(_peer); + return; + } + + h256s& hashes = downloadingPeer->second; unsigned knowns = 0; unsigned unknowns = 0; for (unsigned i = 0; i < _hashes.size(); ++i) @@ -1156,8 +1175,6 @@ bool PV61Sync::isPV61Syncing() const bool PV61Sync::invariants() const { - if (m_downloadingChainMap.size() != m_chainSyncPeers.size()) - BOOST_THROW_EXCEPTION(FailedInvariant() << errinfo_comment("m_downloadingChainMap and m_chainSyncPeers out of sync")); if (m_state == SyncState::Hashes) { if (isPV61Syncing() && !m_syncingBlockNumber) diff --git a/libethereum/BlockChainSync.h b/libethereum/BlockChainSync.h index 01727a0cb..213169add 100644 --- a/libethereum/BlockChainSync.h +++ b/libethereum/BlockChainSync.h @@ -315,6 +315,7 @@ private: std::map, unsigned, std::owner_less>> m_chainSyncPeers; ///< Peers to m_downloadingSubchain number map h256Hash m_knownHashes; ///< Subchain start markers. Used to track suchain completion unsigned m_syncingBlockNumber = 0; ///< Current subchain marker + bool m_hashScanComplete = false; ///< True if leading peer completed hashchain scan and we have a list of subchains ready }; } } diff --git a/libp2p/RLPXSocket.h b/libp2p/RLPXSocket.h index 389418c76..58613bf82 100644 --- a/libp2p/RLPXSocket.h +++ b/libp2p/RLPXSocket.h @@ -45,7 +45,7 @@ public: bool isConnected() const { return m_socket.is_open(); } void close() { try { boost::system::error_code ec; m_socket.shutdown(bi::tcp::socket::shutdown_both, ec); if (m_socket.is_open()) m_socket.close(); } catch (...){} } - bi::tcp::endpoint remoteEndpoint() { try { return m_socket.remote_endpoint(); } catch (...){ return bi::tcp::endpoint(); } } + bi::tcp::endpoint remoteEndpoint() { boost::system::error_code ec; return m_socket.remote_endpoint(ec); } bi::tcp::socket& ref() { return m_socket; } protected: @@ -53,4 +53,4 @@ protected: }; } -} \ No newline at end of file +} From e0b7cfaa244de1c0bbc25333aaf2369064e27a40 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 2 Jul 2015 19:58:37 +0200 Subject: [PATCH 109/290] add badStateRootTest --- .../StateTestsFiller/stSpecialTestFiller.json | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/test/libethereum/StateTestsFiller/stSpecialTestFiller.json b/test/libethereum/StateTestsFiller/stSpecialTestFiller.json index fb7a7aa8f..2944c23c4 100644 --- a/test/libethereum/StateTestsFiller/stSpecialTestFiller.json +++ b/test/libethereum/StateTestsFiller/stSpecialTestFiller.json @@ -488,5 +488,48 @@ "to" : "b03f030056db7d467d778326658bac0d1b35d8f7", "value" : "0" } + }, + + "BadStateRootTx" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "(2**256)-1", + "currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "expect" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "2000000", + "code" : "", + "nonce" : "0", + "storage" : { + } + }, + "1baf27b88c48dd02b744999cf3522766929d2b2a" : { + "balance" : "1000", + "code" : "0x600073a94f5374fce5edbc8e2a8697c15331677e6ebf0b3314156023573540602035145b15602e576040356000555b", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "0x00000000000000000000000000000000000000000000000000000000000bc03712fac13c68425054e372b0861af05648614d69d32800fba9ad4522238d4b937a0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit" : "200000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "1baf27b88c48dd02b744999cf3522766929d2b2a", + "value" : "0" + } } } From ff74c2ebcb2ec05e3e5dcc4c85f96dce29fc6d8c Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 2 Jul 2015 20:26:05 +0200 Subject: [PATCH 110/290] Fix signed/unsigned warnings. --- libdevcore/RLP.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libdevcore/RLP.cpp b/libdevcore/RLP.cpp index 960843f4c..4398dd997 100644 --- a/libdevcore/RLP.cpp +++ b/libdevcore/RLP.cpp @@ -164,30 +164,32 @@ size_t RLP::length() const return n - c_rlpDataImmLenStart; else if (n < c_rlpListStart) { - if (m_data.size() <= n - c_rlpDataIndLenZero) + if (m_data.size() <= size_t(n - c_rlpDataIndLenZero)) BOOST_THROW_EXCEPTION(BadRLP()); if (m_data.size() > 1) if (m_data[1] == 0) BOOST_THROW_EXCEPTION(BadRLP()); - if (n - c_rlpDataIndLenZero > sizeof(ret)) + unsigned lengthSize = n - c_rlpDataIndLenZero; + if (lengthSize > sizeof(ret)) // We did not check, but would most probably not fit in our memory. BOOST_THROW_EXCEPTION(UndersizeRLP()); - for (unsigned i = 0; i < n - c_rlpDataIndLenZero; ++i) + for (unsigned i = 0; i < lengthSize; ++i) ret = (ret << 8) | m_data[i + 1]; } else if (n <= c_rlpListIndLenZero) return n - c_rlpListStart; else { - if (m_data.size() <= n - c_rlpListIndLenZero) + unsigned lengthSize = n - c_rlpListIndLenZero; + if (m_data.size() <= lengthSize) BOOST_THROW_EXCEPTION(BadRLP()); if (m_data.size() > 1) if (m_data[1] == 0) BOOST_THROW_EXCEPTION(BadRLP()); - if (n - c_rlpListIndLenZero > sizeof(ret)) + if (lengthSize > sizeof(ret)) // We did not check, but would most probably not fit in our memory. BOOST_THROW_EXCEPTION(UndersizeRLP()); - for (unsigned i = 0; i < n - c_rlpListIndLenZero; ++i) + for (unsigned i = 0; i < lengthSize; ++i) ret = (ret << 8) | m_data[i + 1]; } // We have to be able to add payloadOffset to length without overflow. From 2a9b906cc3f9d66ba231a04786c7d6142a06948c Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 2 Jul 2015 22:59:37 +0200 Subject: [PATCH 111/290] removed incorrect invariant checks (subject to race contition) --- libethereum/BlockChainSync.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 63ac620ce..04bb44d0b 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -791,10 +791,6 @@ bool PV60Sync::invariants() const return false; if (m_state == SyncState::Hashes) { - bool hashes = false; - host().foreachPeer([&](std::shared_ptr _p) { if (_p->m_asking == Asking::Hashes) hashes = true; return !hashes; }); - if (!hashes) - return false; if (!m_syncingLatestHash) return false; if (m_syncingNeededBlocks.empty() != (!m_syncingLastReceivedHash)) @@ -802,10 +798,6 @@ bool PV60Sync::invariants() const } if (m_state == SyncState::Blocks || m_state == SyncState::NewBlocks) { - bool blocks = false; - host().foreachPeer([&](std::shared_ptr _p) { if (_p->m_asking == Asking::Blocks) blocks = true; return !blocks; }); - if (!blocks) - return false; if (downloadMan().isComplete()) return false; } From 00a6208e79b62c893686fe9b9c116c3e5abce1d7 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 2 Jul 2015 23:06:51 +0200 Subject: [PATCH 112/290] Don't drop DB when chaning DB format. Don't die when geth is run. Repotting. Fixed #2354. --- libdevcore/Common.h | 2 + libdevcore/CommonData.h | 99 +++++++------ libethereum/BasicGasPricer.cpp | 95 ++++++++++++ libethereum/BasicGasPricer.h | 53 +++++++ libethereum/BlockChain.cpp | 62 +++++--- libethereum/BlockChain.h | 4 +- libethereum/Client.cpp | 242 +++++++++---------------------- libethereum/Client.h | 27 ---- libethereum/EthereumHost.cpp | 2 +- libethereum/GasPricer.cpp | 26 ++++ libethereum/GasPricer.h | 74 ++++++++++ libethereum/State.cpp | 19 ++- libethereum/State.h | 42 +----- libethereum/TransactionQueue.cpp | 9 +- libethereum/Utility.cpp | 51 ++++++- libethereum/Utility.h | 2 + 16 files changed, 489 insertions(+), 320 deletions(-) create mode 100644 libethereum/BasicGasPricer.cpp create mode 100644 libethereum/BasicGasPricer.h create mode 100644 libethereum/GasPricer.cpp create mode 100644 libethereum/GasPricer.h diff --git a/libdevcore/Common.h b/libdevcore/Common.h index c7fdb6dab..edd14f4a5 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -64,6 +64,8 @@ using byte = uint8_t; #define DEV_IGNORE_EXCEPTIONS(X) try { X; } catch (...) {} +#define DEV_IF_NO_ELSE(X) if(!(X)){}else + namespace dev { diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h index ed09e60ee..0faba8e8e 100644 --- a/libdevcore/CommonData.h +++ b/libdevcore/CommonData.h @@ -50,8 +50,8 @@ enum class HexPrefix /// Convert a series of bytes to the corresponding string of hex duplets. /// @param _w specifies the width of the first of the elements. Defaults to two - enough to represent a byte. /// @example toHex("A\x69") == "4169" -template -std::string toHex(_T const& _data, int _w = 2, HexPrefix _prefix = HexPrefix::DontAdd) +template +std::string toHex(T const& _data, int _w = 2, HexPrefix _prefix = HexPrefix::DontAdd) { std::ostringstream ret; unsigned ii = 0; @@ -99,27 +99,27 @@ bytes asNibbles(bytesConstRef const& _s); /// Converts a templated integer value to the big-endian byte-stream represented on a templated collection. /// The size of the collection object will be unchanged. If it is too small, it will not represent the /// value properly, if too big then the additional elements will be zeroed out. -/// @a _Out will typically be either std::string or bytes. -/// @a _T will typically by unsigned, u160, u256 or bigint. -template -inline void toBigEndian(_T _val, _Out& o_out) +/// @a Out will typically be either std::string or bytes. +/// @a T will typically by unsigned, u160, u256 or bigint. +template +inline void toBigEndian(T _val, Out& o_out) { for (auto i = o_out.size(); i != 0; _val >>= 8, i--) { - _T v = _val & (_T)0xff; - o_out[i - 1] = (typename _Out::value_type)(uint8_t)v; + T v = _val & (T)0xff; + o_out[i - 1] = (typename Out::value_type)(uint8_t)v; } } /// Converts a big-endian byte-stream represented on a templated collection to a templated integer value. /// @a _In will typically be either std::string or bytes. -/// @a _T will typically by unsigned, u160, u256 or bigint. -template -inline _T fromBigEndian(_In const& _bytes) +/// @a T will typically by unsigned, u160, u256 or bigint. +template +inline T fromBigEndian(_In const& _bytes) { - _T ret = (_T)0; + T ret = (T)0; for (auto i: _bytes) - ret = (_T)((ret << 8) | (byte)(typename std::make_unsigned::type)i); + ret = (T)((ret << 8) | (byte)(typename std::make_unsigned::type)i); return ret; } @@ -131,11 +131,11 @@ inline bytes toBigEndian(u160 _val) { bytes ret(20); toBigEndian(_val, ret); ret /// Convenience function for toBigEndian. /// @returns a byte array just big enough to represent @a _val. -template -inline bytes toCompactBigEndian(_T _val, unsigned _min = 0) +template +inline bytes toCompactBigEndian(T _val, unsigned _min = 0) { int i = 0; - for (_T v = _val; v; ++i, v >>= 8) {} + for (T v = _val; v; ++i, v >>= 8) {} bytes ret(std::max(_min, i), 0); toBigEndian(_val, ret); return ret; @@ -147,11 +147,11 @@ inline bytes toCompactBigEndian(byte _val, unsigned _min = 0) /// Convenience function for toBigEndian. /// @returns a string just big enough to represent @a _val. -template -inline std::string toCompactBigEndianString(_T _val, unsigned _min = 0) +template +inline std::string toCompactBigEndianString(T _val, unsigned _min = 0) { int i = 0; - for (_T v = _val; v; ++i, v >>= 8) {} + for (T v = _val; v; ++i, v >>= 8) {} std::string ret(std::max(_min, i), '\0'); toBigEndian(_val, ret); return ret; @@ -179,8 +179,8 @@ std::string escaped(std::string const& _s, bool _all = true); /// Determines the length of the common prefix of the two collections given. /// @returns the number of elements both @a _t and @a _u share, in order, at the beginning. /// @example commonPrefix("Hello world!", "Hello, world!") == 5 -template -unsigned commonPrefix(_T const& _t, _U const& _u) +template +unsigned commonPrefix(T const& _t, _U const& _u) { unsigned s = std::min(_t.size(), _u.size()); for (unsigned i = 0;; ++i) @@ -196,8 +196,8 @@ std::string randomWord(); // General datatype convenience functions. /// Determine bytes required to encode the given integer value. @returns 0 if @a _i is zero. -template -inline unsigned bytesRequired(_T _i) +template +inline unsigned bytesRequired(T _i) { unsigned i = 0; for (; _i != 0; ++i, _i >>= 8) {} @@ -206,39 +206,39 @@ inline unsigned bytesRequired(_T _i) /// Trims a given number of elements from the front of a collection. /// Only works for POD element types. -template -void trimFront(_T& _t, unsigned _elements) +template +void trimFront(T& _t, unsigned _elements) { - static_assert(std::is_pod::value, ""); + static_assert(std::is_pod::value, ""); memmove(_t.data(), _t.data() + _elements, (_t.size() - _elements) * sizeof(_t[0])); _t.resize(_t.size() - _elements); } /// Pushes an element on to the front of a collection. /// Only works for POD element types. -template -void pushFront(_T& _t, _U _e) +template +void pushFront(T& _t, _U _e) { - static_assert(std::is_pod::value, ""); + static_assert(std::is_pod::value, ""); _t.push_back(_e); memmove(_t.data() + 1, _t.data(), (_t.size() - 1) * sizeof(_e)); _t[0] = _e; } /// Concatenate two vectors of elements of POD types. -template -inline std::vector<_T>& operator+=(std::vector::value, _T>::type>& _a, std::vector<_T> const& _b) +template +inline std::vector& operator+=(std::vector::value, T>::type>& _a, std::vector const& _b) { auto s = _a.size(); _a.resize(_a.size() + _b.size()); - memcpy(_a.data() + s, _b.data(), _b.size() * sizeof(_T)); + memcpy(_a.data() + s, _b.data(), _b.size() * sizeof(T)); return _a; } /// Concatenate two vectors of elements. -template -inline std::vector<_T>& operator+=(std::vector::value, _T>::type>& _a, std::vector<_T> const& _b) +template +inline std::vector& operator+=(std::vector::value, T>::type>& _a, std::vector const& _b) { _a.reserve(_a.size() + _b.size()); for (auto& i: _b) @@ -289,16 +289,16 @@ template std::vector operator+(std::vector _a, U const& } /// Concatenate two vectors of elements. -template -inline std::vector<_T> operator+(std::vector<_T> const& _a, std::vector<_T> const& _b) +template +inline std::vector operator+(std::vector const& _a, std::vector const& _b) { - std::vector<_T> ret(_a); + std::vector ret(_a); return ret += _b; } /// Merge two sets of elements. -template -inline std::set<_T>& operator+=(std::set<_T>& _a, std::set<_T> const& _b) +template +inline std::set& operator+=(std::set& _a, std::set const& _b) { for (auto& i: _b) _a.insert(i); @@ -306,13 +306,28 @@ inline std::set<_T>& operator+=(std::set<_T>& _a, std::set<_T> const& _b) } /// Merge two sets of elements. -template -inline std::set<_T> operator+(std::set<_T> const& _a, std::set<_T> const& _b) +template +inline std::set operator+(std::set const& _a, std::set const& _b) { - std::set<_T> ret(_a); + std::set ret(_a); return ret += _b; } +template +std::unordered_map& operator+=(std::unordered_map& _x, std::unordered_map const& _y) +{ + for (auto const& i: _y) + _x.insert(i); + return _x; +} + +template +std::unordered_map operator+(std::unordered_map const& _x, std::unordered_map const& _y) +{ + std::unordered_map ret(_x); + return ret += _y; +} + /// Make normal string from fixed-length string. std::string toString(string32 const& _s); diff --git a/libethereum/BasicGasPricer.cpp b/libethereum/BasicGasPricer.cpp new file mode 100644 index 000000000..145d23594 --- /dev/null +++ b/libethereum/BasicGasPricer.cpp @@ -0,0 +1,95 @@ +/* + 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 BasicGasPricer.cpp + * @author Gav Wood + * @date 2015 + */ + +#include +#include "BasicGasPricer.h" +#include "BlockChain.h" +using namespace std; +using namespace dev; +using namespace dev::eth; + +void BasicGasPricer::update(BlockChain const& _bc) +{ + unsigned c = 0; + h256 p = _bc.currentHash(); + m_gasPerBlock = _bc.info(p).gasLimit; + + map dist; + u256 total = 0; + + // make gasPrice versus gasUsed distribution for the last 1000 blocks + while (c < 1000 && p) + { + BlockInfo bi = _bc.info(p); + if (bi.transactionsRoot != EmptyTrie) + { + auto bb = _bc.block(p); + RLP r(bb); + BlockReceipts brs(_bc.receipts(bi.hash())); + size_t i = 0; + for (auto const& tr: r[1]) + { + Transaction tx(tr.data(), CheckTransaction::None); + u256 gu = brs.receipts[i].gasUsed(); + dist[tx.gasPrice()] += gu; + total += gu; + i++; + } + } + p = bi.parentHash; + ++c; + } + + // fill m_octiles with weighted gasPrices + if (total > 0) + { + m_octiles[0] = dist.begin()->first; + + // calc mean + u256 mean = 0; + for (auto const& i: dist) + mean += i.first * i.second; + mean /= total; + + // calc standard deviation + u256 sdSquared = 0; + for (auto const& i: dist) + sdSquared += i.second * (i.first - mean) * (i.first - mean); + sdSquared /= total; + + if (sdSquared) + { + long double sd = sqrt(sdSquared.convert_to()); + long double normalizedSd = sd / mean.convert_to(); + + // calc octiles normalized to gaussian distribution + boost::math::normal gauss(1.0, (normalizedSd > 0.01) ? normalizedSd : 0.01); + for (size_t i = 1; i < 8; i++) + m_octiles[i] = u256(mean.convert_to() * boost::math::quantile(gauss, i / 8.0)); + m_octiles[8] = dist.rbegin()->first; + } + else + { + for (size_t i = 0; i < 9; i++) + m_octiles[i] = (i + 1) * mean / 5; + } + } +} diff --git a/libethereum/BasicGasPricer.h b/libethereum/BasicGasPricer.h new file mode 100644 index 000000000..77d4547c5 --- /dev/null +++ b/libethereum/BasicGasPricer.h @@ -0,0 +1,53 @@ +/* + 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 BasicGasPricer.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#include +#include "GasPricer.h" + +namespace dev +{ +namespace eth +{ + +class BasicGasPricer: public GasPricer +{ +public: + explicit BasicGasPricer(u256 _weiPerRef, u256 _refsPerBlock): m_weiPerRef(_weiPerRef), m_refsPerBlock(_refsPerBlock) {} + + void setRefPrice(u256 _weiPerRef) { if ((bigint)m_refsPerBlock * _weiPerRef > std::numeric_limits::max() ) BOOST_THROW_EXCEPTION(Overflow() << errinfo_comment("ether price * block fees is larger than 2**256-1, choose a smaller number.") ); else m_weiPerRef = _weiPerRef; } + void setRefBlockFees(u256 _refsPerBlock) { if ((bigint)m_weiPerRef * _refsPerBlock > std::numeric_limits::max() ) BOOST_THROW_EXCEPTION(Overflow() << errinfo_comment("ether price * block fees is larger than 2**256-1, choose a smaller number.") ); else m_refsPerBlock = _refsPerBlock; } + + u256 ask(State const&) const override { return m_weiPerRef * m_refsPerBlock / m_gasPerBlock; } + u256 bid(TransactionPriority _p = TransactionPriority::Medium) const override { return m_octiles[(int)_p] > 0 ? m_octiles[(int)_p] : (m_weiPerRef * m_refsPerBlock / m_gasPerBlock); } + + void update(BlockChain const& _bc) override; + +private: + u256 m_weiPerRef; + u256 m_refsPerBlock; + u256 m_gasPerBlock = 3141592; + std::array m_octiles; +}; + +} +} diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 47725e088..4e0266b5b 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -127,7 +127,7 @@ static const unsigned c_minCacheSize = 1024 * 1024 * 32; #endif -BlockChain::BlockChain(bytes const& _genesisBlock, std::string _path, WithExisting _we, ProgressCallback const& _p) +BlockChain::BlockChain(bytes const& _genesisBlock, std::string const& _path, WithExisting _we, ProgressCallback const& _p) { // initialise deathrow. m_cacheUsage.resize(c_collectionQueueSize); @@ -137,8 +137,7 @@ BlockChain::BlockChain(bytes const& _genesisBlock, std::string _path, WithExisti m_genesisBlock = _genesisBlock; m_genesisHash = sha3(RLP(m_genesisBlock)[0].data()); - open(_path, _we); - if (_we == WithExisting::Verify) + if (open(_path, _we) != c_minorProtocolVersion) rebuild(_path, _p); } @@ -147,24 +146,41 @@ BlockChain::~BlockChain() close(); } -void BlockChain::open(std::string const& _path, WithExisting _we) +unsigned BlockChain::open(std::string const& _path, WithExisting _we) { - std::string path = _path.empty() ? Defaults::get()->m_dbPath : _path; - boost::filesystem::create_directories(path); + string path = _path.empty() ? Defaults::get()->m_dbPath : _path; + string chainPath = path + "/" + toHex(m_genesisHash.ref().cropped(0, 4)); + string extrasPath = chainPath + "/" + toString(c_databaseVersion); + + boost::filesystem::create_directories(extrasPath); + + bytes status = contents(extrasPath + "/minor"); + unsigned lastMinor = c_minorProtocolVersion; + DEV_IGNORE_EXCEPTIONS(lastMinor = (unsigned)RLP(status)); + if (c_minorProtocolVersion != lastMinor) + { + cnote << "Killing extras database (DB minor version:" << lastMinor << " != our miner version: " << c_minorProtocolVersion << ")."; + DEV_IGNORE_EXCEPTIONS(boost::filesystem::remove_all(extrasPath + "/details.old")); + boost::filesystem::rename(extrasPath + "/extras", extrasPath + "/extras.old"); + boost::filesystem::remove_all(extrasPath + "/state"); + writeFile(extrasPath + "/minor", rlp(c_minorProtocolVersion)); + lastMinor = (unsigned)RLP(status); + } if (_we == WithExisting::Kill) { - boost::filesystem::remove_all(path + "/blocks"); - boost::filesystem::remove_all(path + "/details"); + cnote << "Killing blockchain & extras database (WithExisting::Kill)."; + boost::filesystem::remove_all(chainPath + "/blocks"); + boost::filesystem::remove_all(extrasPath + "/extras"); } ldb::Options o; o.create_if_missing = true; o.max_open_files = 256; - ldb::DB::Open(o, path + "/blocks", &m_blocksDB); - ldb::DB::Open(o, path + "/details", &m_extrasDB); + ldb::DB::Open(o, chainPath + "/blocks", &m_blocksDB); + ldb::DB::Open(o, extrasPath + "/extras", &m_extrasDB); if (!m_blocksDB || !m_extrasDB) { - if (boost::filesystem::space(path + "/blocks").available < 1024) + if (boost::filesystem::space(chainPath + "/blocks").available < 1024) { cwarn << "Not enough available space found on hard drive. Please free some up and then re-run. Bailing."; BOOST_THROW_EXCEPTION(NotEnoughAvailableSpace()); @@ -194,7 +210,8 @@ void BlockChain::open(std::string const& _path, WithExisting _we) m_lastBlockHash = l.empty() ? m_genesisHash : *(h256*)l.data(); m_lastBlockNumber = number(m_lastBlockHash); - cnote << "Opened blockchain DB. Latest: " << currentHash(); + cnote << "Opened blockchain DB. Latest: " << currentHash() << (lastMinor == c_minorProtocolVersion ? "(rebuild not needed)" : "*** REBUILD NEEDED ***"); + return lastMinor; } void BlockChain::close() @@ -208,11 +225,11 @@ void BlockChain::close() m_blocks.clear(); } -#define IGNORE_EXCEPTIONS(X) try { X; } catch (...) {} - void BlockChain::rebuild(std::string const& _path, std::function const& _progress, bool _prepPoW) { - std::string path = _path.empty() ? Defaults::get()->m_dbPath : _path; + string path = _path.empty() ? Defaults::get()->m_dbPath : _path; + string chainPath = path + "/" + toHex(m_genesisHash.ref().cropped(0, 4)); + string extrasPath = chainPath + "/" + toString(c_databaseVersion); #if ETH_PROFILING_GPERF ProfilerStart("BlockChain_rebuild.log"); @@ -220,16 +237,21 @@ void BlockChain::rebuild(std::string const& _path, std::function; class BlockChain { public: - BlockChain(bytes const& _genesisBlock, std::string _path, WithExisting _we, ProgressCallback const& _p = ProgressCallback()); + BlockChain(bytes const& _genesisBlock, std::string const& _path, WithExisting _we = WithExisting::Trust, ProgressCallback const& _p = ProgressCallback()); ~BlockChain(); /// Attempt a database re-open. @@ -261,7 +261,7 @@ public: private: static h256 chunkId(unsigned _level, unsigned _index) { return h256(_index * 0xff + _level); } - void open(std::string const& _path, WithExisting _we = WithExisting::Trust); + unsigned open(std::string const& _path, WithExisting _we = WithExisting::Trust); void close(); template T queryExtras(h256 const& _h, std::unordered_map& _m, boost::shared_mutex& _x, T const& _n, ldb::DB* _extrasDB = nullptr) const diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 172a45983..e812fb4e9 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #if ETH_JSONRPC || !ETH_TRUE #include #include @@ -38,53 +37,82 @@ #include "Defaults.h" #include "Executive.h" #include "EthereumHost.h" +#include "Utility.h" using namespace std; using namespace dev; using namespace dev::eth; using namespace p2p; -VersionChecker::VersionChecker(string const& _dbPath): - m_path(_dbPath.size() ? _dbPath : Defaults::dbPath()) +std::ostream& dev::eth::operator<<(std::ostream& _out, ActivityReport const& _r) { - bytes statusBytes = contents(m_path + "/status"); - RLP status(statusBytes); - try - { - auto protocolVersion = (unsigned)status[0]; - (void)protocolVersion; - auto minorProtocolVersion = (unsigned)status[1]; - auto databaseVersion = (unsigned)status[2]; - h256 ourGenesisHash = CanonBlockChain::genesis().hash(); - auto genesisHash = status.itemCount() > 3 ? (h256)status[3] : ourGenesisHash; - - m_action = - databaseVersion != c_databaseVersion || genesisHash != ourGenesisHash ? - WithExisting::Kill - : minorProtocolVersion != eth::c_minorProtocolVersion ? - WithExisting::Verify - : - WithExisting::Trust; - } - catch (...) - { - m_action = WithExisting::Kill; - } + _out << "Since " << toString(_r.since) << " (" << std::chrono::duration_cast(std::chrono::system_clock::now() - _r.since).count(); + _out << "): " << _r.ticks << "ticks"; + return _out; } -void VersionChecker::setOk() +#ifdef _WIN32 +const char* ClientNote::name() { return EthTeal "^" EthBlue " i"; } +const char* ClientChat::name() { return EthTeal "^" EthWhite " o"; } +const char* ClientTrace::name() { return EthTeal "^" EthGray " O"; } +const char* ClientDetail::name() { return EthTeal "^" EthCoal " 0"; } +#else +const char* ClientNote::name() { return EthTeal "⧫" EthBlue " ℹ"; } +const char* ClientChat::name() { return EthTeal "⧫" EthWhite " ◌"; } +const char* ClientTrace::name() { return EthTeal "⧫" EthGray " ◎"; } +const char* ClientDetail::name() { return EthTeal "⧫" EthCoal " ●"; } +#endif + +static const Addresses c_canaries = { - if (m_action != WithExisting::Trust) - { - try - { - boost::filesystem::create_directory(m_path); - } - catch (...) - { - cwarn << "Unhandled exception! Failed to create directory: " << m_path << "\n" << boost::current_exception_diagnostic_information(); - } - writeFile(m_path + "/status", rlpList(eth::c_protocolVersion, eth::c_minorProtocolVersion, c_databaseVersion, CanonBlockChain::genesis().hash())); - } + Address("4bb7e8ae99b645c2b7860b8f3a2328aae28bd80a"), // gav + Address("1baf27b88c48dd02b744999cf3522766929d2b2a"), // vitalik + Address("a8edb1ac2c86d3d9d78f96cd18001f60df29e52c"), // jeff + Address("60d11b58744784dc97f878f7e3749c0f1381a004") // christoph +}; + +VersionChecker::VersionChecker(string const& _dbPath) +{ + upgradeDatabase(_dbPath); +} + +Client::Client(p2p::Host* _extNet, std::string const& _dbPath, WithExisting _forceAction, u256 _networkId): + Client(_extNet, make_shared(), _dbPath, _forceAction, _networkId) +{ + startWorking(); +} + +Client::Client(p2p::Host* _extNet, std::shared_ptr _gp, std::string const& _dbPath, WithExisting _forceAction, u256 _networkId): + Worker("eth", 0), + m_vc(_dbPath), + m_bc(_dbPath, _forceAction, [](unsigned d, unsigned t){ cerr << "REVISING BLOCKCHAIN: Processed " << d << " of " << t << "...\r"; }), + m_gp(_gp), + m_stateDB(State::openDB(_dbPath, _forceAction)), + m_preMine(m_stateDB, BaseState::CanonGenesis), + m_postMine(m_stateDB) +{ + m_lastGetWork = std::chrono::system_clock::now() - chrono::seconds(30); + m_tqReady = m_tq.onReady([=](){ this->onTransactionQueueReady(); }); // TODO: should read m_tq->onReady(thisThread, syncTransactionQueue); + m_bqReady = m_bq.onReady([=](){ this->onBlockQueueReady(); }); // TODO: should read m_bq->onReady(thisThread, syncBlockQueue); + m_bq.setOnBad([=](Exception& ex){ this->onBadBlock(ex); }); + m_bc.setOnBad([=](Exception& ex){ this->onBadBlock(ex); }); + m_farm.onSolutionFound([=](ProofOfWork::Solution const& s){ return this->submitWork(s); }); + + m_gp->update(m_bc); + + auto host = _extNet->registerCapability(new EthereumHost(m_bc, m_tq, m_bq, _networkId)); + m_host = host; + _extNet->addCapability(host, EthereumHost::staticName(), EthereumHost::c_oldProtocolVersion); //TODO: remove this one v61+ protocol is common + + if (_dbPath.size()) + Defaults::setDBPath(_dbPath); + doWork(); + + startWorking(); +} + +Client::~Client() +{ + stopWorking(); } ImportResult Client::queueBlock(bytes const& _block, bool _isSafe) @@ -211,142 +239,6 @@ void Client::onBadBlock(Exception& _ex) const #endif } -void BasicGasPricer::update(BlockChain const& _bc) -{ - unsigned c = 0; - h256 p = _bc.currentHash(); - m_gasPerBlock = _bc.info(p).gasLimit; - - map dist; - u256 total = 0; - - // make gasPrice versus gasUsed distribution for the last 1000 blocks - while (c < 1000 && p) - { - BlockInfo bi = _bc.info(p); - if (bi.transactionsRoot != EmptyTrie) - { - auto bb = _bc.block(p); - RLP r(bb); - BlockReceipts brs(_bc.receipts(bi.hash())); - size_t i = 0; - for (auto const& tr: r[1]) - { - Transaction tx(tr.data(), CheckTransaction::None); - u256 gu = brs.receipts[i].gasUsed(); - dist[tx.gasPrice()] += gu; - total += gu; - i++; - } - } - p = bi.parentHash; - ++c; - } - - // fill m_octiles with weighted gasPrices - if (total > 0) - { - m_octiles[0] = dist.begin()->first; - - // calc mean - u256 mean = 0; - for (auto const& i: dist) - mean += i.first * i.second; - mean /= total; - - // calc standard deviation - u256 sdSquared = 0; - for (auto const& i: dist) - sdSquared += i.second * (i.first - mean) * (i.first - mean); - sdSquared /= total; - - if (sdSquared) - { - long double sd = sqrt(sdSquared.convert_to()); - long double normalizedSd = sd / mean.convert_to(); - - // calc octiles normalized to gaussian distribution - boost::math::normal gauss(1.0, (normalizedSd > 0.01) ? normalizedSd : 0.01); - for (size_t i = 1; i < 8; i++) - m_octiles[i] = u256(mean.convert_to() * boost::math::quantile(gauss, i / 8.0)); - m_octiles[8] = dist.rbegin()->first; - } - else - { - for (size_t i = 0; i < 9; i++) - m_octiles[i] = (i + 1) * mean / 5; - } - } -} - -std::ostream& dev::eth::operator<<(std::ostream& _out, ActivityReport const& _r) -{ - _out << "Since " << toString(_r.since) << " (" << std::chrono::duration_cast(std::chrono::system_clock::now() - _r.since).count(); - _out << "): " << _r.ticks << "ticks"; - return _out; -} - -#ifdef _WIN32 -const char* ClientNote::name() { return EthTeal "^" EthBlue " i"; } -const char* ClientChat::name() { return EthTeal "^" EthWhite " o"; } -const char* ClientTrace::name() { return EthTeal "^" EthGray " O"; } -const char* ClientDetail::name() { return EthTeal "^" EthCoal " 0"; } -#else -const char* ClientNote::name() { return EthTeal "⧫" EthBlue " ℹ"; } -const char* ClientChat::name() { return EthTeal "⧫" EthWhite " ◌"; } -const char* ClientTrace::name() { return EthTeal "⧫" EthGray " ◎"; } -const char* ClientDetail::name() { return EthTeal "⧫" EthCoal " ●"; } -#endif - -Client::Client(p2p::Host* _extNet, std::string const& _dbPath, WithExisting _forceAction, u256 _networkId): - Client(_extNet, make_shared(), _dbPath, _forceAction, _networkId) -{ - startWorking(); -} - -Client::Client(p2p::Host* _extNet, std::shared_ptr _gp, std::string const& _dbPath, WithExisting _forceAction, u256 _networkId): - Worker("eth", 0), - m_vc(_dbPath), - m_bc(_dbPath, max(m_vc.action(), _forceAction), [](unsigned d, unsigned t){ cerr << "REVISING BLOCKCHAIN: Processed " << d << " of " << t << "...\r"; }), - m_gp(_gp), - m_stateDB(State::openDB(_dbPath, max(m_vc.action(), _forceAction))), - m_preMine(m_stateDB, BaseState::CanonGenesis), - m_postMine(m_stateDB) -{ - m_lastGetWork = std::chrono::system_clock::now() - chrono::seconds(30); - m_tqReady = m_tq.onReady([=](){ this->onTransactionQueueReady(); }); // TODO: should read m_tq->onReady(thisThread, syncTransactionQueue); - m_bqReady = m_bq.onReady([=](){ this->onBlockQueueReady(); }); // TODO: should read m_bq->onReady(thisThread, syncBlockQueue); - m_bq.setOnBad([=](Exception& ex){ this->onBadBlock(ex); }); - m_bc.setOnBad([=](Exception& ex){ this->onBadBlock(ex); }); - m_farm.onSolutionFound([=](ProofOfWork::Solution const& s){ return this->submitWork(s); }); - - m_gp->update(m_bc); - - auto host = _extNet->registerCapability(new EthereumHost(m_bc, m_tq, m_bq, _networkId)); - m_host = host; - _extNet->addCapability(host, EthereumHost::staticName(), EthereumHost::c_oldProtocolVersion); //TODO: remove this one v61+ protocol is common - - if (_dbPath.size()) - Defaults::setDBPath(_dbPath); - m_vc.setOk(); - doWork(); - - startWorking(); -} - -Client::~Client() -{ - stopWorking(); -} - -static const Addresses c_canaries = -{ - Address("4bb7e8ae99b645c2b7860b8f3a2328aae28bd80a"), // gav - Address("1baf27b88c48dd02b744999cf3522766929d2b2a"), // vitalik - Address("a8edb1ac2c86d3d9d78f96cd18001f60df29e52c"), // jeff - Address("60d11b58744784dc97f878f7e3749c0f1381a004") // christoph -}; - bool Client::isChainBad() const { unsigned numberBad = 0; diff --git a/libethereum/Client.h b/libethereum/Client.h index 8deeb3353..343ca5b60 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -64,33 +64,6 @@ class VersionChecker { public: VersionChecker(std::string const& _dbPath); - - void setOk(); - WithExisting action() const { return m_action; } - -private: - WithExisting m_action; - std::string m_path; -}; - -class BasicGasPricer: public GasPricer -{ -public: - explicit BasicGasPricer(u256 _weiPerRef, u256 _refsPerBlock): m_weiPerRef(_weiPerRef), m_refsPerBlock(_refsPerBlock) {} - - void setRefPrice(u256 _weiPerRef) { if ((bigint)m_refsPerBlock * _weiPerRef > std::numeric_limits::max() ) BOOST_THROW_EXCEPTION(Overflow() << errinfo_comment("ether price * block fees is larger than 2**256-1, choose a smaller number.") ); else m_weiPerRef = _weiPerRef; } - void setRefBlockFees(u256 _refsPerBlock) { if ((bigint)m_weiPerRef * _refsPerBlock > std::numeric_limits::max() ) BOOST_THROW_EXCEPTION(Overflow() << errinfo_comment("ether price * block fees is larger than 2**256-1, choose a smaller number.") ); else m_refsPerBlock = _refsPerBlock; } - - u256 ask(State const&) const override { return m_weiPerRef * m_refsPerBlock / m_gasPerBlock; } - u256 bid(TransactionPriority _p = TransactionPriority::Medium) const override { return m_octiles[(int)_p] > 0 ? m_octiles[(int)_p] : (m_weiPerRef * m_refsPerBlock / m_gasPerBlock); } - - void update(BlockChain const& _bc) override; - -private: - u256 m_weiPerRef; - u256 m_refsPerBlock; - u256 m_gasPerBlock = 3141592; - std::array m_octiles; }; struct ClientNote: public LogChannel { static const char* name(); static const int verbosity = 2; }; diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 9980f4339..55a1d1bf0 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -286,7 +286,7 @@ void EthereumHost::onPeerTransactions(std::shared_ptr _peer, RLP c unsigned itemCount = _r.itemCount(); clog(NetAllDetail) << "Transactions (" << dec << itemCount << "entries)"; Guard l(_peer->x_knownTransactions); - for (unsigned i = 0; i < min(itemCount, 256); ++i) // process 256 transactions at most. TODO: much better solution. + for (unsigned i = 0; i < min(itemCount, 32); ++i) // process 256 transactions at most. TODO: much better solution. { auto h = sha3(_r[i].data()); _peer->m_knownTransactions.insert(h); diff --git a/libethereum/GasPricer.cpp b/libethereum/GasPricer.cpp new file mode 100644 index 000000000..21f061afc --- /dev/null +++ b/libethereum/GasPricer.cpp @@ -0,0 +1,26 @@ +/* + 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 GasPricer.cpp + * @author Gav Wood + * @date 2015 + */ + +#include "GasPricer.h" + +using namespace std; +using namespace dev; +using namespace dev::eth; diff --git a/libethereum/GasPricer.h b/libethereum/GasPricer.h new file mode 100644 index 000000000..f0fc6b520 --- /dev/null +++ b/libethereum/GasPricer.h @@ -0,0 +1,74 @@ +/* + 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 GasPricer.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#include + +namespace dev +{ +namespace eth +{ + +class State; +class BlockChain; + +enum class TransactionPriority +{ + Lowest = 0, + Low = 2, + Medium = 4, + High = 6, + Highest = 8 +}; + +class GasPricer +{ +public: + GasPricer() = default; + virtual ~GasPricer() = default; + + virtual u256 ask(State const&) const = 0; + virtual u256 bid(TransactionPriority _p = TransactionPriority::Medium) const = 0; + + virtual void update(BlockChain const&) {} +}; + +class TrivialGasPricer: public GasPricer +{ +public: + TrivialGasPricer() = default; + TrivialGasPricer(u256 const& _ask, u256 const& _bid): m_ask(_ask), m_bid(_bid) {} + + void setAsk(u256 const& _ask) { m_ask = _ask; } + void setBid(u256 const& _bid) { m_bid = _bid; } + + u256 ask() const { return m_ask; } + u256 ask(State const&) const override { return m_ask; } + u256 bid(TransactionPriority = TransactionPriority::Medium) const override { return m_bid; } + +private: + u256 m_ask = 10 * szabo; + u256 m_bid = 10 * szabo; +}; + +} +} diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 3f9978569..6c8927313 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -41,6 +41,7 @@ using namespace std; using namespace dev; using namespace dev::eth; +namespace fs = boost::filesystem; #define ctrace clog(StateTrace) #define ETH_TIMED_ENACTMENTS 0 @@ -52,23 +53,27 @@ const char* StateDetail::name() { return EthViolet "⚙" EthWhite " ◌"; } const char* StateTrace::name() { return EthViolet "⚙" EthGray " ◎"; } const char* StateChat::name() { return EthViolet "⚙" EthWhite " ◌"; } -OverlayDB State::openDB(std::string _path, WithExisting _we) +OverlayDB State::openDB(std::string const& _basePath, WithExisting _we) { - if (_path.empty()) - _path = Defaults::get()->m_dbPath; - boost::filesystem::create_directory(_path); + std::string path = _basePath.empty() ? Defaults::get()->m_dbPath : _basePath; if (_we == WithExisting::Kill) - boost::filesystem::remove_all(_path + "/state"); + { + cnote << "Killing state database (WithExisting::Kill)."; + boost::filesystem::remove_all(path + "/state"); + } + + path += "/" + toHex(CanonBlockChain::genesis().hash().ref().cropped(0, 4)) + "/" + toString(c_databaseVersion); + boost::filesystem::create_directory(path); ldb::Options o; o.max_open_files = 256; o.create_if_missing = true; ldb::DB* db = nullptr; - ldb::DB::Open(o, _path + "/state", &db); + ldb::DB::Open(o, path + "/state", &db); if (!db) { - if (boost::filesystem::space(_path + "/state").available < 1024) + if (boost::filesystem::space(path + "/state").available < 1024) { cwarn << "Not enough available space found on hard drive. Please free some up and then re-run. Bailing."; BOOST_THROW_EXCEPTION(NotEnoughAvailableSpace()); diff --git a/libethereum/State.h b/libethereum/State.h index 6c54cedf7..2a63aeda4 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -37,6 +37,7 @@ #include "Transaction.h" #include "TransactionReceipt.h" #include "AccountDiff.h" +#include "GasPricer.h" namespace dev { @@ -80,45 +81,6 @@ enum class BaseState CanonGenesis }; -enum class TransactionPriority -{ - Lowest = 0, - Low = 2, - Medium = 4, - High = 6, - Highest = 8 -}; - -class GasPricer -{ -public: - GasPricer() = default; - virtual ~GasPricer() = default; - - virtual u256 ask(State const&) const = 0; - virtual u256 bid(TransactionPriority _p = TransactionPriority::Medium) const = 0; - - virtual void update(BlockChain const&) {} -}; - -class TrivialGasPricer: public GasPricer -{ -public: - TrivialGasPricer() = default; - TrivialGasPricer(u256 const& _ask, u256 const& _bid): m_ask(_ask), m_bid(_bid) {} - - void setAsk(u256 const& _ask) { m_ask = _ask; } - void setBid(u256 const& _bid) { m_bid = _bid; } - - u256 ask() const { return m_ask; } - u256 ask(State const&) const override { return m_ask; } - u256 bid(TransactionPriority = TransactionPriority::Medium) const override { return m_bid; } - -private: - u256 m_ask = 10 * szabo; - u256 m_bid = 10 * szabo; -}; - enum class Permanence { Reverted, @@ -171,7 +133,7 @@ public: Address address() const { return m_ourAddress; } /// Open a DB - useful for passing into the constructor & keeping for other states that are necessary. - static OverlayDB openDB(std::string _path, WithExisting _we = WithExisting::Trust); + static OverlayDB openDB(std::string const& _path, WithExisting _we = WithExisting::Trust); static OverlayDB openDB(WithExisting _we = WithExisting::Trust) { return openDB(std::string(), _we); } OverlayDB const& db() const { return m_db; } OverlayDB& db() { return m_db; } diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 8fcf3cfb6..8b0451d65 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -98,11 +98,7 @@ ImportResult TransactionQueue::import(Transaction const& _transaction, ImportCal std::unordered_map TransactionQueue::transactions() const { ReadGuard l(m_lock); - auto ret = m_current; - for (auto const& i: m_future) - if (i.second.nonce() < maxNonce_WITH_LOCK(i.second.sender())) - ret.insert(i); - return ret; + return m_current + m_future; } ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transaction const& _transaction, ImportCallback const& _cb) @@ -113,6 +109,9 @@ ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transactio // If it doesn't work, the signature is bad. // The transaction's nonce may yet be invalid (or, it could be "valid" but we may be missing a marginally older transaction). + + // Remove any prior transaction with the same nonce but a lower gas price. + // Bomb out if there's a prior transaction with higher gas price. auto r = m_senders.equal_range(_transaction.from()); for (auto it = r.first; it != r.second; ++it) if (m_current.count(it->second) && m_current[it->second].nonce() == _transaction.nonce()) diff --git a/libethereum/Utility.cpp b/libethereum/Utility.cpp index adfea4a51..a9158a363 100644 --- a/libethereum/Utility.cpp +++ b/libethereum/Utility.cpp @@ -22,11 +22,16 @@ #include "Utility.h" #include -#include +#include #include +#include +#include +#include +#include "Defaults.h" using namespace std; using namespace dev; using namespace dev::eth; +namespace fs = boost::filesystem; bytes dev::eth::parseData(string const& _args) { @@ -84,3 +89,47 @@ bytes dev::eth::parseData(string const& _args) return m_data; } + +void dev::eth::upgradeDatabase(std::string const& _basePath) +{ + std::string path = _basePath.empty() ? Defaults::get()->dbPath() : _basePath; + + if (fs::exists(path + "/state") && fs::exists(path + "/details") && fs::exists(path + "/blocks")) + { + // upgrade + cnote << "Upgrading database to new layout..."; + bytes statusBytes = contents(path + "/status"); + RLP status(statusBytes); + try + { + auto minorProtocolVersion = (unsigned)status[1]; + auto databaseVersion = (unsigned)status[2]; + auto genesisHash = (h256)status[3]; + + string chainPath = path + "/" + toHex(genesisHash.ref().cropped(0, 4)); + string extrasPath = chainPath + "/" + toString(databaseVersion); + + // write status + if (!fs::exists(chainPath + "/blocks")) + { + boost::filesystem::create_directories(chainPath); + fs::rename(path + "/blocks", chainPath + "/blocks"); + + if (!fs::exists(extrasPath + "/extras")) + { + boost::filesystem::create_directories(extrasPath); + fs::rename(path + "/details", extrasPath + "/extras"); + fs::rename(path + "/state", extrasPath + "/state"); + writeFile(extrasPath + "/minor", rlp(minorProtocolVersion)); + + fs::remove_all(path + "/status"); + } + } + } + catch (...) + { + cwarn << "Couldn't upgrade - bad status"; + } + } +} + diff --git a/libethereum/Utility.h b/libethereum/Utility.h index 893604139..0dfe8509b 100644 --- a/libethereum/Utility.h +++ b/libethereum/Utility.h @@ -42,5 +42,7 @@ namespace eth */ bytes parseData(std::string const& _args); +void upgradeDatabase(std::string const& _basePath); + } } From f1c91d5c7f9a8f9a9c32f79fdef254812e161dca Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 2 Jul 2015 23:30:42 +0200 Subject: [PATCH 113/290] Capture this by value not reference. Remove dead code. --- libethereum/Executive.h | 2 +- libethereum/State.cpp | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/libethereum/Executive.h b/libethereum/Executive.h index 41a8d1961..89fa00214 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -53,7 +53,7 @@ public: std::string json(bool _styled = false) const; - OnOpFunc onOp() { return [&](uint64_t _steps, Instruction _inst, bigint _newMemSize, bigint _gasCost, bigint _gas, VM* _vm, ExtVMFace const* _extVM) { (*this)(_steps, _inst, _newMemSize, _gasCost, _gas, _vm, _extVM); }; } + OnOpFunc onOp() { return [=](uint64_t _steps, Instruction _inst, bigint _newMemSize, bigint _gasCost, bigint _gas, VM* _vm, ExtVMFace const* _extVM) { (*this)(_steps, _inst, _newMemSize, _gasCost, _gas, _vm, _extVM); }; } private: bool m_showMnemonics = false; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 6c8927313..b383d0a6a 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -608,7 +608,6 @@ string State::vmTrace(bytesConstRef _block, BlockChain const& _bc, ImportRequire m_currentBlock.noteDirty(); LastHashes lh = _bc.lastHashes((unsigned)m_previousBlock.number); - vector receipts; string ret; unsigned i = 0; @@ -618,10 +617,6 @@ string State::vmTrace(bytesConstRef _block, BlockChain const& _bc, ImportRequire st.setShowMnemonics(); execute(lh, Transaction(tr.data(), CheckTransaction::Everything), Permanence::Committed, st.onOp()); ret += (ret.empty() ? "[" : ",") + st.json(); - - RLPStream receiptRLP; - m_receipts.back().streamRLP(receiptRLP); - receipts.push_back(receiptRLP.out()); ++i; } return ret.empty() ? "[]" : (ret + "]"); From 07045622075b600ce9994335cd8eff3425861241 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Fri, 3 Jul 2015 00:01:12 +0200 Subject: [PATCH 114/290] style --- test/libethereum/transactionqueue.cpp | 34 ++++++++++++++++----------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/test/libethereum/transactionqueue.cpp b/test/libethereum/transactionqueue.cpp index b7071d640..ab85350a5 100644 --- a/test/libethereum/transactionqueue.cpp +++ b/test/libethereum/transactionqueue.cpp @@ -14,10 +14,10 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file transaction.cpp - * @author Christoph Jentzsch +/** @file transactionqueue.cpp + * @author Christoph Jentzsch * @date 2015 - * Transaaction test functions. + * TransactionQueue test functions. */ #include @@ -35,24 +35,30 @@ BOOST_AUTO_TEST_CASE(maxNonce) dev::eth::TransactionQueue txq; // from a94f5374fce5edbc8e2a8697c15331677e6ebf0b - Transaction tx0(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 0, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); - Transaction tx0_1(1, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 0, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); - Transaction tx1(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 1, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); - Transaction tx2(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 2, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); - Transaction tx9(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 9, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); + const u256 gasCost = 10 * szabo; + const u256 gas = 25000; + Address dest = Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"); + Address to = Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"); + Secret sec = Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8"); + Transaction tx0(0, gasCost, gas, dest, bytes(), 0, sec ); + Transaction tx0_1(1, gasCost, gas, dest, bytes(), 0, sec ); + Transaction tx1(0, gasCost, gas, dest, bytes(), 1, sec ); + Transaction tx2(0, gasCost, gas, dest, bytes(), 2, sec ); + Transaction tx9(0, gasCost, gas, dest, bytes(), 9, sec ); txq.import(tx0); - BOOST_CHECK_EQUAL(1, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + BOOST_CHECK(1 == txq.maxNonce(to)); txq.import(tx0); - BOOST_CHECK_EQUAL(1, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + BOOST_CHECK(1 == txq.maxNonce(to)); txq.import(tx0_1); - BOOST_CHECK_EQUAL(1, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + BOOST_CHECK(1 == txq.maxNonce(to)); txq.import(tx1); - BOOST_CHECK_EQUAL(2, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + BOOST_CHECK(2 == txq.maxNonce(to)); txq.import(tx9); - BOOST_CHECK_EQUAL(10, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + BOOST_CHECK(10 == txq.maxNonce(to)); txq.import(tx2); - BOOST_CHECK_EQUAL(10, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + BOOST_CHECK(10 == txq.maxNonce(to)); + } BOOST_AUTO_TEST_SUITE_END() From 466070b5de4308377f39ffde63c105f205424f51 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 3 Jul 2015 10:03:20 +0200 Subject: [PATCH 115/290] transaction queue shouldn't be returning future txs. --- libethereum/TransactionQueue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 8b0451d65..bbda58fd7 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -98,7 +98,7 @@ ImportResult TransactionQueue::import(Transaction const& _transaction, ImportCal std::unordered_map TransactionQueue::transactions() const { ReadGuard l(m_lock); - return m_current + m_future; + return m_current; } ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transaction const& _transaction, ImportCallback const& _cb) From c9489a14e7042cf3c317d22521bab5c98f6083b7 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 3 Jul 2015 10:03:40 +0200 Subject: [PATCH 116/290] Fix js console. Clean up eth's main. --- eth/main.cpp | 2663 ++++++++++++++++++++++++-------------------------- 1 file changed, 1288 insertions(+), 1375 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index b4f0326a9..e60da08f5 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -285,1555 +285,1463 @@ void stopMiningAfterXBlocks(eth::Client* _c, unsigned _start, unsigned _mining) this_thread::sleep_for(chrono::milliseconds(100)); } -int main(int argc, char** argv) +void interactiveMode(eth::Client* c, std::shared_ptr gasPricer, WebThreeDirect& web3, KeyManager& keyManager, string& logbuf, string& additional, function getPassword, function getAccountPassword, NetworkPreferences netPrefs, Address beneficiary, Address signingKey, TransactionPriority priority) { - // Init defaults - Defaults::get(); - - /// Operating mode. - OperationMode mode = OperationMode::Node; - string dbPath; - unsigned prime = 0; - bool yesIReallyKnowWhatImDoing = false; - - /// File name for import/export. - string filename; - bool safeImport = false; - - /// Hashes/numbers for export range. - string exportFrom = "1"; - string exportTo = "latest"; - Format exportFormat = Format::Binary; - - /// General params for Node operation - NodeMode nodeMode = NodeMode::Full; - bool interactive = false; -#if ETH_JSONRPC - int jsonrpc = -1; -#endif - string jsonAdmin; - bool upnp = true; - WithExisting killChain = WithExisting::Trust; - bool jit = false; - string sentinel; - - /// Networking params. - string clientName; - string listenIP; - unsigned short listenPort = 30303; - string publicIP; - string remoteHost; - unsigned short remotePort = 30303; - unsigned peers = 11; - bool bootstrap = false; - bool disableDiscovery = false; - bool pinning = false; - unsigned networkId = 0; - - /// Mining params - unsigned mining = 0; - bool forceMining = false; - bool mineOnWrongChain = false; - Address signingKey; - Address sessionKey; - Address beneficiary = signingKey; - - /// Structured logging params - bool structuredLogging = false; - string structuredLoggingFormat = "%Y-%m-%dT%H:%M:%S"; - string structuredLoggingURL; - - /// Transaction params - TransactionPriority priority = TransactionPriority::Medium; -// double etherPrice = 30.679; -// double blockFees = 15.0; - u256 askPrice("500000000000"); - u256 bidPrice("500000000000"); - - // javascript console - bool useConsole = false; - - /// Wallet password stuff - string masterPassword; - - string configFile = getDataDir() + "/config.rlp"; - bytes b = contents(configFile); - - strings passwordsToNote; - Secrets toImport; - if (b.size()) + additional = "Press Enter"; + string l; + while (!g_exit) { - RLP config(b); - if (config[0].size() == 32) // secret key - import and forget. + g_silence = false; + cout << logbuf << "Press Enter" << flush; + std::getline(cin, l); + logbuf.clear(); + g_silence = true; + +#if ETH_READLINE + if (l.size()) + add_history(l.c_str()); + if (auto c = readline("> ")) { - Secret s = config[0].toHash(); - toImport.push_back(s); + l = c; + free(c); } - else // new format - just use it as an address. - signingKey = config[0].toHash
(); - beneficiary = config[1].toHash
(); - } - - MinerCLI m(MinerCLI::OperationMode::None); - - for (int i = 1; i < argc; ++i) - { - string arg = argv[i]; - if (m.interpretOption(i, argc, argv)) {} - else if (arg == "--listen-ip" && i + 1 < argc) - listenIP = argv[++i]; - else if ((arg == "-l" || arg == "--listen" || arg == "--listen-port") && i + 1 < argc) + else + break; +#else + string l; + cout << "> " << flush; + std::getline(cin, l); +#endif + istringstream iss(l); + string cmd; + iss >> cmd; + boost::to_lower(cmd); + if (cmd == "netstart") { - if (arg == "-l") - cerr << "-l is DEPRECATED. It will be removed for the Frontier. Use --listen-port instead." << endl; - listenPort = (short)atoi(argv[++i]); + iss >> netPrefs.listenPort; + web3.setNetworkPreferences(netPrefs); + web3.startNetwork(); } - else if ((arg == "-u" || arg == "--public-ip" || arg == "--public") && i + 1 < argc) + else if (cmd == "connect") { - if (arg == "-u") - cerr << "-u is DEPRECATED. It will be removed for the Frontier. Use --public-ip instead." << endl; - publicIP = argv[++i]; + string addrPort; + iss >> addrPort; + web3.addNode(p2p::NodeId(), addrPort); } - else if ((arg == "-r" || arg == "--remote") && i + 1 < argc) - remoteHost = argv[++i]; - else if ((arg == "-p" || arg == "--port") && i + 1 < argc) + else if (cmd == "netstop") + web3.stopNetwork(); + else if (c && cmd == "minestart") + c->startMining(); + else if (c && cmd == "minestop") + c->stopMining(); + else if (c && cmd == "mineforce") { - if (arg == "-p") - cerr << "-p is DEPRECATED. It will be removed for the Frontier. Use --port instead (or place directly as host:port)." << endl; - remotePort = (short)atoi(argv[++i]); + string enable; + iss >> enable; + c->setForceMining(isTrue(enable)); } - else if (arg == "--password" && i + 1 < argc) - passwordsToNote.push_back(argv[++i]); - else if (arg == "--master" && i + 1 < argc) - masterPassword = argv[++i]; - else if ((arg == "-I" || arg == "--import") && i + 1 < argc) + else if (cmd == "verbosity") { - mode = OperationMode::Import; - filename = argv[++i]; + if (iss.peek() != -1) + iss >> g_logVerbosity; + cout << "Verbosity: " << g_logVerbosity << endl; } - else if (arg == "--dont-check") - safeImport = true; - else if ((arg == "-E" || arg == "--export") && i + 1 < argc) + else if (cmd == "address") { - mode = OperationMode::Export; - filename = argv[++i]; + cout << "Current mining beneficiary:" << endl << beneficiary << endl; + cout << "Current signing account:" << endl << signingKey << endl; } - else if (arg == "--prime" && i + 1 < argc) - try - { - prime = stoi(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } - else if (arg == "--yes-i-really-know-what-im-doing") - yesIReallyKnowWhatImDoing = true; - else if (arg == "--sentinel" && i + 1 < argc) - sentinel = argv[++i]; - else if (arg == "--mine-on-wrong-chain") - mineOnWrongChain = true; - else if (arg == "--format" && i + 1 < argc) + else if (c && cmd == "blockhashfromnumber") { - string m = argv[++i]; - if (m == "binary") - exportFormat = Format::Binary; - else if (m == "hex") - exportFormat = Format::Hex; - else if (m == "human") - exportFormat = Format::Human; - else + if (iss.peek() != -1) { - cerr << "Bad " << arg << " option: " << m << endl; - return -1; + unsigned number; + iss >> number; + cout << " hash of block: " << c->hashFromNumber(number).hex() << endl; } } - else if (arg == "--to" && i + 1 < argc) - exportTo = argv[++i]; - else if (arg == "--from" && i + 1 < argc) - exportFrom = argv[++i]; - else if (arg == "--only" && i + 1 < argc) - exportTo = exportFrom = argv[++i]; - else if ((arg == "-n" || arg == "-u" || arg == "--upnp") && i + 1 < argc) + else if (c && cmd == "numberfromblockhash") { - if (arg == "-n") - cerr << "-n is DEPRECATED. It will be removed for the Frontier. Use --upnp instead." << endl; - string m = argv[++i]; - if (isTrue(m)) - upnp = true; - else if (isFalse(m)) - upnp = false; - else + if (iss.peek() != -1) { - cerr << "Bad " << arg << " option: " << m << endl; - return -1; + string stringHash; + iss >> stringHash; + + h256 hash = h256(fromHex(stringHash)); + cout << " number of block: " << c->numberFromHash(hash) << endl; } } - else if (arg == "--network-id" && i + 1 < argc) - try { - networkId = stol(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } - else if (arg == "-K" || arg == "--kill-blockchain" || arg == "--kill") - killChain = WithExisting::Kill; - else if (arg == "-R" || arg == "--rebuild") - killChain = WithExisting::Verify; - else if ((arg == "-c" || arg == "--client-name") && i + 1 < argc) + else if (c && cmd == "block") + cout << "Current block: " << c->blockChain().details().number << endl; + else if (c && cmd == "blockqueue") + cout << "Current blockqueue status: " << endl << c->blockQueueStatus() << endl; + else if (c && cmd == "hashrate") + cout << "Current hash rate: " << toString(c->hashrate()) << " hashes per second." << endl; + else if (c && cmd == "findblock") { - if (arg == "-c") - cerr << "-c is DEPRECATED. It will be removed for the Frontier. Use --client-name instead." << endl; - clientName = argv[++i]; - } - else if ((arg == "-a" || arg == "--address" || arg == "--coinbase-address") && i + 1 < argc) - try { - beneficiary = h160(fromHex(argv[++i], WhenError::Throw)); - } - catch (BadHexCharacter&) - { - cerr << "Bad hex in " << arg << " option: " << argv[i] << endl; - return -1; - } - catch (...) + if (iss.peek() != -1) { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; + string stringHash; + iss >> stringHash; + + h256 hash = h256(fromHex(stringHash)); + + // search in blockchain + cout << "search in blockchain... " << endl; + try + { + cout << c->blockInfo(hash) << endl; + } + catch(Exception& _e) + { + cout << "block not in blockchain" << endl; + cout << boost::diagnostic_information(_e) << endl; + } + + cout << "search in blockqueue... " << endl; + + switch(c->blockQueue().blockStatus(hash)) + { + case QueueStatus::Ready: + cout << "Ready" << endl; + break; + case QueueStatus::Importing: + cout << "Importing" << endl; + break; + case QueueStatus::UnknownParent: + cout << "UnknownParent" << endl; + break; + case QueueStatus::Bad: + cout << "Bad" << endl; + break; + case QueueStatus::Unknown: + cout << "Unknown" << endl; + break; + default: + cout << "invalid queueStatus" << endl; + } } - else if ((arg == "-s" || arg == "--import-secret") && i + 1 < argc) - { - Secret s(fromHex(argv[++i])); - toImport.push_back(s); - signingKey = toAddress(s); - } - else if ((arg == "-S" || arg == "--import-session-secret") && i + 1 < argc) - { - Secret s(fromHex(argv[++i])); - toImport.push_back(s); - sessionKey = toAddress(s); + else + cwarn << "Require parameter: findblock HASH"; } - else if ((arg == "--sign-key") && i + 1 < argc) - sessionKey = Address(fromHex(argv[++i])); - else if ((arg == "--session-sign-key") && i + 1 < argc) - sessionKey = Address(fromHex(argv[++i])); - else if (arg == "--structured-logging-format" && i + 1 < argc) - structuredLoggingFormat = string(argv[++i]); - else if (arg == "--structured-logging") - structuredLogging = true; - else if (arg == "--structured-logging-url" && i + 1 < argc) + else if (c && cmd == "firstunknown") + cout << "first unknown blockhash: " << c->blockQueue().firstUnknown().hex() << endl; + else if (c && cmd == "retryunknown") + c->retryUnknown(); + else if (cmd == "peers") { - structuredLogging = true; - structuredLoggingURL = argv[++i]; + for (auto it: web3.peers()) + cout << it.host << ":" << it.port << ", " << it.clientVersion << ", " + << std::chrono::duration_cast(it.lastPing).count() << "ms" + << endl; } - else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc) - dbPath = argv[++i]; - else if (arg == "--genesis-nonce" && i + 1 < argc) + else if (cmd == "newaccount") { - try + string name; + std::getline(iss, name); + auto s = Secret::random(); + string password; + while (password.empty()) { - CanonBlockChain::setGenesisNonce(Nonce(argv[++i])); + password = getPassword("Please enter a password to protect this key (press enter for protection only be the MASTER password/keystore): "); + string confirm = getPassword("Please confirm the password by entering it again: "); + if (password != confirm) + { + cout << "Passwords were different. Try again." << endl; + password.clear(); + } } - catch (...) + if (!password.empty()) { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; + cout << "Enter a hint for this password: " << flush; + string hint; + std::getline(cin, hint); + keyManager.import(s, name, password, hint); } + else + keyManager.import(s, name); + cout << "New account created: " << toAddress(s); } -/* else if ((arg == "-B" || arg == "--block-fees") && i + 1 < argc) + else if (c && cmd == "accounts") { - try + cout << "Accounts:" << endl; + u256 total = 0; + for (auto const& address: keyManager.accounts()) { - blockFees = stof(argv[++i]); + auto b = c->balanceAt(address); + cout << ((address == signingKey) ? "SIGNING " : " ") << ((address == beneficiary) ? "COINBASE " : " ") << keyManager.accountName(address) << " (" << address << "): " << formatBalance(b) << " = " << b << " wei" << endl; + total += b; } - catch (...) + cout << "Total: " << formatBalance(total) << " = " << total << " wei" << endl; + } + else if (c && cmd == "transact") + { + auto const& bc =c->blockChain(); + auto h = bc.currentHash(); + auto blockData = bc.block(h); + BlockInfo info(blockData); + if (iss.peek() != -1) { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; + string hexAddr; + u256 amount; + u256 gasPrice; + u256 gas; + string sechex; + string sdata; + + iss >> hexAddr >> amount >> gasPrice >> gas >> sechex >> sdata; + + if (!gasPrice) + gasPrice = gasPricer->bid(priority); + + cnote << "Data:"; + cnote << sdata; + bytes data = dev::eth::parseData(sdata); + cnote << "Bytes:"; + string sbd = asString(data); + bytes bbd = asBytes(sbd); + stringstream ssbd; + ssbd << bbd; + cnote << ssbd.str(); + int ssize = sechex.length(); + int size = hexAddr.length(); + u256 minGas = (u256)Transaction::gasRequired(data, 0); + if (size < 40) + { + if (size > 0) + cwarn << "Invalid address length:" << size; + } + else if (gas < minGas) + cwarn << "Minimum gas amount is" << minGas; + else if (ssize < 40) + { + if (ssize > 0) + cwarn << "Invalid secret length:" << ssize; + } + else + { + try + { + Secret secret = h256(fromHex(sechex)); + Address dest = h160(fromHex(hexAddr)); + c->submitTransaction(secret, amount, dest, data, gas, gasPrice); + } + catch (BadHexCharacter& _e) + { + cwarn << "invalid hex character, transaction rejected"; + cwarn << boost::diagnostic_information(_e); + } + catch (...) + { + cwarn << "transaction rejected"; + } + } } + else + cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA"; } - else if ((arg == "-e" || arg == "--ether-price") && i + 1 < argc) + + else if (c && cmd == "transactnonce") { - try + auto const& bc =c->blockChain(); + auto h = bc.currentHash(); + auto blockData = bc.block(h); + BlockInfo info(blockData); + if (iss.peek() != -1) { - etherPrice = stof(argv[++i]); + string hexAddr; + u256 amount; + u256 gasPrice; + u256 gas; + string sechex; + string sdata; + u256 nonce; + + iss >> hexAddr >> amount >> gasPrice >> gas >> sechex >> sdata >> nonce; + + if (!gasPrice) + gasPrice = gasPricer->bid(priority); + + cnote << "Data:"; + cnote << sdata; + bytes data = dev::eth::parseData(sdata); + cnote << "Bytes:"; + string sbd = asString(data); + bytes bbd = asBytes(sbd); + stringstream ssbd; + ssbd << bbd; + cnote << ssbd.str(); + int ssize = sechex.length(); + int size = hexAddr.length(); + u256 minGas = (u256)Transaction::gasRequired(data, 0); + if (size < 40) + { + if (size > 0) + cwarn << "Invalid address length:" << size; + } + else if (gas < minGas) + cwarn << "Minimum gas amount is" << minGas; + else if (ssize < 40) + { + if (ssize > 0) + cwarn << "Invalid secret length:" << ssize; + } + else + { + try + { + Secret secret = h256(fromHex(sechex)); + Address dest = h160(fromHex(hexAddr)); + c->submitTransaction(secret, amount, dest, data, gas, gasPrice, nonce); + } + catch (BadHexCharacter& _e) + { + cwarn << "invalid hex character, transaction rejected"; + cwarn << boost::diagnostic_information(_e); + } + catch (...) + { + cwarn << "transaction rejected"; + } + } } - catch (...) + else + cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA NONCE"; + } + + else if (c && cmd == "txcreate") + { + auto const& bc =c->blockChain(); + auto h = bc.currentHash(); + auto blockData = bc.block(h); + BlockInfo info(blockData); + if (iss.peek() != -1) { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; + u256 amount; + u256 gasPrice; + u256 gas; + string sechex; + string sdata; + + iss >> amount >> gasPrice >> gas >> sechex >> sdata; + + if (!gasPrice) + gasPrice = gasPricer->bid(priority); + + cnote << "Data:"; + cnote << sdata; + bytes data = dev::eth::parseData(sdata); + cnote << "Bytes:"; + string sbd = asString(data); + bytes bbd = asBytes(sbd); + stringstream ssbd; + ssbd << bbd; + cnote << ssbd.str(); + int ssize = sechex.length(); + u256 minGas = (u256)Transaction::gasRequired(data, 0); + if (gas < minGas) + cwarn << "Minimum gas amount is" << minGas; + else if (ssize < 40) + { + if (ssize > 0) + cwarn << "Invalid secret length:" << ssize; + } + else + { + try + { + Secret secret = h256(fromHex(sechex)); + cout << " new contract address : " << c->submitTransaction(secret, amount, data, gas, gasPrice) << endl; + } + catch (BadHexCharacter& _e) + { + cwarn << "invalid hex character, transaction rejected"; + cwarn << boost::diagnostic_information(_e); + } + catch (...) + { + cwarn << "transaction rejected"; + } + } } - }*/ - else if (arg == "--ask" && i + 1 < argc) + else + cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET INIT"; + } +#if ETH_FATDB + else if (c && cmd == "listcontracts") { - try + auto acs =c->addresses(); + string ss; + for (auto const& i: acs) + if ( c->codeAt(i, PendingBlock).size()) + { + ss = toString(i) + " : " + toString( c->balanceAt(i)) + " [" + toString((unsigned) c->countAt(i)) + "]"; + cout << ss << endl; + } + } + else if (c && cmd == "listaccounts") + { + auto acs =c->addresses(); + string ss; + for (auto const& i: acs) + if ( c->codeAt(i, PendingBlock).empty()) + { + ss = toString(i) + " : " + toString( c->balanceAt(i)) + " [" + toString((unsigned) c->countAt(i)) + "]"; + cout << ss << endl; + } + } + else if (c && cmd == "balanceat") + { + if (iss.peek() != -1) { - askPrice = u256(argv[++i]); + string stringHash; + iss >> stringHash; + + Address address = h160(fromHex(stringHash)); + + cout << "balance of " << stringHash << " is: " << toString(c->balanceAt(address)) << endl; } - catch (...) + } + else if (c && cmd == "balanceatblock") + { + if (iss.peek() != -1) { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; + string stringHash; + unsigned blocknumber; + iss >> stringHash >> blocknumber; + + Address address = h160(fromHex(stringHash)); + + cout << "balance of " << stringHash << " is: " << toString(c->balanceAt(address, blocknumber)) << endl; } } - else if (arg == "--bid" && i + 1 < argc) + else if (c && cmd == "storageat") { - try + if (iss.peek() != -1) { - bidPrice = u256(argv[++i]); + string stringHash; + iss >> stringHash; + + Address address = h160(fromHex(stringHash)); + + cout << "storage at " << stringHash << " is: " << endl; + for (auto s: c->storageAt(address)) + cout << toHex(s.first) << " : " << toHex(s.second) << endl; } - catch (...) + } + else if (c && cmd == "storageatblock") + { + if (iss.peek() != -1) { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; + string stringHash; + unsigned blocknumber; + iss >> stringHash >> blocknumber; + + Address address = h160(fromHex(stringHash)); + + cout << "storage at " << stringHash << " is: " << endl; + for (auto s: c->storageAt(address, blocknumber)) + cout << "\"0x" << toHex(s.first) << "\" : \"0x" << toHex(s.second) << "\"," << endl; } } - else if ((arg == "-P" || arg == "--priority") && i + 1 < argc) + else if (c && cmd == "codeat") { - string m = boost::to_lower_copy(string(argv[++i])); - if (m == "lowest") - priority = TransactionPriority::Lowest; - else if (m == "low") - priority = TransactionPriority::Low; - else if (m == "medium" || m == "mid" || m == "default" || m == "normal") - priority = TransactionPriority::Medium; - else if (m == "high") - priority = TransactionPriority::High; - else if (m == "highest") - priority = TransactionPriority::Highest; + if (iss.peek() != -1) + { + string stringHash; + iss >> stringHash; + + Address address = h160(fromHex(stringHash)); + + cout << "code at " << stringHash << " is: " << toHex(c->codeAt(address)) << endl; + } + } +#endif + + else if (c && cmd == "send") + { + if (iss.peek() != -1) + { + string hexAddr; + u256 amount; + + iss >> hexAddr >> amount; + int size = hexAddr.length(); + if (size < 40) + { + if (size > 0) + cwarn << "Invalid address length:" << size; + } + else + { + auto const& bc =c->blockChain(); + auto h = bc.currentHash(); + auto blockData = bc.block(h); + BlockInfo info(blockData); + u256 minGas = (u256)Transaction::gasRequired(bytes(), 0); + try + { + Address dest = h160(fromHex(hexAddr, WhenError::Throw)); + c->submitTransaction(keyManager.secret(signingKey, [&](){ return getAccountPassword(signingKey); }), amount, dest, bytes(), minGas); + } + catch (BadHexCharacter& _e) + { + cwarn << "invalid hex character, transaction rejected"; + cwarn << boost::diagnostic_information(_e); + } + catch (...) + { + cwarn << "transaction rejected"; + } + } + } else - try { - priority = (TransactionPriority)(max(0, min(100, stoi(m))) * 8 / 100); + cwarn << "Require parameters: send ADDRESS AMOUNT"; + } + else if (c && cmd == "contract") + { + auto const& bc =c->blockChain(); + auto h = bc.currentHash(); + auto blockData = bc.block(h); + BlockInfo info(blockData); + if (iss.peek() != -1) + { + u256 endowment; + u256 gas; + u256 gasPrice; + string sinit; + iss >> endowment >> gasPrice >> gas >> sinit; + trim_all(sinit); + int size = sinit.length(); + bytes init; + cnote << "Init:"; + cnote << sinit; + cnote << "Code size:" << size; + if (size < 1) + cwarn << "No code submitted"; + else + { + cnote << "Assembled:"; + stringstream ssc; + try + { + init = fromHex(sinit, WhenError::Throw); + } + catch (BadHexCharacter& _e) + { + cwarn << "invalid hex character, code rejected"; + cwarn << boost::diagnostic_information(_e); + init = bytes(); + } + catch (...) + { + cwarn << "code rejected"; + init = bytes(); + } + ssc.str(string()); + ssc << disassemble(init); + cnote << "Init:"; + cnote << ssc.str(); } - catch (...) { - cerr << "Unknown " << arg << " option: " << m << endl; - return -1; + u256 minGas = (u256)Transaction::gasRequired(init, 0); + if (!init.size()) + cwarn << "Contract creation aborted, no init code."; + else if (endowment < 0) + cwarn << "Invalid endowment"; + else if (gas < minGas) + cwarn << "Minimum gas amount is" << minGas; + else + c->submitTransaction(keyManager.secret(signingKey, [&](){ return getAccountPassword(signingKey); }), endowment, init, gas, gasPrice); + } + else + cwarn << "Require parameters: contract ENDOWMENT GASPRICE GAS CODEHEX"; + } + else if (c && cmd == "dumpreceipt") + { + unsigned block; + unsigned index; + iss >> block >> index; + dev::eth::TransactionReceipt r = c->blockChain().receipts(c->blockChain().numberHash(block)).receipts[index]; + auto rb = r.rlp(); + cout << "RLP: " << RLP(rb) << endl; + cout << "Hex: " << toHex(rb) << endl; + cout << r << endl; + } + else if (c && cmd == "reprocess") + { + string block; + iss >> block; + h256 blockHash; + try + { + if (block.size() == 64 || block.size() == 66) + blockHash = h256(block); + else + blockHash = c->blockChain().numberHash(stoi(block)); + c->state(blockHash); + } + catch (...) + {} + } + else if (c && cmd == "dumptrace") + { + unsigned block; + unsigned index; + string filename; + string format; + iss >> block >> index >> filename >> format; + ofstream f; + f.open(filename); + + dev::eth::State state = c->state(index + 1,c->blockChain().numberHash(block)); + if (index < state.pending().size()) + { + Executive e(state, c->blockChain(), 0); + Transaction t = state.pending()[index]; + state = state.fromPending(index); + try + { + OnOpFunc oof; + if (format == "pretty") + oof = [&](uint64_t steps, Instruction instr, bigint newMemSize, bigint gasCost, bigint gas, dev::eth::VM* vvm, dev::eth::ExtVMFace const* vextVM) + { + dev::eth::VM* vm = vvm; + dev::eth::ExtVM const* ext = static_cast(vextVM); + f << endl << " STACK" << endl; + for (auto i: vm->stack()) + f << (h256)i << endl; + f << " MEMORY" << endl << dev::memDump(vm->memory()); + f << " STORAGE" << endl; + for (auto const& i: ext->state().storage(ext->myAddress)) + f << showbase << hex << i.first << ": " << i.second << endl; + f << dec << ext->depth << " | " << ext->myAddress << " | #" << steps << " | " << hex << setw(4) << setfill('0') << vm->curPC() << " : " << dev::eth::instructionInfo(instr).name << " | " << dec << gas << " | -" << dec << gasCost << " | " << newMemSize << "x32"; + }; + else if (format == "standard") + oof = [&](uint64_t, Instruction instr, bigint, bigint, bigint gas, dev::eth::VM* vvm, dev::eth::ExtVMFace const* vextVM) + { + dev::eth::VM* vm = vvm; + dev::eth::ExtVM const* ext = static_cast(vextVM); + f << ext->myAddress << " " << hex << toHex(dev::toCompactBigEndian(vm->curPC(), 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)instr, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)gas, 1)) << endl; + }; + else if (format == "standard+") + oof = [&](uint64_t, Instruction instr, bigint, bigint, bigint gas, dev::eth::VM* vvm, dev::eth::ExtVMFace const* vextVM) + { + dev::eth::VM* vm = vvm; + dev::eth::ExtVM const* ext = static_cast(vextVM); + if (instr == Instruction::STOP || instr == Instruction::RETURN || instr == Instruction::SUICIDE) + for (auto const& i: ext->state().storage(ext->myAddress)) + f << toHex(dev::toCompactBigEndian(i.first, 1)) << " " << toHex(dev::toCompactBigEndian(i.second, 1)) << endl; + f << ext->myAddress << " " << hex << toHex(dev::toCompactBigEndian(vm->curPC(), 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)instr, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)gas, 1)) << endl; + }; + e.initialize(t); + if (!e.execute()) + e.go(oof); + e.finalize(); + } + catch(Exception const& _e) + { + // TODO: a bit more information here. this is probably quite worrying as the transaction is already in the blockchain. + cwarn << diagnostic_information(_e); } + } } - else if ((arg == "-m" || arg == "--mining") && i + 1 < argc) + else if (c && cmd == "inspect") { - string m = argv[++i]; - if (isTrue(m)) - mining = ~(unsigned)0; - else if (isFalse(m)) - mining = 0; + string rechex; + iss >> rechex; + + if (rechex.length() != 40) + cwarn << "Invalid address length"; else - try { - mining = stoi(m); + { + auto h = h160(fromHex(rechex)); + stringstream s; + + try + { + auto storage =c->storageAt(h, PendingBlock); + for (auto const& i: storage) + s << "@" << showbase << hex << i.first << " " << showbase << hex << i.second << endl; + s << endl << disassemble( c->codeAt(h, PendingBlock)) << endl; + + string outFile = getDataDir() + "/" + rechex + ".evm"; + ofstream ofs; + ofs.open(outFile, ofstream::binary); + ofs.write(s.str().c_str(), s.str().length()); + ofs.close(); + + cnote << "Saved" << rechex << "to" << outFile; } - catch (...) { - cerr << "Unknown " << arg << " option: " << m << endl; - return -1; + catch (dev::InvalidTrie) + { + cwarn << "Corrupted trie."; } + } } - else if (arg == "-b" || arg == "--bootstrap") - bootstrap = true; - else if (arg == "--no-discovery") - disableDiscovery = true; - else if (arg == "--pin") - pinning = true; - else if (arg == "-f" || arg == "--force-mining") - forceMining = true; - else if (arg == "-i" || arg == "--interactive") - interactive = true; -#if ETH_JSONRPC - else if ((arg == "-j" || arg == "--json-rpc")) - jsonrpc = jsonrpc == -1 ? SensibleHttpPort : jsonrpc; - else if (arg == "--json-rpc-port" && i + 1 < argc) - jsonrpc = atoi(argv[++i]); - else if (arg == "--json-admin" && i + 1 < argc) - jsonAdmin = argv[++i]; -#endif -#if ETH_JSCONSOLE - else if (arg == "--console") - useConsole = true; -#endif - else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc) - g_logVerbosity = atoi(argv[++i]); - else if ((arg == "-x" || arg == "--peers") && i + 1 < argc) - peers = atoi(argv[++i]); - else if ((arg == "-o" || arg == "--mode") && i + 1 < argc) + else if (cmd == "setsigningkey") { - string m = argv[++i]; - if (m == "full") - nodeMode = NodeMode::Full; - else if (m == "peer") - nodeMode = NodeMode::PeerServer; + if (iss.peek() != -1) + { + string hexSec; + iss >> hexSec; + signingKey = Address(fromHex(hexSec)); + } else + cwarn << "Require parameter: setSecret HEXSECRETKEY"; + } + else if (cmd == "setaddress") + { + if (iss.peek() != -1) { - cerr << "Unknown mode: " << m << endl; - return -1; + string hexAddr; + iss >> hexAddr; + if (hexAddr.length() != 40) + cwarn << "Invalid address length: " << hexAddr.length(); + else + { + try + { + beneficiary = h160(fromHex(hexAddr, WhenError::Throw)); + } + catch (BadHexCharacter& _e) + { + cwarn << "invalid hex character, coinbase rejected"; + cwarn << boost::diagnostic_information(_e); + } + catch (...) + { + cwarn << "coinbase rejected"; + } + } } + else + cwarn << "Require parameter: setAddress HEXADDRESS"; } -#if ETH_EVMJIT - else if (arg == "-J" || arg == "--jit") - jit = true; -#endif - else if (arg == "-h" || arg == "--help") - help(); - else if (arg == "-V" || arg == "--version") - version(); - else + else if (cmd == "exportconfig") { - cerr << "Invalid argument: " << arg << endl; - exit(-1); + if (iss.peek() != -1) + { + string path; + iss >> path; + RLPStream config(2); + config << signingKey << beneficiary; + writeFile(path, config.out()); + } + else + cwarn << "Require parameter: exportConfig PATH"; } + else if (cmd == "importconfig") + { + if (iss.peek() != -1) + { + string path; + iss >> path; + bytes b = contents(path); + if (b.size()) + { + RLP config(b); + signingKey = config[0].toHash
(); + beneficiary = config[1].toHash
(); + } + else + cwarn << path << "has no content!"; + } + else + cwarn << "Require parameter: importConfig PATH"; + } + else if (cmd == "help") + interactiveHelp(); + else if (cmd == "exit") + break; + else + cout << "Unrecognised command. Type 'help' for help in interactive mode." << endl; } +} - m.execute(); - - KeyManager keyManager; - for (auto const& s: passwordsToNote) - keyManager.notePassword(s); - - { - RLPStream config(2); - config << signingKey << beneficiary; - writeFile(configFile, config.out()); - } - - if (sessionKey) - signingKey = sessionKey; - - if (!clientName.empty()) - clientName += "/"; +int main(int argc, char** argv) +{ + // Init defaults + Defaults::get(); - string logbuf; - std::string additional; - if (interactive) - g_logPost = [&](std::string const& a, char const*){ - static SpinLock s_lock; - SpinGuard l(s_lock); - - if (g_silence) - logbuf += a + "\n"; - else - cout << "\r \r" << a << endl << additional << flush; + /// Operating mode. + OperationMode mode = OperationMode::Node; + string dbPath; + unsigned prime = 0; + bool yesIReallyKnowWhatImDoing = false; - // helpful to use OutputDebugString on windows - #ifdef _WIN32 - { - OutputDebugStringA(a.data()); - OutputDebugStringA("\n"); - } - #endif - }; + /// File name for import/export. + string filename; + bool safeImport = false; - auto getPassword = [&](string const& prompt){ - auto s = g_silence; - g_silence = true; - cout << endl; - string ret = dev::getPassword(prompt); - g_silence = s; - return ret; - }; - auto getAccountPassword = [&](Address const& a){ - return getPassword("Enter password for address " + keyManager.accountName(a) + " (" + a.abridged() + "; hint:" + keyManager.passwordHint(a) + "): "); - }; + /// Hashes/numbers for export range. + string exportFrom = "1"; + string exportTo = "latest"; + Format exportFormat = Format::Binary; - StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat, structuredLoggingURL); - VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter); - auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp); - netPrefs.discovery = !disableDiscovery; - netPrefs.pin = pinning; - auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp"); - dev::WebThreeDirect web3( - WebThreeDirect::composeClientVersion("++eth", clientName), - dbPath, - killChain, - nodeMode == NodeMode::Full ? set{"eth"/*, "shh"*/} : set(), - netPrefs, - &nodesState); - web3.ethereum()->setMineOnBadChain(mineOnWrongChain); - web3.ethereum()->setSentinel(sentinel); + /// General params for Node operation + NodeMode nodeMode = NodeMode::Full; + bool interactive = false; +#if ETH_JSONRPC + int jsonrpc = -1; +#endif + string jsonAdmin; + bool upnp = true; + WithExisting killChain = WithExisting::Trust; + bool jit = false; + string sentinel; - auto toNumber = [&](string const& s) -> unsigned { - if (s == "latest") - return web3.ethereum()->number(); - if (s.size() == 64 || (s.size() == 66 && s.substr(0, 2) == "0x")) - return web3.ethereum()->blockChain().number(h256(s)); - try { - return stol(s); - } - catch (...) - { - cerr << "Bad block number/hash option: " << s << endl; - exit(-1); - } - }; + /// Networking params. + string clientName; + string listenIP; + unsigned short listenPort = 30303; + string publicIP; + string remoteHost; + unsigned short remotePort = 30303; + unsigned peers = 11; + bool bootstrap = false; + bool disableDiscovery = false; + bool pinning = false; + unsigned networkId = 0; - if (mode == OperationMode::Export) - { - ofstream fout(filename, std::ofstream::binary); - ostream& out = (filename.empty() || filename == "--") ? cout : fout; + /// Mining params + unsigned mining = 0; + bool forceMining = false; + bool mineOnWrongChain = false; + Address signingKey; + Address sessionKey; + Address beneficiary = signingKey; - unsigned last = toNumber(exportTo); - for (unsigned i = toNumber(exportFrom); i <= last; ++i) - { - bytes block = web3.ethereum()->blockChain().block(web3.ethereum()->blockChain().numberHash(i)); - switch (exportFormat) - { - case Format::Binary: out.write((char const*)block.data(), block.size()); break; - case Format::Hex: out << toHex(block) << endl; break; - case Format::Human: out << RLP(block) << endl; break; - default:; - } - } - return 0; - } + /// Structured logging params + bool structuredLogging = false; + string structuredLoggingFormat = "%Y-%m-%dT%H:%M:%S"; + string structuredLoggingURL; - if (mode == OperationMode::Import) - { - ifstream fin(filename, std::ifstream::binary); - istream& in = (filename.empty() || filename == "--") ? cin : fin; - unsigned alreadyHave = 0; - unsigned good = 0; - unsigned futureTime = 0; - unsigned unknownParent = 0; - unsigned bad = 0; - chrono::steady_clock::time_point t = chrono::steady_clock::now(); - double last = 0; - unsigned lastImported = 0; - unsigned imported = 0; - while (in.peek() != -1) - { - bytes block(8); - in.read((char*)block.data(), 8); - block.resize(RLP(block, RLP::LaissezFaire).actualSize()); - in.read((char*)block.data() + 8, block.size() - 8); + /// Transaction params + TransactionPriority priority = TransactionPriority::Medium; +// double etherPrice = 30.679; +// double blockFees = 15.0; + u256 askPrice("500000000000"); + u256 bidPrice("500000000000"); - switch (web3.ethereum()->queueBlock(block, safeImport)) - { - case ImportResult::Success: good++; break; - case ImportResult::AlreadyKnown: alreadyHave++; break; - case ImportResult::UnknownParent: unknownParent++; break; - case ImportResult::FutureTimeUnknown: unknownParent++; futureTime++; break; - case ImportResult::FutureTimeKnown: futureTime++; break; - default: bad++; break; - } + // javascript console + bool useConsole = false; - // sync chain with queue - tuple r = web3.ethereum()->syncQueue(10); - imported += get<2>(r); + /// Wallet password stuff + string masterPassword; - double e = chrono::duration_cast(chrono::steady_clock::now() - t).count() / 1000.0; - if ((unsigned)e >= last + 10) - { - auto i = imported - lastImported; - auto d = e - last; - cout << i << " more imported at " << (round(i * 10 / d) / 10) << " blocks/s. " << imported << " imported in " << e << " seconds at " << (round(imported * 10 / e) / 10) << " blocks/s (#" << web3.ethereum()->number() << ")" << endl; - last = (unsigned)e; - lastImported = imported; -// cout << web3.ethereum()->blockQueueStatus() << endl; - } - } + string configFile = getDataDir() + "/config.rlp"; + bytes b = contents(configFile); - while (web3.ethereum()->blockQueue().items().first + web3.ethereum()->blockQueue().items().second > 0) + strings passwordsToNote; + Secrets toImport; + if (b.size()) + { + RLP config(b); + if (config[0].size() == 32) // secret key - import and forget. { - this_thread::sleep_for(chrono::seconds(1)); - web3.ethereum()->syncQueue(100000); + Secret s = config[0].toHash(); + toImport.push_back(s); } - double e = chrono::duration_cast(chrono::steady_clock::now() - t).count() / 1000.0; - cout << imported << " imported in " << e << " seconds at " << (round(imported * 10 / e) / 10) << " blocks/s (#" << web3.ethereum()->number() << ")" << endl; - return 0; + else // new format - just use it as an address. + signingKey = config[0].toHash
(); + beneficiary = config[1].toHash
(); } - if (c_network == eth::Network::Frontier && !yesIReallyKnowWhatImDoing) + MinerCLI m(MinerCLI::OperationMode::None); + + for (int i = 1; i < argc; ++i) { - auto pd = contents(getDataDir() + "primes"); - unordered_set primes = RLP(pd).toUnorderedSet(); - while (true) + string arg = argv[i]; + if (m.interpretOption(i, argc, argv)) {} + else if (arg == "--listen-ip" && i + 1 < argc) + listenIP = argv[++i]; + else if ((arg == "-l" || arg == "--listen" || arg == "--listen-port") && i + 1 < argc) { - if (!prime) - try - { - prime = stoi(getPassword("To enter the Frontier, enter a 6 digit prime that you have not entered before: ")); - } - catch (...) {} - if (isPrime(prime) && !primes.count(prime)) - break; - prime = 0; + if (arg == "-l") + cerr << "-l is DEPRECATED. It will be removed for the Frontier. Use --listen-port instead." << endl; + listenPort = (short)atoi(argv[++i]); } - primes.insert(prime); - writeFile(getDataDir() + "primes", rlp(primes)); - } - - if (keyManager.exists()) - { - if (masterPassword.empty() || !keyManager.load(masterPassword)) - while (true) - { - masterPassword = getPassword("Please enter your MASTER password: "); - if (keyManager.load(masterPassword)) - break; - cout << "Password invalid. Try again." << endl; - } - } - else - { - while (masterPassword.empty()) + else if ((arg == "-u" || arg == "--public-ip" || arg == "--public") && i + 1 < argc) { - masterPassword = getPassword("Please enter a MASTER password to protect your key store (make it strong!): "); - string confirm = getPassword("Please confirm the password by entering it again: "); - if (masterPassword != confirm) - { - cout << "Passwords were different. Try again." << endl; - masterPassword.clear(); - } + if (arg == "-u") + cerr << "-u is DEPRECATED. It will be removed for the Frontier. Use --public-ip instead." << endl; + publicIP = argv[++i]; } - keyManager.create(masterPassword); - } - - for (auto const& s: toImport) - { - keyManager.import(s, "Imported key (UNSAFE)"); - if (!signingKey) - signingKey = toAddress(s); - } - - if (keyManager.accounts().empty()) - keyManager.import(Secret::random(), "Default key"); - - cout << ethCredits(); - web3.setIdealPeerCount(peers); -// std::shared_ptr gasPricer = make_shared(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000)); - std::shared_ptr gasPricer = make_shared(askPrice, bidPrice); - eth::Client* c = nodeMode == NodeMode::Full ? web3.ethereum() : nullptr; - StructuredLogger::starting(WebThreeDirect::composeClientVersion("++eth", clientName), dev::Version); - if (c) - { - c->setGasPricer(gasPricer); - c->setForceMining(forceMining); - c->setTurboMining(m.minerType() == MinerCLI::MinerType::GPU); - c->setAddress(beneficiary); - c->setNetworkId(networkId); - } - - cout << "Transaction Signer: " << signingKey << endl; - cout << "Mining Benefactor: " << beneficiary << endl; - - if (bootstrap || !remoteHost.empty()) - { - web3.startNetwork(); - cout << "Node ID: " << web3.enode() << endl; - } - else - cout << "Networking disabled. To start, use netstart or pass -b or a remote host." << endl; - -#if ETH_JSONRPC || !ETH_TRUE - shared_ptr jsonrpcServer; - unique_ptr jsonrpcConnector; - if (jsonrpc > -1) - { - jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads)); - jsonrpcServer = shared_ptr(new dev::WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared([&](){ return web3.ethereum(); }, getAccountPassword, keyManager), vector(), keyManager, *gasPricer)); - jsonrpcServer->setMiningBenefactorChanger([&](Address const& a) { beneficiary = a; }); - jsonrpcServer->StartListening(); - if (jsonAdmin.empty()) - jsonAdmin = jsonrpcServer->newSession(SessionPermissions{{Priviledge::Admin}}); - else - jsonrpcServer->addSession(jsonAdmin, SessionPermissions{{Priviledge::Admin}}); - cout << "JSONRPC Admin Session Key: " << jsonAdmin << endl; - } -#endif - - if (bootstrap) - for (auto const& i: Host::pocHosts()) - web3.requirePeer(i.first, i.second); - if (!remoteHost.empty()) - web3.addNode(p2p::NodeId(), remoteHost + ":" + toString(remotePort)); - - signal(SIGABRT, &sighandler); - signal(SIGTERM, &sighandler); - signal(SIGINT, &sighandler); - - if (interactive) - { - additional = "Press Enter"; - string l; - while (!g_exit) + else if ((arg == "-r" || arg == "--remote") && i + 1 < argc) + remoteHost = argv[++i]; + else if ((arg == "-p" || arg == "--port") && i + 1 < argc) { - g_silence = false; - cout << logbuf << "Press Enter" << flush; - std::getline(cin, l); - logbuf.clear(); - g_silence = true; - -#if ETH_READLINE - if (l.size()) - add_history(l.c_str()); - if (auto c = readline("> ")) + if (arg == "-p") + cerr << "-p is DEPRECATED. It will be removed for the Frontier. Use --port instead (or place directly as host:port)." << endl; + remotePort = (short)atoi(argv[++i]); + } + else if (arg == "--password" && i + 1 < argc) + passwordsToNote.push_back(argv[++i]); + else if (arg == "--master" && i + 1 < argc) + masterPassword = argv[++i]; + else if ((arg == "-I" || arg == "--import") && i + 1 < argc) + { + mode = OperationMode::Import; + filename = argv[++i]; + } + else if (arg == "--dont-check") + safeImport = true; + else if ((arg == "-E" || arg == "--export") && i + 1 < argc) + { + mode = OperationMode::Export; + filename = argv[++i]; + } + else if (arg == "--prime" && i + 1 < argc) + try { - l = c; - free(c); + prime = stoi(argv[++i]); } - else - break; -#else - string l; - cout << "> " << flush; - std::getline(cin, l); -#endif - istringstream iss(l); - string cmd; - iss >> cmd; - boost::to_lower(cmd); - if (cmd == "netstart") + catch (...) { - iss >> netPrefs.listenPort; - web3.setNetworkPreferences(netPrefs); - web3.startNetwork(); + cerr << "Bad " << arg << " option: " << argv[i] << endl; + return -1; } - else if (cmd == "connect") + else if (arg == "--yes-i-really-know-what-im-doing") + yesIReallyKnowWhatImDoing = true; + else if (arg == "--sentinel" && i + 1 < argc) + sentinel = argv[++i]; + else if (arg == "--mine-on-wrong-chain") + mineOnWrongChain = true; + else if (arg == "--format" && i + 1 < argc) + { + string m = argv[++i]; + if (m == "binary") + exportFormat = Format::Binary; + else if (m == "hex") + exportFormat = Format::Hex; + else if (m == "human") + exportFormat = Format::Human; + else { - string addrPort; - iss >> addrPort; - web3.addNode(p2p::NodeId(), addrPort); + cerr << "Bad " << arg << " option: " << m << endl; + return -1; } - else if (cmd == "netstop") - web3.stopNetwork(); - else if (c && cmd == "minestart") - c->startMining(); - else if (c && cmd == "minestop") - c->stopMining(); - else if (c && cmd == "mineforce") + } + else if (arg == "--to" && i + 1 < argc) + exportTo = argv[++i]; + else if (arg == "--from" && i + 1 < argc) + exportFrom = argv[++i]; + else if (arg == "--only" && i + 1 < argc) + exportTo = exportFrom = argv[++i]; + else if ((arg == "-n" || arg == "-u" || arg == "--upnp") && i + 1 < argc) + { + if (arg == "-n") + cerr << "-n is DEPRECATED. It will be removed for the Frontier. Use --upnp instead." << endl; + string m = argv[++i]; + if (isTrue(m)) + upnp = true; + else if (isFalse(m)) + upnp = false; + else { - string enable; - iss >> enable; - c->setForceMining(isTrue(enable)); + cerr << "Bad " << arg << " option: " << m << endl; + return -1; } -/* else if (c && cmd == "setblockfees") - { - iss >> blockFees; - try - { - gasPricer->setRefBlockFees(u256(blockFees * 1000)); - } - catch (Overflow const& _e) - { - cout << boost::diagnostic_information(_e); - } - - cout << "Block fees: " << blockFees << endl; + } + else if (arg == "--network-id" && i + 1 < argc) + try { + networkId = stol(argv[++i]); } - else if (c && cmd == "setetherprice") + catch (...) { - iss >> etherPrice; - if (etherPrice == 0) - cout << "ether price cannot be set to zero" << endl; - else - { - try - { - gasPricer->setRefPrice(u256(double(ether / 1000) / etherPrice)); - } - catch (Overflow const& _e) - { - cout << boost::diagnostic_information(_e); - } - } - cout << "ether Price: " << etherPrice << endl; + cerr << "Bad " << arg << " option: " << argv[i] << endl; + return -1; + } + else if (arg == "-K" || arg == "--kill-blockchain" || arg == "--kill") + killChain = WithExisting::Kill; + else if (arg == "-R" || arg == "--rebuild") + killChain = WithExisting::Verify; + else if ((arg == "-c" || arg == "--client-name") && i + 1 < argc) + { + if (arg == "-c") + cerr << "-c is DEPRECATED. It will be removed for the Frontier. Use --client-name instead." << endl; + clientName = argv[++i]; + } + else if ((arg == "-a" || arg == "--address" || arg == "--coinbase-address") && i + 1 < argc) + try { + beneficiary = h160(fromHex(argv[++i], WhenError::Throw)); } - else if (c && cmd == "setpriority") + catch (BadHexCharacter&) { - string m; - iss >> m; - boost::to_lower(m); - if (m == "lowest") - priority = TransactionPriority::Lowest; - else if (m == "low") - priority = TransactionPriority::Low; - else if (m == "medium" || m == "mid" || m == "default" || m == "normal") - priority = TransactionPriority::Medium; - else if (m == "high") - priority = TransactionPriority::High; - else if (m == "highest") - priority = TransactionPriority::Highest; - else - try { - priority = (TransactionPriority)(max(0, min(100, stoi(m))) * 8 / 100); - } - catch (...) { - cerr << "Unknown priority: " << m << endl; - } - cout << "Priority: " << (int)priority << "/8" << endl; - }*/ - else if (cmd == "verbosity") + cerr << "Bad hex in " << arg << " option: " << argv[i] << endl; + return -1; + } + catch (...) { - if (iss.peek() != -1) - iss >> g_logVerbosity; - cout << "Verbosity: " << g_logVerbosity << endl; + cerr << "Bad " << arg << " option: " << argv[i] << endl; + return -1; } -#if ETH_JSONRPC || !ETH_TRUE - else if (cmd == "jsonport") + else if ((arg == "-s" || arg == "--import-secret") && i + 1 < argc) + { + Secret s(fromHex(argv[++i])); + toImport.push_back(s); + signingKey = toAddress(s); + } + else if ((arg == "-S" || arg == "--import-session-secret") && i + 1 < argc) + { + Secret s(fromHex(argv[++i])); + toImport.push_back(s); + sessionKey = toAddress(s); + } + else if ((arg == "--sign-key") && i + 1 < argc) + sessionKey = Address(fromHex(argv[++i])); + else if ((arg == "--session-sign-key") && i + 1 < argc) + sessionKey = Address(fromHex(argv[++i])); + else if (arg == "--structured-logging-format" && i + 1 < argc) + structuredLoggingFormat = string(argv[++i]); + else if (arg == "--structured-logging") + structuredLogging = true; + else if (arg == "--structured-logging-url" && i + 1 < argc) + { + structuredLogging = true; + structuredLoggingURL = argv[++i]; + } + else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc) + dbPath = argv[++i]; + else if (arg == "--genesis-nonce" && i + 1 < argc) + { + try { - if (iss.peek() != -1) - iss >> jsonrpc; - cout << "JSONRPC Port: " << jsonrpc << endl; + CanonBlockChain::setGenesisNonce(Nonce(argv[++i])); } - else if (cmd == "jsonstart") + catch (...) { - if (jsonrpc < 0) - jsonrpc = SensibleHttpPort; - jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads)); - jsonrpcServer = shared_ptr(new dev::WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared([&](){ return web3.ethereum(); }, getAccountPassword, keyManager), vector(), keyManager, *gasPricer)); - jsonrpcServer->setMiningBenefactorChanger([&](Address const& a) { beneficiary = a; }); - jsonrpcServer->StartListening(); - if (jsonAdmin.empty()) - jsonAdmin = jsonrpcServer->newSession(SessionPermissions{{Priviledge::Admin}}); - else - jsonrpcServer->addSession(jsonAdmin, SessionPermissions{{Priviledge::Admin}}); - cout << "JSONRPC Admin Session Key: " << jsonAdmin << endl; + cerr << "Bad " << arg << " option: " << argv[i] << endl; + return -1; } - else if (cmd == "jsonstop") + } +/* else if ((arg == "-B" || arg == "--block-fees") && i + 1 < argc) + { + try { - if (jsonrpcServer.get()) - jsonrpcServer->StopListening(); - jsonrpcServer.reset(); + blockFees = stof(argv[++i]); } -#endif - else if (cmd == "address") + catch (...) { - cout << "Current mining beneficiary:" << endl << beneficiary << endl; - cout << "Current signing account:" << endl << signingKey << endl; + cerr << "Bad " << arg << " option: " << argv[i] << endl; + return -1; } - else if (c && cmd == "blockhashfromnumber") + } + else if ((arg == "-e" || arg == "--ether-price") && i + 1 < argc) + { + try { - if (iss.peek() != -1) - { - unsigned number; - iss >> number; - cout << " hash of block: " << c->hashFromNumber(number).hex() << endl; - } + etherPrice = stof(argv[++i]); } - else if (c && cmd == "numberfromblockhash") + catch (...) { - if (iss.peek() != -1) - { - string stringHash; - iss >> stringHash; - - h256 hash = h256(fromHex(stringHash)); - cout << " number of block: " << c->numberFromHash(hash) << endl; - } + cerr << "Bad " << arg << " option: " << argv[i] << endl; + return -1; } - else if (c && cmd == "block") - cout << "Current block: " << c->blockChain().details().number << endl; - else if (c && cmd == "blockqueue") - cout << "Current blockqueue status: " << endl << c->blockQueueStatus() << endl; - else if (c && cmd == "hashrate") - cout << "Current hash rate: " << toString(c->hashrate()) << " hashes per second." << endl; - else if (c && cmd == "findblock") + }*/ + else if (arg == "--ask" && i + 1 < argc) + { + try { - if (iss.peek() != -1) - { - string stringHash; - iss >> stringHash; - - h256 hash = h256(fromHex(stringHash)); - - // search in blockchain - cout << "search in blockchain... " << endl; - try - { - cout << c->blockInfo(hash) << endl; - } - catch(Exception& _e) - { - cout << "block not in blockchain" << endl; - cout << boost::diagnostic_information(_e) << endl; - } - - cout << "search in blockqueue... " << endl; - - switch(c->blockQueue().blockStatus(hash)) - { - case QueueStatus::Ready: - cout << "Ready" << endl; - break; - case QueueStatus::Importing: - cout << "Importing" << endl; - break; - case QueueStatus::UnknownParent: - cout << "UnknownParent" << endl; - break; - case QueueStatus::Bad: - cout << "Bad" << endl; - break; - case QueueStatus::Unknown: - cout << "Unknown" << endl; - break; - default: - cout << "invalid queueStatus" << endl; - } - } - else - cwarn << "Require parameter: findblock HASH"; + askPrice = u256(argv[++i]); } - else if (c && cmd == "firstunknown") - cout << "first unknown blockhash: " << c->blockQueue().firstUnknown().hex() << endl; - else if (c && cmd == "retryunknown") - c->retryUnknown(); - else if (cmd == "peers") + catch (...) { - for (auto it: web3.peers()) - cout << it.host << ":" << it.port << ", " << it.clientVersion << ", " - << std::chrono::duration_cast(it.lastPing).count() << "ms" - << endl; + cerr << "Bad " << arg << " option: " << argv[i] << endl; + return -1; } - else if (cmd == "newaccount") + } + else if (arg == "--bid" && i + 1 < argc) + { + try { - string name; - std::getline(iss, name); - auto s = Secret::random(); - string password; - while (password.empty()) - { - password = getPassword("Please enter a password to protect this key (press enter for protection only be the MASTER password/keystore): "); - string confirm = getPassword("Please confirm the password by entering it again: "); - if (password != confirm) - { - cout << "Passwords were different. Try again." << endl; - password.clear(); - } - } - if (!password.empty()) - { - cout << "Enter a hint for this password: " << flush; - string hint; - std::getline(cin, hint); - keyManager.import(s, name, password, hint); - } - else - keyManager.import(s, name); - cout << "New account created: " << toAddress(s); + bidPrice = u256(argv[++i]); } - else if (c && cmd == "accounts") + catch (...) { - cout << "Accounts:" << endl; - u256 total = 0; - for (auto const& address: keyManager.accounts()) - { - auto b = c->balanceAt(address); - cout << ((address == signingKey) ? "SIGNING " : " ") << ((address == beneficiary) ? "COINBASE " : " ") << keyManager.accountName(address) << " (" << address << "): " << formatBalance(b) << " = " << b << " wei" << endl; - total += b; - } - cout << "Total: " << formatBalance(total) << " = " << total << " wei" << endl; + cerr << "Bad " << arg << " option: " << argv[i] << endl; + return -1; } - else if (c && cmd == "transact") - { - auto const& bc =c->blockChain(); - auto h = bc.currentHash(); - auto blockData = bc.block(h); - BlockInfo info(blockData); - if (iss.peek() != -1) - { - string hexAddr; - u256 amount; - u256 gasPrice; - u256 gas; - string sechex; - string sdata; - - iss >> hexAddr >> amount >> gasPrice >> gas >> sechex >> sdata; - - if (!gasPrice) - gasPrice = gasPricer->bid(priority); - - cnote << "Data:"; - cnote << sdata; - bytes data = dev::eth::parseData(sdata); - cnote << "Bytes:"; - string sbd = asString(data); - bytes bbd = asBytes(sbd); - stringstream ssbd; - ssbd << bbd; - cnote << ssbd.str(); - int ssize = sechex.length(); - int size = hexAddr.length(); - u256 minGas = (u256)Transaction::gasRequired(data, 0); - if (size < 40) - { - if (size > 0) - cwarn << "Invalid address length:" << size; - } - else if (gas < minGas) - cwarn << "Minimum gas amount is" << minGas; - else if (ssize < 40) - { - if (ssize > 0) - cwarn << "Invalid secret length:" << ssize; - } - else - { - try - { - Secret secret = h256(fromHex(sechex)); - Address dest = h160(fromHex(hexAddr)); - c->submitTransaction(secret, amount, dest, data, gas, gasPrice); - } - catch (BadHexCharacter& _e) - { - cwarn << "invalid hex character, transaction rejected"; - cwarn << boost::diagnostic_information(_e); - } - catch (...) - { - cwarn << "transaction rejected"; - } - } + } + else if ((arg == "-P" || arg == "--priority") && i + 1 < argc) + { + string m = boost::to_lower_copy(string(argv[++i])); + if (m == "lowest") + priority = TransactionPriority::Lowest; + else if (m == "low") + priority = TransactionPriority::Low; + else if (m == "medium" || m == "mid" || m == "default" || m == "normal") + priority = TransactionPriority::Medium; + else if (m == "high") + priority = TransactionPriority::High; + else if (m == "highest") + priority = TransactionPriority::Highest; + else + try { + priority = (TransactionPriority)(max(0, min(100, stoi(m))) * 8 / 100); } - else - cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA"; - } - - else if (c && cmd == "transactnonce") - { - auto const& bc =c->blockChain(); - auto h = bc.currentHash(); - auto blockData = bc.block(h); - BlockInfo info(blockData); - if (iss.peek() != -1) - { - string hexAddr; - u256 amount; - u256 gasPrice; - u256 gas; - string sechex; - string sdata; - u256 nonce; - - iss >> hexAddr >> amount >> gasPrice >> gas >> sechex >> sdata >> nonce; - - if (!gasPrice) - gasPrice = gasPricer->bid(priority); - - cnote << "Data:"; - cnote << sdata; - bytes data = dev::eth::parseData(sdata); - cnote << "Bytes:"; - string sbd = asString(data); - bytes bbd = asBytes(sbd); - stringstream ssbd; - ssbd << bbd; - cnote << ssbd.str(); - int ssize = sechex.length(); - int size = hexAddr.length(); - u256 minGas = (u256)Transaction::gasRequired(data, 0); - if (size < 40) - { - if (size > 0) - cwarn << "Invalid address length:" << size; - } - else if (gas < minGas) - cwarn << "Minimum gas amount is" << minGas; - else if (ssize < 40) - { - if (ssize > 0) - cwarn << "Invalid secret length:" << ssize; - } - else - { - try - { - Secret secret = h256(fromHex(sechex)); - Address dest = h160(fromHex(hexAddr)); - c->submitTransaction(secret, amount, dest, data, gas, gasPrice, nonce); - } - catch (BadHexCharacter& _e) - { - cwarn << "invalid hex character, transaction rejected"; - cwarn << boost::diagnostic_information(_e); - } - catch (...) - { - cwarn << "transaction rejected"; - } - } + catch (...) { + cerr << "Unknown " << arg << " option: " << m << endl; + return -1; } - else - cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA NONCE"; - } - - else if (c && cmd == "txcreate") - { - auto const& bc =c->blockChain(); - auto h = bc.currentHash(); - auto blockData = bc.block(h); - BlockInfo info(blockData); - if (iss.peek() != -1) - { - u256 amount; - u256 gasPrice; - u256 gas; - string sechex; - string sdata; - - iss >> amount >> gasPrice >> gas >> sechex >> sdata; - - if (!gasPrice) - gasPrice = gasPricer->bid(priority); - - cnote << "Data:"; - cnote << sdata; - bytes data = dev::eth::parseData(sdata); - cnote << "Bytes:"; - string sbd = asString(data); - bytes bbd = asBytes(sbd); - stringstream ssbd; - ssbd << bbd; - cnote << ssbd.str(); - int ssize = sechex.length(); - u256 minGas = (u256)Transaction::gasRequired(data, 0); - if (gas < minGas) - cwarn << "Minimum gas amount is" << minGas; - else if (ssize < 40) - { - if (ssize > 0) - cwarn << "Invalid secret length:" << ssize; - } - else - { - try - { - Secret secret = h256(fromHex(sechex)); - cout << " new contract address : " << c->submitTransaction(secret, amount, data, gas, gasPrice) << endl; - } - catch (BadHexCharacter& _e) - { - cwarn << "invalid hex character, transaction rejected"; - cwarn << boost::diagnostic_information(_e); - } - catch (...) - { - cwarn << "transaction rejected"; - } - } + } + else if ((arg == "-m" || arg == "--mining") && i + 1 < argc) + { + string m = argv[++i]; + if (isTrue(m)) + mining = ~(unsigned)0; + else if (isFalse(m)) + mining = 0; + else + try { + mining = stoi(m); } - else - cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET INIT"; - } -#if ETH_FATDB - else if (c && cmd == "listcontracts") + catch (...) { + cerr << "Unknown " << arg << " option: " << m << endl; + return -1; + } + } + else if (arg == "-b" || arg == "--bootstrap") + bootstrap = true; + else if (arg == "--no-discovery") + disableDiscovery = true; + else if (arg == "--pin") + pinning = true; + else if (arg == "-f" || arg == "--force-mining") + forceMining = true; + else if (arg == "-i" || arg == "--interactive") + interactive = true; +#if ETH_JSONRPC + else if ((arg == "-j" || arg == "--json-rpc")) + jsonrpc = jsonrpc == -1 ? SensibleHttpPort : jsonrpc; + else if (arg == "--json-rpc-port" && i + 1 < argc) + jsonrpc = atoi(argv[++i]); + else if (arg == "--json-admin" && i + 1 < argc) + jsonAdmin = argv[++i]; +#endif +#if ETH_JSCONSOLE + else if (arg == "--console") + useConsole = true; +#endif + else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc) + g_logVerbosity = atoi(argv[++i]); + else if ((arg == "-x" || arg == "--peers") && i + 1 < argc) + peers = atoi(argv[++i]); + else if ((arg == "-o" || arg == "--mode") && i + 1 < argc) + { + string m = argv[++i]; + if (m == "full") + nodeMode = NodeMode::Full; + else if (m == "peer") + nodeMode = NodeMode::PeerServer; + else { - auto acs =c->addresses(); - string ss; - for (auto const& i: acs) - if ( c->codeAt(i, PendingBlock).size()) - { - ss = toString(i) + " : " + toString( c->balanceAt(i)) + " [" + toString((unsigned) c->countAt(i)) + "]"; - cout << ss << endl; - } + cerr << "Unknown mode: " << m << endl; + return -1; } - else if (c && cmd == "listaccounts") + } +#if ETH_EVMJIT + else if (arg == "-J" || arg == "--jit") + jit = true; +#endif + else if (arg == "-h" || arg == "--help") + help(); + else if (arg == "-V" || arg == "--version") + version(); + else + { + cerr << "Invalid argument: " << arg << endl; + exit(-1); + } + } + + m.execute(); + + KeyManager keyManager; + for (auto const& s: passwordsToNote) + keyManager.notePassword(s); + + { + RLPStream config(2); + config << signingKey << beneficiary; + writeFile(configFile, config.out()); + } + + if (sessionKey) + signingKey = sessionKey; + + if (!clientName.empty()) + clientName += "/"; + + string logbuf; + std::string additional; + if (interactive) + g_logPost = [&](std::string const& a, char const*){ + static SpinLock s_lock; + SpinGuard l(s_lock); + + if (g_silence) + logbuf += a + "\n"; + else + cout << "\r \r" << a << endl << additional << flush; + + // helpful to use OutputDebugString on windows + #ifdef _WIN32 { - auto acs =c->addresses(); - string ss; - for (auto const& i: acs) - if ( c->codeAt(i, PendingBlock).empty()) - { - ss = toString(i) + " : " + toString( c->balanceAt(i)) + " [" + toString((unsigned) c->countAt(i)) + "]"; - cout << ss << endl; - } + OutputDebugStringA(a.data()); + OutputDebugStringA("\n"); } - else if (c && cmd == "balanceat") - { - if (iss.peek() != -1) - { - string stringHash; - iss >> stringHash; + #endif + }; - Address address = h160(fromHex(stringHash)); + auto getPassword = [&](string const& prompt){ + auto s = g_silence; + g_silence = true; + cout << endl; + string ret = dev::getPassword(prompt); + g_silence = s; + return ret; + }; + auto getAccountPassword = [&](Address const& a){ + return getPassword("Enter password for address " + keyManager.accountName(a) + " (" + a.abridged() + "; hint:" + keyManager.passwordHint(a) + "): "); + }; - cout << "balance of " << stringHash << " is: " << toString(c->balanceAt(address)) << endl; - } - } - else if (c && cmd == "balanceatblock") + StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat, structuredLoggingURL); + VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter); + auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp); + netPrefs.discovery = !disableDiscovery; + netPrefs.pin = pinning; + auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp"); + dev::WebThreeDirect web3( + WebThreeDirect::composeClientVersion("++eth", clientName), + dbPath, + killChain, + nodeMode == NodeMode::Full ? set{"eth"/*, "shh"*/} : set(), + netPrefs, + &nodesState); + web3.ethereum()->setMineOnBadChain(mineOnWrongChain); + web3.ethereum()->setSentinel(sentinel); + + auto toNumber = [&](string const& s) -> unsigned { + if (s == "latest") + return web3.ethereum()->number(); + if (s.size() == 64 || (s.size() == 66 && s.substr(0, 2) == "0x")) + return web3.ethereum()->blockChain().number(h256(s)); + try { + return stol(s); + } + catch (...) + { + cerr << "Bad block number/hash option: " << s << endl; + exit(-1); + } + }; + + if (mode == OperationMode::Export) + { + ofstream fout(filename, std::ofstream::binary); + ostream& out = (filename.empty() || filename == "--") ? cout : fout; + + unsigned last = toNumber(exportTo); + for (unsigned i = toNumber(exportFrom); i <= last; ++i) + { + bytes block = web3.ethereum()->blockChain().block(web3.ethereum()->blockChain().numberHash(i)); + switch (exportFormat) { - if (iss.peek() != -1) - { - string stringHash; - unsigned blocknumber; - iss >> stringHash >> blocknumber; - - Address address = h160(fromHex(stringHash)); - - cout << "balance of " << stringHash << " is: " << toString(c->balanceAt(address, blocknumber)) << endl; - } + case Format::Binary: out.write((char const*)block.data(), block.size()); break; + case Format::Hex: out << toHex(block) << endl; break; + case Format::Human: out << RLP(block) << endl; break; + default:; } - else if (c && cmd == "storageat") - { - if (iss.peek() != -1) - { - string stringHash; - iss >> stringHash; + } + return 0; + } - Address address = h160(fromHex(stringHash)); + if (mode == OperationMode::Import) + { + ifstream fin(filename, std::ifstream::binary); + istream& in = (filename.empty() || filename == "--") ? cin : fin; + unsigned alreadyHave = 0; + unsigned good = 0; + unsigned futureTime = 0; + unsigned unknownParent = 0; + unsigned bad = 0; + chrono::steady_clock::time_point t = chrono::steady_clock::now(); + double last = 0; + unsigned lastImported = 0; + unsigned imported = 0; + while (in.peek() != -1) + { + bytes block(8); + in.read((char*)block.data(), 8); + block.resize(RLP(block, RLP::LaissezFaire).actualSize()); + in.read((char*)block.data() + 8, block.size() - 8); - cout << "storage at " << stringHash << " is: " << endl; - for (auto s: c->storageAt(address)) - cout << toHex(s.first) << " : " << toHex(s.second) << endl; - } - } - else if (c && cmd == "storageatblock") + switch (web3.ethereum()->queueBlock(block, safeImport)) { - if (iss.peek() != -1) - { - string stringHash; - unsigned blocknumber; - iss >> stringHash >> blocknumber; - - Address address = h160(fromHex(stringHash)); - - cout << "storage at " << stringHash << " is: " << endl; - for (auto s: c->storageAt(address, blocknumber)) - cout << "\"0x" << toHex(s.first) << "\" : \"0x" << toHex(s.second) << "\"," << endl; - } + case ImportResult::Success: good++; break; + case ImportResult::AlreadyKnown: alreadyHave++; break; + case ImportResult::UnknownParent: unknownParent++; break; + case ImportResult::FutureTimeUnknown: unknownParent++; futureTime++; break; + case ImportResult::FutureTimeKnown: futureTime++; break; + default: bad++; break; } - else if (c && cmd == "codeat") - { - if (iss.peek() != -1) - { - string stringHash; - iss >> stringHash; - Address address = h160(fromHex(stringHash)); + // sync chain with queue + tuple r = web3.ethereum()->syncQueue(10); + imported += get<2>(r); - cout << "code at " << stringHash << " is: " << toHex(c->codeAt(address)) << endl; - } + double e = chrono::duration_cast(chrono::steady_clock::now() - t).count() / 1000.0; + if ((unsigned)e >= last + 10) + { + auto i = imported - lastImported; + auto d = e - last; + cout << i << " more imported at " << (round(i * 10 / d) / 10) << " blocks/s. " << imported << " imported in " << e << " seconds at " << (round(imported * 10 / e) / 10) << " blocks/s (#" << web3.ethereum()->number() << ")" << endl; + last = (unsigned)e; + lastImported = imported; +// cout << web3.ethereum()->blockQueueStatus() << endl; } -#endif + } - else if (c && cmd == "send") - { - if (iss.peek() != -1) - { - string hexAddr; - u256 amount; + while (web3.ethereum()->blockQueue().items().first + web3.ethereum()->blockQueue().items().second > 0) + { + this_thread::sleep_for(chrono::seconds(1)); + web3.ethereum()->syncQueue(100000); + } + double e = chrono::duration_cast(chrono::steady_clock::now() - t).count() / 1000.0; + cout << imported << " imported in " << e << " seconds at " << (round(imported * 10 / e) / 10) << " blocks/s (#" << web3.ethereum()->number() << ")" << endl; + return 0; + } - iss >> hexAddr >> amount; - int size = hexAddr.length(); - if (size < 40) - { - if (size > 0) - cwarn << "Invalid address length:" << size; - } - else - { - auto const& bc =c->blockChain(); - auto h = bc.currentHash(); - auto blockData = bc.block(h); - BlockInfo info(blockData); - u256 minGas = (u256)Transaction::gasRequired(bytes(), 0); - try - { - Address dest = h160(fromHex(hexAddr, WhenError::Throw)); - c->submitTransaction(keyManager.secret(signingKey, [&](){ return getAccountPassword(signingKey); }), amount, dest, bytes(), minGas); - } - catch (BadHexCharacter& _e) - { - cwarn << "invalid hex character, transaction rejected"; - cwarn << boost::diagnostic_information(_e); - } - catch (...) - { - cwarn << "transaction rejected"; - } - } - } - else - cwarn << "Require parameters: send ADDRESS AMOUNT"; - } - else if (c && cmd == "contract") - { - auto const& bc =c->blockChain(); - auto h = bc.currentHash(); - auto blockData = bc.block(h); - BlockInfo info(blockData); - if (iss.peek() != -1) - { - u256 endowment; - u256 gas; - u256 gasPrice; - string sinit; - iss >> endowment >> gasPrice >> gas >> sinit; - trim_all(sinit); - int size = sinit.length(); - bytes init; - cnote << "Init:"; - cnote << sinit; - cnote << "Code size:" << size; - if (size < 1) - cwarn << "No code submitted"; - else - { - cnote << "Assembled:"; - stringstream ssc; - try - { - init = fromHex(sinit, WhenError::Throw); - } - catch (BadHexCharacter& _e) - { - cwarn << "invalid hex character, code rejected"; - cwarn << boost::diagnostic_information(_e); - init = bytes(); - } - catch (...) - { - cwarn << "code rejected"; - init = bytes(); - } - ssc.str(string()); - ssc << disassemble(init); - cnote << "Init:"; - cnote << ssc.str(); - } - u256 minGas = (u256)Transaction::gasRequired(init, 0); - if (!init.size()) - cwarn << "Contract creation aborted, no init code."; - else if (endowment < 0) - cwarn << "Invalid endowment"; - else if (gas < minGas) - cwarn << "Minimum gas amount is" << minGas; - else - c->submitTransaction(keyManager.secret(signingKey, [&](){ return getAccountPassword(signingKey); }), endowment, init, gas, gasPrice); - } - else - cwarn << "Require parameters: contract ENDOWMENT GASPRICE GAS CODEHEX"; - } - else if (c && cmd == "dumpreceipt") - { - unsigned block; - unsigned index; - iss >> block >> index; - dev::eth::TransactionReceipt r = c->blockChain().receipts(c->blockChain().numberHash(block)).receipts[index]; - auto rb = r.rlp(); - cout << "RLP: " << RLP(rb) << endl; - cout << "Hex: " << toHex(rb) << endl; - cout << r << endl; - } - else if (c && cmd == "reprocess") - { - string block; - iss >> block; - h256 blockHash; + if (c_network == eth::Network::Frontier && !yesIReallyKnowWhatImDoing) + { + auto pd = contents(getDataDir() + "primes"); + unordered_set primes = RLP(pd).toUnorderedSet(); + while (true) + { + if (!prime) try { - if (block.size() == 64 || block.size() == 66) - blockHash = h256(block); - else - blockHash = c->blockChain().numberHash(stoi(block)); - c->state(blockHash); - } - catch (...) - {} - } - else if (c && cmd == "dumptrace") - { - unsigned block; - unsigned index; - string filename; - string format; - iss >> block >> index >> filename >> format; - ofstream f; - f.open(filename); - - dev::eth::State state = c->state(index + 1,c->blockChain().numberHash(block)); - if (index < state.pending().size()) - { - Executive e(state, c->blockChain(), 0); - Transaction t = state.pending()[index]; - state = state.fromPending(index); - try - { - OnOpFunc oof; - if (format == "pretty") - oof = [&](uint64_t steps, Instruction instr, bigint newMemSize, bigint gasCost, bigint gas, dev::eth::VM* vvm, dev::eth::ExtVMFace const* vextVM) - { - dev::eth::VM* vm = vvm; - dev::eth::ExtVM const* ext = static_cast(vextVM); - f << endl << " STACK" << endl; - for (auto i: vm->stack()) - f << (h256)i << endl; - f << " MEMORY" << endl << dev::memDump(vm->memory()); - f << " STORAGE" << endl; - for (auto const& i: ext->state().storage(ext->myAddress)) - f << showbase << hex << i.first << ": " << i.second << endl; - f << dec << ext->depth << " | " << ext->myAddress << " | #" << steps << " | " << hex << setw(4) << setfill('0') << vm->curPC() << " : " << dev::eth::instructionInfo(instr).name << " | " << dec << gas << " | -" << dec << gasCost << " | " << newMemSize << "x32"; - }; - else if (format == "standard") - oof = [&](uint64_t, Instruction instr, bigint, bigint, bigint gas, dev::eth::VM* vvm, dev::eth::ExtVMFace const* vextVM) - { - dev::eth::VM* vm = vvm; - dev::eth::ExtVM const* ext = static_cast(vextVM); - f << ext->myAddress << " " << hex << toHex(dev::toCompactBigEndian(vm->curPC(), 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)instr, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)gas, 1)) << endl; - }; - else if (format == "standard+") - oof = [&](uint64_t, Instruction instr, bigint, bigint, bigint gas, dev::eth::VM* vvm, dev::eth::ExtVMFace const* vextVM) - { - dev::eth::VM* vm = vvm; - dev::eth::ExtVM const* ext = static_cast(vextVM); - if (instr == Instruction::STOP || instr == Instruction::RETURN || instr == Instruction::SUICIDE) - for (auto const& i: ext->state().storage(ext->myAddress)) - f << toHex(dev::toCompactBigEndian(i.first, 1)) << " " << toHex(dev::toCompactBigEndian(i.second, 1)) << endl; - f << ext->myAddress << " " << hex << toHex(dev::toCompactBigEndian(vm->curPC(), 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)instr, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)gas, 1)) << endl; - }; - e.initialize(t); - if (!e.execute()) - e.go(oof); - e.finalize(); - } - catch(Exception const& _e) - { - // TODO: a bit more information here. this is probably quite worrying as the transaction is already in the blockchain. - cwarn << diagnostic_information(_e); - } + prime = stoi(getPassword("To enter the Frontier, enter a 6 digit prime that you have not entered before: ")); } - } - else if (c && cmd == "inspect") - { - string rechex; - iss >> rechex; - - if (rechex.length() != 40) - cwarn << "Invalid address length"; - else - { - auto h = h160(fromHex(rechex)); - stringstream s; + catch (...) {} + if (isPrime(prime) && !primes.count(prime)) + break; + prime = 0; + } + primes.insert(prime); + writeFile(getDataDir() + "primes", rlp(primes)); + } - try - { - auto storage =c->storageAt(h, PendingBlock); - for (auto const& i: storage) - s << "@" << showbase << hex << i.first << " " << showbase << hex << i.second << endl; - s << endl << disassemble( c->codeAt(h, PendingBlock)) << endl; - - string outFile = getDataDir() + "/" + rechex + ".evm"; - ofstream ofs; - ofs.open(outFile, ofstream::binary); - ofs.write(s.str().c_str(), s.str().length()); - ofs.close(); - - cnote << "Saved" << rechex << "to" << outFile; - } - catch (dev::InvalidTrie) - { - cwarn << "Corrupted trie."; - } - } - } - else if (cmd == "setsigningkey") - { - if (iss.peek() != -1) - { - string hexSec; - iss >> hexSec; - signingKey = Address(fromHex(hexSec)); - } - else - cwarn << "Require parameter: setSecret HEXSECRETKEY"; - } - else if (cmd == "setaddress") - { - if (iss.peek() != -1) - { - string hexAddr; - iss >> hexAddr; - if (hexAddr.length() != 40) - cwarn << "Invalid address length: " << hexAddr.length(); - else - { - try - { - beneficiary = h160(fromHex(hexAddr, WhenError::Throw)); - } - catch (BadHexCharacter& _e) - { - cwarn << "invalid hex character, coinbase rejected"; - cwarn << boost::diagnostic_information(_e); - } - catch (...) - { - cwarn << "coinbase rejected"; - } - } - } - else - cwarn << "Require parameter: setAddress HEXADDRESS"; - } - else if (cmd == "exportconfig") + if (keyManager.exists()) + { + if (masterPassword.empty() || !keyManager.load(masterPassword)) + while (true) { - if (iss.peek() != -1) - { - string path; - iss >> path; - RLPStream config(2); - config << signingKey << beneficiary; - writeFile(path, config.out()); - } - else - cwarn << "Require parameter: exportConfig PATH"; + masterPassword = getPassword("Please enter your MASTER password: "); + if (keyManager.load(masterPassword)) + break; + cout << "Password invalid. Try again." << endl; } - else if (cmd == "importconfig") + } + else + { + while (masterPassword.empty()) + { + masterPassword = getPassword("Please enter a MASTER password to protect your key store (make it strong!): "); + string confirm = getPassword("Please confirm the password by entering it again: "); + if (masterPassword != confirm) { - if (iss.peek() != -1) - { - string path; - iss >> path; - bytes b = contents(path); - if (b.size()) - { - RLP config(b); - signingKey = config[0].toHash
(); - beneficiary = config[1].toHash
(); - } - else - cwarn << path << "has no content!"; - } - else - cwarn << "Require parameter: importConfig PATH"; + cout << "Passwords were different. Try again." << endl; + masterPassword.clear(); } - else if (cmd == "help") - interactiveHelp(); - else if (cmd == "exit") - break; - else - cout << "Unrecognised command. Type 'help' for help in interactive mode." << endl; } -#if ETH_JSONRPC - if (jsonrpcServer.get()) - jsonrpcServer->StopListening(); -#endif + keyManager.create(masterPassword); + } + + for (auto const& s: toImport) + { + keyManager.import(s, "Imported key (UNSAFE)"); + if (!signingKey) + signingKey = toAddress(s); + } + + if (keyManager.accounts().empty()) + keyManager.import(Secret::random(), "Default key"); + + cout << ethCredits(); + web3.setIdealPeerCount(peers); +// std::shared_ptr gasPricer = make_shared(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000)); + std::shared_ptr gasPricer = make_shared(askPrice, bidPrice); + eth::Client* c = nodeMode == NodeMode::Full ? web3.ethereum() : nullptr; + StructuredLogger::starting(WebThreeDirect::composeClientVersion("++eth", clientName), dev::Version); + if (c) + { + c->setGasPricer(gasPricer); + c->setForceMining(forceMining); + c->setTurboMining(m.minerType() == MinerCLI::MinerType::GPU); + c->setAddress(beneficiary); + c->setNetworkId(networkId); + } + + cout << "Transaction Signer: " << signingKey << endl; + cout << "Mining Benefactor: " << beneficiary << endl; + + if (bootstrap || !remoteHost.empty()) + { + web3.startNetwork(); + cout << "Node ID: " << web3.enode() << endl; + } + else + cout << "Networking disabled. To start, use netstart or pass -b or a remote host." << endl; + + if (useConsole && jsonrpc == -1) + jsonrpc = SensibleHttpPort; + +#if ETH_JSONRPC || !ETH_TRUE + shared_ptr jsonrpcServer; + unique_ptr jsonrpcConnector; + if (jsonrpc > -1) + { + jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads)); + jsonrpcServer = make_shared(*jsonrpcConnector.get(), web3, make_shared([&](){ return web3.ethereum(); }, getAccountPassword, keyManager), vector(), keyManager, *gasPricer); + jsonrpcServer->setMiningBenefactorChanger([&](Address const& a) { beneficiary = a; }); + jsonrpcServer->StartListening(); + if (jsonAdmin.empty()) + jsonAdmin = jsonrpcServer->newSession(SessionPermissions{{Priviledge::Admin}}); + else + jsonrpcServer->addSession(jsonAdmin, SessionPermissions{{Priviledge::Admin}}); + cout << "JSONRPC Admin Session Key: " << jsonAdmin << endl; } +#endif + + if (bootstrap) + for (auto const& i: Host::pocHosts()) + web3.requirePeer(i.first, i.second); + if (!remoteHost.empty()) + web3.addNode(p2p::NodeId(), remoteHost + ":" + toString(remotePort)); + + signal(SIGABRT, &sighandler); + signal(SIGTERM, &sighandler); + signal(SIGINT, &sighandler); + + if (interactive) + interactiveMode(c, gasPricer, web3, keyManager, logbuf, additional, getPassword, getAccountPassword, netPrefs, beneficiary, signingKey, priority); else if (c) { - unsigned n =c->blockChain().details().number; + unsigned n = c->blockChain().details().number; if (mining) c->startMining(); if (useConsole) { -#if ETH_JSCONSOLE +#if ETH_JSCONSOLE || !ETH_TRUE JSLocalConsole console; - - jsonrpcServer = shared_ptr(new dev::WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared([&](){ return web3.ethereum(); }, getAccountPassword, keyManager), vector(), keyManager, *gasPricer)); - jsonrpcServer->setMiningBenefactorChanger([&](Address const& a) { beneficiary = a; }); - jsonrpcServer->StartListening(); - if (jsonAdmin.empty()) - jsonAdmin = jsonrpcServer->newSession(SessionPermissions{{Priviledge::Admin}}); - else - jsonrpcServer->addSession(jsonAdmin, SessionPermissions{{Priviledge::Admin}}); - cout << "JSONRPC Admin Session Key: " << jsonAdmin << endl; - + // TODO: set port properly? while (!g_exit) { console.readExpression(); stopMiningAfterXBlocks(c, n, mining); } - jsonrpcServer->StopListening(); #endif } @@ -1845,6 +1753,11 @@ int main(int argc, char** argv) while (!g_exit) this_thread::sleep_for(chrono::milliseconds(1000)); +#if ETH_JSONRPC + if (jsonrpcServer.get()) + jsonrpcServer->StopListening(); +#endif + StructuredLogger::stopping(WebThreeDirect::composeClientVersion("++eth", clientName), dev::Version); auto netData = web3.saveNetwork(); if (!netData.empty()) From 18ad0a4c9a592b21808f411495e747172da22302 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 3 Jul 2015 10:10:20 +0200 Subject: [PATCH 117/290] Fix for crap compilers. Fix for tests. --- libethereum/Transaction.h | 20 +++++++++++++++++++- libethereum/TransactionQueue.cpp | 1 - test/libethereum/gaspricer.cpp | 5 ++--- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h index 95e1619fe..77ba1824d 100644 --- a/libethereum/Transaction.h +++ b/libethereum/Transaction.h @@ -85,7 +85,25 @@ public: /// Constructs a null transaction. Transaction() {} - using TransactionBase::TransactionBase; + /// Constructs a signed message-call transaction. + Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data, u256 const& _nonce, Secret const& _secret): + TransactionBase(_value, _gasPrice, _gas, _dest, _data, _nonce, _secret) + {} + + /// Constructs a signed contract-creation transaction. + Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data, u256 const& _nonce, Secret const& _secret): + TransactionBase(_value, _gasPrice, _gas, _data, _nonce, _secret) + {} + + /// Constructs an unsigned message-call transaction. + Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data, u256 const& _nonce = 0): + TransactionBase(_value, _gasPrice, _gas, _dest, _data, _nonce) + {} + + /// Constructs an unsigned contract-creation transaction. + Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data, u256 const& _nonce = 0): + TransactionBase(_value, _gasPrice, _gas, _data, _nonce) + {} /// Constructs a transaction from the given RLP. explicit Transaction(bytesConstRef _rlp, CheckTransaction _checkSig); diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index bbda58fd7..d2ced467e 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -109,7 +109,6 @@ ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transactio // If it doesn't work, the signature is bad. // The transaction's nonce may yet be invalid (or, it could be "valid" but we may be missing a marginally older transaction). - // Remove any prior transaction with the same nonce but a lower gas price. // Bomb out if there's a prior transaction with higher gas price. auto r = m_senders.equal_range(_transaction.from()); diff --git a/test/libethereum/gaspricer.cpp b/test/libethereum/gaspricer.cpp index 105f4c2d7..ce49a4a20 100644 --- a/test/libethereum/gaspricer.cpp +++ b/test/libethereum/gaspricer.cpp @@ -20,10 +20,9 @@ */ #include -#include #include -#include -#include +#include +#include #include "../TestHelper.h" using namespace std; From 1c009a5cec242590734fb4b04633df374d2358c5 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 3 Jul 2015 10:32:08 +0200 Subject: [PATCH 118/290] Version bump. --- libdevcore/Common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 5450f9311..5591e94bf 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -28,7 +28,7 @@ using namespace dev; namespace dev { -char const* Version = "0.9.27"; +char const* Version = "0.9.28"; const u256 UndefinedU256 = ~(u256)0; From d06c1a6d141ac48c36e6b6c2061cc1336de338f0 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 3 Jul 2015 11:10:00 +0200 Subject: [PATCH 119/290] bug fix --- mix/ClientModel.cpp | 4 ++-- mix/ClientModel.h | 4 +++- mix/qml/Block.qml | 14 +++++------ mix/qml/BlockChain.qml | 19 ++++++++++----- mix/qml/KeyValuePanel.qml | 16 ++++++++----- mix/qml/ScenarioExecution.qml | 13 ++++++++++ mix/qml/StateListModel.qml | 3 +-- mix/qml/TransactionDialog.qml | 7 +++--- mix/qml/Watchers.qml | 45 ++++++++++++++++++++++++----------- 9 files changed, 84 insertions(+), 41 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 89a836893..eae3f8834 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -206,12 +206,12 @@ QVariantList ClientModel::gasCosts() const return res; } -void ClientModel::addAccount(QString const& _secret, QString const& _amount) +void ClientModel::addAccount(QString const& _secret) { KeyPair key(Secret(_secret.toStdString())); m_accountsSecret.push_back(key); Address address = key.address(); - m_accounts[address] = Account(u256(_amount.toStdString()), Account::NormalCreation); + m_accounts[address] = Account(u256(0), Account::NormalCreation); m_ethAccounts->setAccounts(m_accountsSecret); } diff --git a/mix/ClientModel.h b/mix/ClientModel.h index e14c3c486..5428bb6f8 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -188,7 +188,7 @@ public: /// To Hex number Q_INVOKABLE QString toHex(QString const& _int); /// Add new account to the model - Q_INVOKABLE void addAccount(QString const& _secret, QString const& _amount); + Q_INVOKABLE void addAccount(QString const& _secret); /// Return the address associated with the current secret Q_INVOKABLE QString resolveAddress(QString const& _secret); @@ -246,6 +246,8 @@ signals: void stateCleared(); /// new state has been processed void newState(unsigned _record, QVariantMap _accounts); + /// account has been added to the model + void accountAdded(QString _address, QString _amount); private: RecordLogEntry* lastBlock() const; diff --git a/mix/qml/Block.qml b/mix/qml/Block.qml index cb6737292..732166628 100644 --- a/mix/qml/Block.qml +++ b/mix/qml/Block.qml @@ -41,6 +41,7 @@ ColumnLayout { transactionDialog.stateAccounts = scenario.accounts transactionDialog.execute = false + transactionDialog.editMode = true transactionDialog.open(txIndex, blockIndex, transactions.get(txIndex)) } @@ -164,11 +165,11 @@ ColumnLayout Image { anchors.top: parent.top anchors.left: parent.left - anchors.leftMargin: -9 - anchors.topMargin: -4 + anchors.leftMargin: -4 + anchors.topMargin: 0 id: saveStatusImage source: "qrc:/qml/img/recyclediscard@2x.png" - width: statusWidth + 20 + width: statusWidth + 10 fillMode: Image.PreserveAspectFit } @@ -317,10 +318,10 @@ ColumnLayout Rectangle { width: debugActionWidth - height: trHeight - anchors.left: rowContentTr.right + height: trHeight - 10 + anchors.right: rowContentTr.right anchors.top: rowContentTr.top - anchors.leftMargin: -50 + anchors.rightMargin: 10 color: "transparent" Image { @@ -328,7 +329,6 @@ ColumnLayout source: "qrc:/qml/img/rightarrow@2x.png" width: debugActionWidth fillMode: Image.PreserveAspectFit - anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter visible: transactions.get(index).recordIndex !== undefined } diff --git a/mix/qml/BlockChain.qml b/mix/qml/BlockChain.qml index ca7b60ce7..43bed678f 100644 --- a/mix/qml/BlockChain.qml +++ b/mix/qml/BlockChain.qml @@ -24,6 +24,7 @@ ColumnLayout { signal chainReloaded signal txSelected(var blockIndex, var txIndex) signal rebuilding + signal accountAdded(string address, string amount) Connections { @@ -47,14 +48,12 @@ ColumnLayout { { fromWidth = 250 toWidth = 240 - //valueWidth = 200 } else { var diff = (width - previousWidth) / 3; fromWidth = fromWidth + diff < 250 ? 250 : fromWidth + diff toWidth = toWidth + diff < 240 ? 240 : toWidth + diff - //valueWidth = valueWidth + diff < 200 ? 200 : valueWidth + diff } previousWidth = width } @@ -89,7 +88,7 @@ ColumnLayout { { id: header spacing: 0 - Layout.preferredHeight: 30 + Layout.preferredHeight: 24 Rectangle { Layout.preferredWidth: statusWidth @@ -100,12 +99,13 @@ ColumnLayout { anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter source: "qrc:/qml/img/recycleicon@2x.png" - width: statusWidth + 20 + width: statusWidth + 10 fillMode: Image.PreserveAspectFit } } Rectangle { + anchors.verticalCenter: parent.verticalCenter Layout.preferredWidth: fromWidth Label { @@ -118,11 +118,13 @@ ColumnLayout { Label { text: "To" + anchors.verticalCenter: parent.verticalCenter Layout.preferredWidth: toWidth + cellSpacing } Label { text: "" + anchors.verticalCenter: parent.verticalCenter Layout.preferredWidth: debugActionWidth } } @@ -363,6 +365,7 @@ ColumnLayout { var item = TransactionHelper.defaultTransaction() transactionDialog.stateAccounts = model.accounts transactionDialog.execute = true + transactionDialog.editMode = false transactionDialog.open(model.blocks[model.blocks.length - 1].transactions.length, model.blocks.length - 1, item) } width: 100 @@ -414,7 +417,6 @@ ColumnLayout { } else addNewBlock() - } function addNewBlock() @@ -509,7 +511,12 @@ ColumnLayout { id: newAccount text: qsTr("New Account..") onClicked: { - model.accounts.push(projectModel.stateListModel.newAccount("1000000", QEther.Ether)) + var ac = projectModel.stateListModel.newAccount("O", QEther.Wei) + model.accounts.push(ac) + clientModel.addAccount(ac.secret); + for (var k in Object.keys(blockChainPanel.states)) + blockChainPanel.states[k].accounts["0x" + ac.address] = "0 wei" // add the account in all the previous state (balance at O) + accountAdded(ac.address, "0") } Layout.preferredWidth: 100 Layout.preferredHeight: 30 diff --git a/mix/qml/KeyValuePanel.qml b/mix/qml/KeyValuePanel.qml index 63baa3801..056384b9e 100644 --- a/mix/qml/KeyValuePanel.qml +++ b/mix/qml/KeyValuePanel.qml @@ -18,6 +18,11 @@ ColumnLayout { property string role property alias model: modelKeyValue + function add(key, value) + { + modelKeyValue.append({ "key": key, "value": value }) + } + function clear() { modelKeyValue.clear() @@ -29,10 +34,7 @@ ColumnLayout { if (typeof(computeData) !== "undefined" && computeData instanceof Function) computeData() else - { - console.log("--------------") - console.log(JSON.stringify(_data)) - console.log(role) + { if (_data !== undefined && _data[role] !== undefined) { var keys = Object.keys(_data[role]) @@ -77,6 +79,7 @@ ColumnLayout { id: columnValues horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff anchors.fill: parent + clip: true ColumnLayout { anchors.margins: 10 @@ -97,7 +100,7 @@ ColumnLayout { anchors.left: parent.left anchors.leftMargin: 10 text: { - if (index >= 0) + if (index >= 0 && repeaterKeyValue.model.get(index).key !== undefined) return repeaterKeyValue.model.get(index).key else return "" @@ -113,7 +116,7 @@ ColumnLayout { anchors.right: parent.right anchors.rightMargin: 10 text: { - if (index >= 0) + if (index >= 0 && repeaterKeyValue.model.get(index).value !== undefined) return repeaterKeyValue.model.get(index).value else return "" @@ -123,6 +126,7 @@ ColumnLayout { } } } + } } } diff --git a/mix/qml/ScenarioExecution.qml b/mix/qml/ScenarioExecution.qml index 1eb0c3d0c..687c8e99f 100644 --- a/mix/qml/ScenarioExecution.qml +++ b/mix/qml/ScenarioExecution.qml @@ -84,14 +84,27 @@ Rectangle { Connections { target: blockChain + property var currentSelectedBlock + property var currentSelectedTx onTxSelected: { + currentSelectedBlock = blockIndex + currentSelectedTx = txIndex + updateWatchers(blockIndex, txIndex) + } + + function updateWatchers(blockIndex, txIndex){ var tx = blockChain.model.blocks[blockIndex].transactions[txIndex] var state = blockChain.getState(tx.recordIndex) watchers.updateWidthTx(tx, state, blockIndex, txIndex) } + onRebuilding: { watchers.clear() } + + onAccountAdded: { + watchers.addAccount(address, "0 wei") + } } } diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index a5e6365e0..d3bf1c860 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -257,8 +257,7 @@ Item { _secret = clientModel.newSecret(); var address = clientModel.address(_secret); var name = qsTr("Account") + "-" + address.substring(0, 4); - var amount = QEtherHelper.createEther(_balance, _unit) - clientModel.addAccount(_secret, amount.toWei().value()) + var amount = QEtherHelper.createEther(_balance, _unit) return { name: name, secret: _secret, balance: amount, address: address }; } diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index f4aa9a5f0..4edc601de 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -16,7 +16,8 @@ Dialog { width: 580 height: 500 visible: false - title: qsTr("Edit Transaction") + title: editMode ? qsTr("Edit Transaction") : qsTr("Add Transaction") + property bool editMode property int transactionIndex property int blockIndex property alias gas: gasValueEdit.gasValue; @@ -390,7 +391,7 @@ Dialog { objectName: "trTypeExecute" exclusiveGroup: rbbuttonList height: 30 - text: qsTr("Execute Contract") + text: qsTr("Transact with Contract") } } } @@ -687,7 +688,7 @@ Dialog { } Button { - text: qsTr("Update"); + text: editMode ? qsTr("Update") : qsTr("Ok") onClicked: { var invalid = InputValidator.validate(paramsModel, paramValues); if (invalid.length === 0) diff --git a/mix/qml/Watchers.qml b/mix/qml/Watchers.qml index 2e436a634..087dd1105 100644 --- a/mix/qml/Watchers.qml +++ b/mix/qml/Watchers.qml @@ -24,16 +24,23 @@ Rectangle { { from.text = "" to.text = "" + value.text = "" inputParams.clear() returnParams.clear() accounts.clear() events.clear() } + function addAccount(address, amount) + { + accounts.add(address, amount) + } + function updateWidthTx(_tx, _state, _blockIndex, _txIndex) { - from.text = _tx.sender + from.text = clientModel.resolveAddress(_tx.sender) to.text = _tx.label + value.text = _tx.value.format() tx = _tx blockIndex = _blockIndex txIndex = _txIndex @@ -43,10 +50,10 @@ Rectangle { { returnParams.role = "creationAddr" returnParams._data = { - creationAddr : { - "": _tx.returned + creationAddr : { } } + returnParams._data.creationAddr[qsTr("contract address")] = _tx.returned } else { @@ -68,6 +75,7 @@ Rectangle { color: "transparent" Row { + id: rowHeader anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter height: 5 @@ -100,19 +108,28 @@ Rectangle { clip: true width: 100 } + Label { + id: value + color: "#EAB920" + font.italic: true + clip: true + } + } - Image { - source: "qrc:/qml/img/edit.png" - height: 15 - fillMode: Image.PreserveAspectFit - visible: from.text !== "" - MouseArea + Image { + anchors.right: rowHeader.parent.right + anchors.top: rowHeader.parent.top + anchors.topMargin: 10 + source: "qrc:/qml/img/edit.png" + height: 15 + fillMode: Image.PreserveAspectFit + visible: from.text !== "" + MouseArea + { + anchors.fill: parent + onClicked: { - anchors.fill: parent - onClicked: - { - bc.blockChainRepeater.editTx(blockIndex, txIndex) - } + bc.blockChainRepeater.editTx(blockIndex, txIndex) } } } From 4d03f86b343516250b0d42f6acd5537613e0ccb3 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 3 Jul 2015 11:40:47 +0200 Subject: [PATCH 120/290] clean code, add icons --- mix/ClientModel.h | 2 -- mix/qml/BlockChain.qml | 2 +- mix/qml/ScenarioLoader.qml | 8 +++++--- mix/qml/Watchers.qml | 12 ++++++------ mix/res.qrc | 5 +++++ 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 5428bb6f8..92f06b48b 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -246,8 +246,6 @@ signals: void stateCleared(); /// new state has been processed void newState(unsigned _record, QVariantMap _accounts); - /// account has been added to the model - void accountAdded(QString _address, QString _amount); private: RecordLogEntry* lastBlock() const; diff --git a/mix/qml/BlockChain.qml b/mix/qml/BlockChain.qml index 43bed678f..ccc027444 100644 --- a/mix/qml/BlockChain.qml +++ b/mix/qml/BlockChain.qml @@ -429,7 +429,7 @@ ColumnLayout { height: 30 buttonShortcut: "" - sourceImg: "qrc:/qml/img/addblock@2x.png" + sourceImg: "qrc:/qml/img/newblock@2x.png" } } diff --git a/mix/qml/ScenarioLoader.qml b/mix/qml/ScenarioLoader.qml index accdc324a..58247b213 100644 --- a/mix/qml/ScenarioLoader.qml +++ b/mix/qml/ScenarioLoader.qml @@ -107,11 +107,13 @@ ColumnLayout Rectangle { id: editIconRect + anchors.top: scenarioName.top + anchors.topMargin: 6 anchors.left: scenarioName.right - anchors.leftMargin: 15 + anchors.leftMargin: 20 Image { - source: "qrc:/qml/img/edit.png" - width: 10 + source: "qrc:/qml/img/edittransaction.png" + width: 30 fillMode: Image.PreserveAspectFit anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter diff --git a/mix/qml/Watchers.qml b/mix/qml/Watchers.qml index 087dd1105..9625d9424 100644 --- a/mix/qml/Watchers.qml +++ b/mix/qml/Watchers.qml @@ -70,15 +70,15 @@ Rectangle { spacing: 15 Rectangle { - height: 20 + height: 15 width: parent.width - 30 color: "transparent" Row { id: rowHeader anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - height: 5 + anchors.top: rowHeader.parent.top + anchors.topMargin: 6 spacing: 5 Label { id: fromLabel @@ -119,9 +119,9 @@ Rectangle { Image { anchors.right: rowHeader.parent.right anchors.top: rowHeader.parent.top - anchors.topMargin: 10 - source: "qrc:/qml/img/edit.png" - height: 15 + anchors.topMargin: -3 + source: "qrc:/qml/img/edittransaction2.png" + height: 30 fillMode: Image.PreserveAspectFit visible: from.text !== "" MouseArea diff --git a/mix/res.qrc b/mix/res.qrc index b50aa3d9f..c868ff34b 100644 --- a/mix/res.qrc +++ b/mix/res.qrc @@ -90,5 +90,10 @@ qml/img/saveicon@2x.png qml/img/sendtransactionicon.png qml/img/sendtransactionicon@2x.png + qml/img/edittransaction@2x.png + qml/img/newblock@2x.png + qml/img/edittransaction2@2x.png + qml/img/edittransaction.png + qml/img/edittransaction2.png From 6b4b330d8b1b57b15dc005d4a5158b622337558a Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 3 Jul 2015 11:57:46 +0200 Subject: [PATCH 121/290] retrieve short type name --- mix/CodeModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 655be1c08..1d566308b 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -543,7 +543,7 @@ void CodeModel::retrieveSubType(SolidityType& _wrapperType, dev::solidity::Type SolidityType CodeModel::nodeType(dev::solidity::Type const* _type) { - SolidityType r { SolidityType::Type::UnsignedInteger, 32, 1, false, false, QString::fromStdString(_type->toString()), std::vector(), std::vector(), nullptr }; + SolidityType r { SolidityType::Type::UnsignedInteger, 32, 1, false, false, QString::fromStdString(_type->toString(true)), std::vector(), std::vector(), nullptr }; if (!_type) return r; switch (_type->getCategory()) From aacb80120eba85f302b540154a64bb5661f55767 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 3 Jul 2015 11:59:36 +0200 Subject: [PATCH 122/290] Removed empty line. --- libdevcore/RLP.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libdevcore/RLP.cpp b/libdevcore/RLP.cpp index 4398dd997..e3dc09a13 100644 --- a/libdevcore/RLP.cpp +++ b/libdevcore/RLP.cpp @@ -246,7 +246,6 @@ void RLPStream::noteAppended(size_t _itemCount) m_out[p] = (byte)(c_rlpListStart + s); else if (c_rlpListIndLenZero + brs <= 0xff) { - m_out[p] = (byte)(c_rlpListIndLenZero + brs); byte* b = &(m_out[p + brs]); for (; s; s >>= 8) From 40ebe265550d5aa50e6123a89f9301dc1da3bc54 Mon Sep 17 00:00:00 2001 From: subtly Date: Fri, 3 Jul 2015 06:16:47 -0400 Subject: [PATCH 123/290] Sign, recovery, and verify. --- CMakeLists.txt | 1 + libdevcrypto/Common.cpp | 22 +++++++++++++++++++++- libdevcrypto/Common.h | 2 -- libdevcrypto/CryptoPP.cpp | 2 +- test/CMakeLists.txt | 1 + test/libdevcrypto/crypto.cpp | 1 - test/libp2p/rlpx.cpp | 1 - 7 files changed, 24 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d7e598678..036b67234 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -398,6 +398,7 @@ if (JSCONSOLE) endif () if (NOT WIN32) + add_definitions(-DETH_HAVE_SECP256K1) add_subdirectory(secp256k1) endif () diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index de1eb645a..fccb005f4 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -46,7 +46,6 @@ struct Secp256k1Context ~Secp256k1Context() { secp256k1_stop(); } }; static Secp256k1Context s_secp256k1; -void dev::crypto::secp256k1Init() { (void)s_secp256k1; } #endif static Secp256k1PP s_secp256k1pp; @@ -184,17 +183,38 @@ bytes dev::decryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _ci Public dev::recover(Signature const& _sig, h256 const& _message) { +#ifdef ETH_HAVE_SECP256K1 + bytes o(65); + int pubkeylen; + if (!secp256k1_ecdsa_recover_compact(_message.data(), h256::size, _sig.data(), o.data(), &pubkeylen, false, o[64])) + return Public(); + return FixedHash<64>(o.data()+1, Public::ConstructFromPointer); +#else return s_secp256k1pp.recover(_sig, _message.ref()); +#endif } Signature dev::sign(Secret const& _k, h256 const& _hash) { +#ifdef ETH_HAVE_SECP256K1 + Signature s; + if (!secp256k1_ecdsa_sign_compact(_hash.data(), h256::size, s.data(), _k.data(), Nonce::get().data(), (int*)(s.data()+64))) + return Signature(); + return s; +#else return s_secp256k1pp.sign(_k, _hash); +#endif } bool dev::verify(Public const& _p, Signature const& _s, h256 const& _hash) { + if (!_p) + return false; +#ifdef ETH_HAVE_SECP256K1 + return _p == recover(_s, _hash); +#else return s_secp256k1pp.verify(_p, _s, _hash.ref(), true); +#endif } bytes dev::pbkdf2(string const& _pass, bytes const& _salt, unsigned _iterations, unsigned _dkLen) diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h index 7bb46c3ea..b3d2649b8 100644 --- a/libdevcrypto/Common.h +++ b/libdevcrypto/Common.h @@ -177,8 +177,6 @@ namespace crypto { struct InvalidState: public dev::Exception {}; -void secp256k1Init(); - /// Key derivation h256 kdf(Secret const& _priv, h256 const& _hash); diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp index 270367de5..5ca93af4d 100644 --- a/libdevcrypto/CryptoPP.cpp +++ b/libdevcrypto/CryptoPP.cpp @@ -103,7 +103,7 @@ bool Secp256k1PP::decryptECIES(Secret const& _k, bytes& io_text) // interop w/go ecies implementation // io_cipher[0] must be 2, 3, or 4, else invalidpublickey - if (io_text[0] < 2 || io_text[0] > 4) + if (io_text.empty() || io_text[0] < 2 || io_text[0] > 4) // invalid message: publickey return false; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 952b1674f..cbf184808 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -72,6 +72,7 @@ add_executable(testeth ${SRC_LIST} ${HEADERS}) target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) target_link_libraries(testeth ${CURL_LIBRARIES}) +target_link_libraries(testeth ${CRYPTOPP_LIBRARIES}) target_link_libraries(testeth ethereum) target_link_libraries(testeth ethcore) if (NOT WIN32) diff --git a/test/libdevcrypto/crypto.cpp b/test/libdevcrypto/crypto.cpp index 135292506..b70eae36e 100644 --- a/test/libdevcrypto/crypto.cpp +++ b/test/libdevcrypto/crypto.cpp @@ -69,7 +69,6 @@ BOOST_AUTO_TEST_CASE(emptySHA3Types) #if ETH_HAVE_SECP256K1 BOOST_AUTO_TEST_CASE(secp256k1lib) { - secp256k1Init(); KeyPair k = KeyPair::create(); BOOST_REQUIRE(!!k.sec()); BOOST_REQUIRE(!!k.pub()); diff --git a/test/libp2p/rlpx.cpp b/test/libp2p/rlpx.cpp index 6d5e59733..8251e94e2 100644 --- a/test/libp2p/rlpx.cpp +++ b/test/libp2p/rlpx.cpp @@ -21,7 +21,6 @@ */ #include -#include #include #include #include From 19199e47d60eec9b46107f9f3da8ce6e7128e120 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 3 Jul 2015 12:36:21 +0200 Subject: [PATCH 124/290] readline optional for jsconsole --- libjsconsole/CMakeLists.txt | 4 +++- libjsconsole/JSConsole.h | 28 ++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/libjsconsole/CMakeLists.txt b/libjsconsole/CMakeLists.txt index 761435fe1..f2bd8ac02 100644 --- a/libjsconsole/CMakeLists.txt +++ b/libjsconsole/CMakeLists.txt @@ -24,7 +24,9 @@ add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} jsengine) target_link_libraries(${EXECUTABLE} devcore) -target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES}) +if (READLINE_FOUND) + target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES}) +endif() target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${CURL_LIBRARIES}) diff --git a/libjsconsole/JSConsole.h b/libjsconsole/JSConsole.h index 50f6d6ae5..8042dd6bb 100644 --- a/libjsconsole/JSConsole.h +++ b/libjsconsole/JSConsole.h @@ -23,9 +23,11 @@ #pragma once #include -// TODO! make readline optional! + +#if ETH_READLINE #include #include +#endif namespace dev { @@ -42,18 +44,34 @@ public: void readExpression() const { std::string cmd = ""; - g_logPost = [](std::string const& a, char const*) { std::cout << "\r \r" << a << std::endl << std::flush; rl_forced_update_display(); }; + g_logPost = [](std::string const& a, char const*) + { + std::cout << "\r \r" << a << std::endl << std::flush; +#if ETH_READLINE + rl_forced_update_display(); +#endif + }; bool isEmpty = true; int openBrackets = 0; do { + std::string rl; +#if ETH_READLINE char* buff = readline(promptForIndentionLevel(openBrackets).c_str()); isEmpty = !(buff && *buff); if (!isEmpty) { - cmd += std::string(buff); - cmd += " "; + rl = std::string(buff); free(buff); + } +#else + std::cout << propmtForIndentionLevel(openBrackets) << std::endl << std::flush; + std::getline(std::cin, rl); +#endif + if (rl.length() > 0) + { + cmd += rl; + cmd += " "; int open = std::count(cmd.begin(), cmd.end(), '{'); open += std::count(cmd.begin(), cmd.end(), '('); int closed = std::count(cmd.begin(), cmd.end(), '}'); @@ -64,7 +82,9 @@ public: if (!isEmpty) { +#if ETH_READLINE add_history(cmd.c_str()); +#endif auto value = m_engine.eval(cmd.c_str()); std::string result = m_printer.prettyPrint(value).cstr(); std::cout << result << std::endl; From 5df0d1b8722a7c92d4a79f0f4185708a555127d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 3 Jul 2015 14:04:04 +0200 Subject: [PATCH 125/290] --vm command line option replacing --jit. --- eth/main.cpp | 15 ++++++--------- ethvm/main.cpp | 9 ++++----- neth/main.cpp | 15 ++++++--------- test/TestHelper.cpp | 4 ++-- 4 files changed, 18 insertions(+), 25 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 0ccba6fca..c45dfe766 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -193,7 +193,7 @@ void help() << "General Options:" << endl << " -d,--db-path Load database from path (default: " << getDataDir() << ")" << endl #if ETH_EVMJIT || !ETH_TRUE - << " -J,--jit Enable EVM JIT (default: off)." << endl + << " --vm= Select VM. Options are: jit, smart. (default: interpreter)" << endl #endif << " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (default: 8)." << endl << " -V,--version Show the version and exit." << endl @@ -313,7 +313,6 @@ int main(int argc, char** argv) string jsonAdmin; bool upnp = true; WithExisting killChain = WithExisting::Trust; - bool jit = false; string sentinel; /// Networking params. @@ -667,10 +666,10 @@ int main(int argc, char** argv) } } #if ETH_EVMJIT - else if (arg == "-J" || arg == "--jit") - { - jit = true; - } + else if (arg == "--vm=jit") + VMFactory::setKind(VMKind::JIT); + else if (arg == "--vm=smart") + VMFactory::setKind(VMKind::Smart); #endif else if (arg == "-h" || arg == "--help") help(); @@ -707,7 +706,7 @@ int main(int argc, char** argv) g_logPost = [&](std::string const& a, char const*){ static SpinLock s_lock; SpinGuard l(s_lock); - + if (g_silence) logbuf += a + "\n"; else @@ -735,7 +734,6 @@ int main(int argc, char** argv) }; StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat, structuredLoggingURL); - VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter); auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp); netPrefs.discovery = !disableDiscovery; netPrefs.pin = pinning; @@ -1864,4 +1862,3 @@ int main(int argc, char** argv) writeFile((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp", netData); return 0; } - diff --git a/ethvm/main.cpp b/ethvm/main.cpp index 4ca733ed0..64413b5a4 100644 --- a/ethvm/main.cpp +++ b/ethvm/main.cpp @@ -43,11 +43,10 @@ void help() << " --gas-price Transaction's gas price' should be (default: 0)." << endl << " --sender Transaction sender should be (default: 0000...0069)." << endl << " --origin Transaction origin should be (default: 0000...0069)." << endl -#if ETH_EVMJIT || !ETH_TRUE +#if ETH_EVMJIT || !ETH_TRUETRUE << endl << "VM options:" << endl - << " -J,--jit Enable LLVM VM (default: off)." << endl - << " --smart Enable smart VM (default: off)." << endl + << " --vm= Select VM. Options are: jit, smart. (default: interpreter)" << endl #endif << endl << "Options for trace:" << endl @@ -97,9 +96,9 @@ int main(int argc, char** argv) else if (arg == "-V" || arg == "--version") version(); #if ETH_EVMJIT - else if (arg == "-J" || arg == "--jit") + else if (arg == "--vm=jit") VMFactory::setKind(VMKind::JIT); - else if (arg == "--smart") + else if (arg == "--vm=smart") VMFactory::setKind(VMKind::Smart); #endif else if (arg == "--mnemonics") diff --git a/neth/main.cpp b/neth/main.cpp index a55c3d559..cd2fe39b4 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -101,7 +101,7 @@ void help() << " -x,--peers Attempt to connect to given number of peers (default: 5)." << endl << " -V,--version Show the version and exit." << endl #if ETH_EVMJIT - << " --jit Use EVM JIT (default: off)." << endl + << " --vm= Select VM. Options are: jit, smart. (default: interpreter)" << endl #endif ; exit(0); @@ -514,15 +514,12 @@ int main(int argc, char** argv) return -1; } } - else if (arg == "--jit") - { #if ETH_EVMJIT - jit = true; -#else - cerr << "EVM JIT not enabled" << endl; - return -1; + else if (arg == "--vm=jit") + VMFactory::setKind(VMKind::JIT); + else if (arg == "--vm=smart") + VMFactory::setKind(VMKind::Smart); #endif - } else if (arg == "-h" || arg == "--help") help(); else if (arg == "-V" || arg == "--version") @@ -551,7 +548,7 @@ int main(int argc, char** argv) mode == NodeMode::Full ? set{"eth", "shh"} : set(), netPrefs, &nodesState); - + web3.setIdealPeerCount(peers); std::shared_ptr gasPricer = make_shared(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000)); eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr; diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 698f35122..01bb5f300 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -235,7 +235,7 @@ void ImportTest::importState(json_spirit::mObject& _o, State& _state) } void ImportTest::importTransaction(json_spirit::mObject& _o) -{ +{ if (_o.count("secretKey") > 0) { assert(_o.count("nonce") > 0); @@ -728,7 +728,7 @@ Options::Options() for (auto i = 0; i < argc; ++i) { auto arg = std::string{argv[i]}; - if (arg == "--jit") + if (arg == "--jit" || arg == "--vm=jit") // TODO: Remove deprecated option "--jit" eth::VMFactory::setKind(eth::VMKind::JIT); else if (arg == "--vm=smart") eth::VMFactory::setKind(eth::VMKind::Smart); From 6dcc16cb7ad57fe0158f336ee3f08aa50163b46b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 3 Jul 2015 14:11:50 +0200 Subject: [PATCH 126/290] Exetend VM selection options in AlethZero. --- alethzero/Main.ui | 58 +++++++++++++++++++++++++++---------------- alethzero/MainWin.cpp | 54 +++++++++++++++++++++++++++++++--------- alethzero/MainWin.h | 9 +++++-- 3 files changed, 86 insertions(+), 35 deletions(-) diff --git a/alethzero/Main.ui b/alethzero/Main.ui index f798437e6..24afcb656 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -44,14 +44,14 @@ 0 bytes used - - - - - - - - + + + + + + + + @@ -132,7 +132,7 @@ 0 0 1617 - 24 + 25 @@ -192,8 +192,11 @@ + + + + - @@ -1696,17 +1699,6 @@ font-size: 14pt &Clear Pending - - - true - - - false - - - Use &LLVM-EVM - - &Kill Account @@ -1782,6 +1774,30 @@ font-size: 14pt &Gas Prices... + + + true + + + Interpreter + + + + + true + + + JIT + + + + + true + + + Smart + + diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 821022abc..c69e6e391 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -239,6 +239,21 @@ Main::Main(QWidget *parent) : ethereum()->setDefault(LatestBlock); + m_vmSelectionGroup = new QActionGroup{ui->menu_Debug}; + m_vmSelectionGroup->addAction(ui->vmInterpreter); + m_vmSelectionGroup->addAction(ui->vmJIT); + m_vmSelectionGroup->addAction(ui->vmSmart); + m_vmSelectionGroup->setExclusive(true); + +#if ETH_EVMJIT + ui->vmSmart->setChecked(true); // Default when JIT enabled + on_vmSmart_triggered(); +#else + ui->vmInterpreter->setChecked(true); + ui->vmJIT->setEnabled(false); + ui->vmSmart->setEnabled(false); +#endif + readSettings(); m_transact = new Transact(this, this); @@ -247,10 +262,6 @@ Main::Main(QWidget *parent) : #if !ETH_FATDB removeDockWidget(ui->dockWidget_accounts); -#endif -#if !ETH_EVMJIT - ui->jitvm->setEnabled(false); - ui->jitvm->setChecked(false); #endif installWatches(); startTimer(100); @@ -723,7 +734,8 @@ void Main::writeSettings() s.setValue("url", ui->urlEdit->text()); s.setValue("privateChain", m_privateChain); s.setValue("verbosity", ui->verbosity->value()); - s.setValue("jitvm", ui->jitvm->isChecked()); + if (auto vm = m_vmSelectionGroup->checkedAction()) + s.setValue("vm", vm->text()); bytes d = m_webThree->saveNetwork(); if (!d.empty()) @@ -814,8 +826,28 @@ void Main::readSettings(bool _skipGeometry) m_privateChain = s.value("privateChain", "").toString(); ui->usePrivate->setChecked(m_privateChain.size()); ui->verbosity->setValue(s.value("verbosity", 1).toInt()); - ui->jitvm->setChecked(s.value("jitvm", true).toBool()); - on_jitvm_triggered(); + +#if ETH_EVMJIT // We care only if JIT is enabled. Otherwise it can cause misconfiguration. + auto vmName = s.value("vm").toString(); + if (!vmName.isEmpty()) + { + if (vmName == ui->vmInterpreter->text()) + { + ui->vmInterpreter->setChecked(true); + on_vmInterpreter_triggered(); + } + else if (vmName == ui->vmJIT->text()) + { + ui->vmJIT->setChecked(true); + on_vmJIT_triggered(); + } + else if (vmName == ui->vmSmart->text()) + { + ui->vmSmart->setChecked(true); + on_vmSmart_triggered(); + } + } +#endif ui->urlEdit->setText(s.value("url", "about:blank").toString()); //http://gavwood.com/gavcoin.html on_urlEdit_returnPressed(); @@ -992,11 +1024,9 @@ void Main::on_usePrivate_triggered() on_killBlockchain_triggered(); } -void Main::on_jitvm_triggered() -{ - bool jit = ui->jitvm->isChecked(); - VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter); -} +void Main::on_vmInterpreter_triggered() { VMFactory::setKind(VMKind::Interpreter); } +void Main::on_vmJIT_triggered() { VMFactory::setKind(VMKind::JIT); } +void Main::on_vmSmart_triggered() { VMFactory::setKind(VMKind::Smart); } void Main::on_urlEdit_returnPressed() { diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index f8a6fa6c7..5ea1f5515 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -44,6 +44,7 @@ #include "Connect.h" class QListWidgetItem; +class QActionGroup; namespace Ui { class Main; @@ -182,8 +183,10 @@ private slots: void on_forceMining_triggered(); void on_usePrivate_triggered(); void on_turboMining_triggered(); - void on_jitvm_triggered(); void on_retryUnknown_triggered(); + void on_vmInterpreter_triggered(); + void on_vmJIT_triggered(); + void on_vmSmart_triggered(); // Debugger void on_debugCurrent_triggered(); @@ -271,6 +274,8 @@ private: dev::Address m_nameReg; dev::Address m_beneficiary; + QActionGroup* m_vmSelectionGroup = nullptr; + QList> m_consoleHistory; QMutex m_logLock; QString m_logHistory; @@ -286,6 +291,6 @@ private: std::unique_ptr m_dappHost; DappLoader* m_dappLoader; QWebEnginePage* m_webPage; - + Connect m_connect; }; From 9eb7c6a528e40d239b1916d628c675aab1bff1f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 3 Jul 2015 14:12:31 +0200 Subject: [PATCH 127/290] Reduce SmartVM logs verbosity. --- libevm/SmartVM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevm/SmartVM.cpp b/libevm/SmartVM.cpp index 3fb5be8c5..3a97a99e7 100644 --- a/libevm/SmartVM.cpp +++ b/libevm/SmartVM.cpp @@ -36,7 +36,7 @@ namespace eth { namespace { - struct JitInfo: LogChannel { static const char* name() { return "JIT"; }; static const int verbosity = 0; }; + struct JitInfo: LogChannel { static const char* name() { return "JIT"; }; static const int verbosity = 11; }; using HitMap = std::unordered_map; From 91a954dd9da6fc927b9f6b7e455fcfbfd9abbc7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 3 Jul 2015 14:27:17 +0200 Subject: [PATCH 128/290] Reapply --vm option changes to eth. --- eth/main.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index e60da08f5..43721b819 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -194,7 +194,7 @@ void help() << "General Options:" << endl << " -d,--db-path Load database from path (default: " << getDataDir() << ")" << endl #if ETH_EVMJIT || !ETH_TRUE - << " -J,--jit Enable EVM JIT (default: off)." << endl + << " --vm= Select VM. Options are: jit, smart. (default: interpreter)" << endl #endif << " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (default: 8)." << endl << " -V,--version Show the version and exit." << endl @@ -1441,8 +1441,10 @@ int main(int argc, char** argv) } } #if ETH_EVMJIT - else if (arg == "-J" || arg == "--jit") - jit = true; + else if (arg == "--vm=jit") + VMFactory::setKind(VMKind::JIT); + else if (arg == "--vm=smart") + VMFactory::setKind(VMKind::Smart); #endif else if (arg == "-h" || arg == "--help") help(); @@ -1479,7 +1481,7 @@ int main(int argc, char** argv) g_logPost = [&](std::string const& a, char const*){ static SpinLock s_lock; SpinGuard l(s_lock); - + if (g_silence) logbuf += a + "\n"; else @@ -1764,4 +1766,3 @@ int main(int argc, char** argv) writeFile((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp", netData); return 0; } - From 064dfa51e28fbe31d5c17e41c09e53bb0a988387 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 3 Jul 2015 14:43:09 +0200 Subject: [PATCH 129/290] More leniency over status when upgrading, avoid continual retrying. --- libethereum/Utility.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libethereum/Utility.cpp b/libethereum/Utility.cpp index a9158a363..966ec4f56 100644 --- a/libethereum/Utility.cpp +++ b/libethereum/Utility.cpp @@ -27,6 +27,7 @@ #include #include #include +#include "CanonBlockChain.h" #include "Defaults.h" using namespace std; using namespace dev; @@ -104,7 +105,7 @@ void dev::eth::upgradeDatabase(std::string const& _basePath) { auto minorProtocolVersion = (unsigned)status[1]; auto databaseVersion = (unsigned)status[2]; - auto genesisHash = (h256)status[3]; + auto genesisHash = status.itemCount() > 3 ? (h256)status[3] : CanonBlockChain::genesis().hash(); string chainPath = path + "/" + toHex(genesisHash.ref().cropped(0, 4)); string extrasPath = chainPath + "/" + toString(databaseVersion); @@ -121,8 +122,6 @@ void dev::eth::upgradeDatabase(std::string const& _basePath) fs::rename(path + "/details", extrasPath + "/extras"); fs::rename(path + "/state", extrasPath + "/state"); writeFile(extrasPath + "/minor", rlp(minorProtocolVersion)); - - fs::remove_all(path + "/status"); } } } @@ -130,6 +129,8 @@ void dev::eth::upgradeDatabase(std::string const& _basePath) { cwarn << "Couldn't upgrade - bad status"; } + + fs::rename(path + "/status", path + "/status.old"); } } From 136bd963d4f52cd0ad264f5e7e5881ab799f6c56 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 3 Jul 2015 14:48:40 +0200 Subject: [PATCH 130/290] Slightly more useful errors in the case of upgrade failure. --- libethereum/Utility.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libethereum/Utility.cpp b/libethereum/Utility.cpp index 966ec4f56..e02012cd5 100644 --- a/libethereum/Utility.cpp +++ b/libethereum/Utility.cpp @@ -125,9 +125,13 @@ void dev::eth::upgradeDatabase(std::string const& _basePath) } } } + catch (Exception& ex) + { + cwarn << "Couldn't upgrade: " << ex.what() << boost::diagnostic_information(ex); + } catch (...) { - cwarn << "Couldn't upgrade - bad status"; + cwarn << "Couldn't upgrade. Some issue with moving files around. Probably easiest just to redownload."; } fs::rename(path + "/status", path + "/status.old"); From bd15597f7fe34b095f78d1f1add0963b9d374017 Mon Sep 17 00:00:00 2001 From: subtly Date: Fri, 3 Jul 2015 08:51:36 -0400 Subject: [PATCH 131/290] oops. get v from signature. --- libdevcrypto/Common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index fccb005f4..eca0521cf 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -186,7 +186,7 @@ Public dev::recover(Signature const& _sig, h256 const& _message) #ifdef ETH_HAVE_SECP256K1 bytes o(65); int pubkeylen; - if (!secp256k1_ecdsa_recover_compact(_message.data(), h256::size, _sig.data(), o.data(), &pubkeylen, false, o[64])) + if (!secp256k1_ecdsa_recover_compact(_message.data(), h256::size, _sig.data(), o.data(), &pubkeylen, false, _sig[64])) return Public(); return FixedHash<64>(o.data()+1, Public::ConstructFromPointer); #else From 2081ac1412631edc7a970f21511c1dc26ff96f74 Mon Sep 17 00:00:00 2001 From: subtly Date: Fri, 3 Jul 2015 08:52:46 -0400 Subject: [PATCH 132/290] fix failing peer test. --- test/libp2p/peer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libp2p/peer.cpp b/test/libp2p/peer.cpp index 8f37ce164..e84e86027 100644 --- a/test/libp2p/peer.cpp +++ b/test/libp2p/peer.cpp @@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(host) auto node2 = host2.id(); host2.start(); - while (!host2.isStarted()) + while (!host2.haveNetwork()) this_thread::sleep_for(chrono::milliseconds(20)); host1.addNode(node2, NodeIPEndpoint(bi::address::from_string("127.0.0.1"), host2prefs.listenPort, host2prefs.listenPort)); From 16b62e5a8472fca3b4c0d2f7328dcb443903a02f Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 3 Jul 2015 14:57:24 +0200 Subject: [PATCH 133/290] Renamed actualSizeOfPrefix to sizeAsEncoded. --- libdevcore/RLP.cpp | 10 +++++----- libdevcore/RLP.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libdevcore/RLP.cpp b/libdevcore/RLP.cpp index e3dc09a13..7e419e42b 100644 --- a/libdevcore/RLP.cpp +++ b/libdevcore/RLP.cpp @@ -50,7 +50,7 @@ RLP::iterator& RLP::iterator::operator++() if (m_remaining) { m_currentItem.retarget(m_currentItem.next().data(), m_remaining); - m_currentItem = m_currentItem.cropped(0, actualSizeOfPrefix(m_currentItem)); + m_currentItem = m_currentItem.cropped(0, sizeAsEncoded(m_currentItem)); m_remaining -= std::min(m_remaining, m_currentItem.size()); } else @@ -63,7 +63,7 @@ RLP::iterator::iterator(RLP const& _parent, bool _begin) if (_begin && _parent.isList()) { auto pl = _parent.payload(); - m_currentItem = pl.cropped(0, actualSizeOfPrefix(pl)); + m_currentItem = pl.cropped(0, sizeAsEncoded(pl)); m_remaining = pl.size() - m_currentItem.size(); } else @@ -77,14 +77,14 @@ RLP RLP::operator[](size_t _i) const { if (_i < m_lastIndex) { - m_lastEnd = actualSizeOfPrefix(payload()); + m_lastEnd = sizeAsEncoded(payload()); m_lastItem = payload().cropped(0, m_lastEnd); m_lastIndex = 0; } for (; m_lastIndex < _i && m_lastItem.size(); ++m_lastIndex) { m_lastItem = payload().cropped(m_lastEnd); - m_lastItem = m_lastItem.cropped(0, actualSizeOfPrefix(m_lastItem)); + m_lastItem = m_lastItem.cropped(0, sizeAsEncoded(m_lastItem)); m_lastEnd += m_lastItem.size(); } return RLP(m_lastItem, ThrowOnFail | FailIfTooSmall); @@ -206,7 +206,7 @@ size_t RLP::items() const bytesConstRef d = payload().cropped(0, length()); size_t i = 0; for (; d.size(); ++i) - d = d.cropped(actualSizeOfPrefix(d)); + d = d.cropped(sizeAsEncoded(d)); return i; } return 0; diff --git a/libdevcore/RLP.h b/libdevcore/RLP.h index e124ea2b6..0a4d1b88b 100644 --- a/libdevcore/RLP.h +++ b/libdevcore/RLP.h @@ -327,8 +327,8 @@ private: /// @returns the number of data items. size_t items() const; - /// @returns the "actualSize" of the RLP encoded in the largest prefix of @a _data and throws on error. - static size_t actualSizeOfPrefix(bytesConstRef _data) { return RLP(_data, ThrowOnFail | FailIfTooSmall).actualSize(); } + /// @returns the size encoded into the RLP in @a _data and throws if _data is too short. + static size_t sizeAsEncoded(bytesConstRef _data) { return RLP(_data, ThrowOnFail | FailIfTooSmall).actualSize(); } /// Our byte data. bytesConstRef m_data; From ff112cb94c90a6017f64508b429093b97173506d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 3 Jul 2015 15:16:51 +0200 Subject: [PATCH 134/290] Make --vm command line option syntax consistent with other options. --- eth/main.cpp | 21 ++++++++++++++++----- ethvm/main.cpp | 23 +++++++++++++++++------ neth/main.cpp | 21 ++++++++++++++++----- test/TestHelper.cpp | 18 ++++++++++++++---- 4 files changed, 63 insertions(+), 20 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 43721b819..7d269d944 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -194,7 +194,7 @@ void help() << "General Options:" << endl << " -d,--db-path Load database from path (default: " << getDataDir() << ")" << endl #if ETH_EVMJIT || !ETH_TRUE - << " --vm= Select VM. Options are: jit, smart. (default: interpreter)" << endl + << " --vm Select VM. Options are: interpreter, jit, smart. (default: interpreter)" << endl #endif << " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (default: 8)." << endl << " -V,--version Show the version and exit." << endl @@ -1441,10 +1441,21 @@ int main(int argc, char** argv) } } #if ETH_EVMJIT - else if (arg == "--vm=jit") - VMFactory::setKind(VMKind::JIT); - else if (arg == "--vm=smart") - VMFactory::setKind(VMKind::Smart); + else if (arg == "--vm" && i + 1 < argc) + { + string vmKind = argv[++i]; + if (vmKind == "interpreter") + VMFactory::setKind(VMKind::Interpreter); + else if (vmKind == "jit") + VMFactory::setKind(VMKind::JIT); + else if (vmKind == "smart") + VMFactory::setKind(VMKind::Smart); + else + { + cerr << "Unknown VM kind: " << vmKind << endl; + return -1; + } + } #endif else if (arg == "-h" || arg == "--help") help(); diff --git a/ethvm/main.cpp b/ethvm/main.cpp index 64413b5a4..46442d4ee 100644 --- a/ethvm/main.cpp +++ b/ethvm/main.cpp @@ -43,10 +43,10 @@ void help() << " --gas-price Transaction's gas price' should be (default: 0)." << endl << " --sender Transaction sender should be (default: 0000...0069)." << endl << " --origin Transaction origin should be (default: 0000...0069)." << endl -#if ETH_EVMJIT || !ETH_TRUETRUE +#if ETH_EVMJIT || !ETH_TRUE << endl << "VM options:" << endl - << " --vm= Select VM. Options are: jit, smart. (default: interpreter)" << endl + << " --vm Select VM. Options are: interpreter, jit, smart. (default: interpreter)" << endl #endif << endl << "Options for trace:" << endl @@ -96,10 +96,21 @@ int main(int argc, char** argv) else if (arg == "-V" || arg == "--version") version(); #if ETH_EVMJIT - else if (arg == "--vm=jit") - VMFactory::setKind(VMKind::JIT); - else if (arg == "--vm=smart") - VMFactory::setKind(VMKind::Smart); + else if (arg == "--vm" && i + 1 < argc) + { + string vmKind = argv[++i]; + if (vmKind == "interpreter") + VMFactory::setKind(VMKind::Interpreter); + else if (vmKind == "jit") + VMFactory::setKind(VMKind::JIT); + else if (vmKind == "smart") + VMFactory::setKind(VMKind::Smart); + else + { + cerr << "Unknown VM kind: " << vmKind << endl; + return -1; + } + } #endif else if (arg == "--mnemonics") st.setShowMnemonics(); diff --git a/neth/main.cpp b/neth/main.cpp index cd2fe39b4..65f46735f 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -101,7 +101,7 @@ void help() << " -x,--peers Attempt to connect to given number of peers (default: 5)." << endl << " -V,--version Show the version and exit." << endl #if ETH_EVMJIT - << " --vm= Select VM. Options are: jit, smart. (default: interpreter)" << endl + << " --vm Select VM. Options are: interpreter, jit, smart. (default: interpreter)" << endl #endif ; exit(0); @@ -515,10 +515,21 @@ int main(int argc, char** argv) } } #if ETH_EVMJIT - else if (arg == "--vm=jit") - VMFactory::setKind(VMKind::JIT); - else if (arg == "--vm=smart") - VMFactory::setKind(VMKind::Smart); + else if (arg == "--vm" && i + 1 < argc) + { + string vmKind = argv[++i]; + if (vmKind == "interpreter") + VMFactory::setKind(VMKind::Interpreter); + else if (vmKind == "jit") + VMFactory::setKind(VMKind::JIT); + else if (vmKind == "smart") + VMFactory::setKind(VMKind::Smart); + else + { + cerr << "Unknown VM kind: " << vmKind << endl; + return -1; + } + } #endif else if (arg == "-h" || arg == "--help") help(); diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 01bb5f300..b3dee72ec 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -728,10 +728,20 @@ Options::Options() for (auto i = 0; i < argc; ++i) { auto arg = std::string{argv[i]}; - if (arg == "--jit" || arg == "--vm=jit") // TODO: Remove deprecated option "--jit" - eth::VMFactory::setKind(eth::VMKind::JIT); - else if (arg == "--vm=smart") - eth::VMFactory::setKind(eth::VMKind::Smart); + if (arg == "--vm" && i + 1 < argc) + { + string vmKind = argv[++i]; + if (vmKind == "interpreter") + VMFactory::setKind(VMKind::Interpreter); + else if (vmKind == "jit") + VMFactory::setKind(VMKind::JIT); + else if (vmKind == "smart") + VMFactory::setKind(VMKind::Smart); + else + cerr << "Unknown VM kind: " << vmKind << endl; + } + else if (arg == "--jit") // TODO: Remove deprecated option "--jit" + VMFactory::setKind(VMKind::JIT); else if (arg == "--vmtrace") vmtrace = true; else if (arg == "--filltests") From 7527a684f99ffbbef86f9f45a28a08db7fedabed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 3 Jul 2015 15:20:30 +0200 Subject: [PATCH 135/290] Remove old FIXME comment. --- libevm/SmartVM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevm/SmartVM.cpp b/libevm/SmartVM.cpp index 3a97a99e7..fe1c9e346 100644 --- a/libevm/SmartVM.cpp +++ b/libevm/SmartVM.cpp @@ -117,7 +117,7 @@ bytesConstRef SmartVM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _ auto vmKind = VMKind::Interpreter; // default VM // Jitted EVM code already in memory? - if (evmjit::JIT::isCodeReady(eth2jit(codeHash))) // FIXME: JIT::isCodeReady is not thread-safe + if (evmjit::JIT::isCodeReady(eth2jit(codeHash))) { clog(JitInfo) << "JIT: " << codeHash; vmKind = VMKind::JIT; From ca487600a3b261f9f029e84b58a0a543f59ace97 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 3 Jul 2015 15:44:47 +0200 Subject: [PATCH 136/290] Multiple directories involved now. --- libethereum/State.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index b383d0a6a..a000d628a 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -64,7 +64,7 @@ OverlayDB State::openDB(std::string const& _basePath, WithExisting _we) } path += "/" + toHex(CanonBlockChain::genesis().hash().ref().cropped(0, 4)) + "/" + toString(c_databaseVersion); - boost::filesystem::create_directory(path); + boost::filesystem::create_directories(path); ldb::Options o; o.max_open_files = 256; From 881e9fbad7af62d5f8f8fd6c42b12ef7c45e3bc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 3 Jul 2015 16:47:58 +0200 Subject: [PATCH 137/290] Use Guard alias and DEV_GUARDED macro in SmartVM. --- CodingStandards.txt | 3 +-- libevm/SmartVM.cpp | 11 ++++------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/CodingStandards.txt b/CodingStandards.txt index 66a61f6ae..a065928d3 100644 --- a/CodingStandards.txt +++ b/CodingStandards.txt @@ -196,7 +196,7 @@ a. Prefer 'using' to 'typedef'. e.g. using ints = std::vector; rather than b. Generally avoid shortening a standard form that already includes all important information: - e.g. stick to shared_ptr rather than shortening to ptr. c. Where there are exceptions to this (due to excessive use and clear meaning), note the change prominently and use it consistently. -- e.g. using Guard = boost::lock_guard; ///< Guard is used throughout the codebase since it's clear in meaning and used commonly. +- e.g. using Guard = std::lock_guard; ///< Guard is used throughout the codebase since it's clear in meaning and used commonly. d. In general expressions should be roughly as important/semantically meaningful as the space they occupy. @@ -226,4 +226,3 @@ a. Includes should go in order of lower level (STL -> boost -> libdevcore -> lib #include b. The only exception to the above rule is the top of a .cpp file where its corresponding header should be located. - diff --git a/libevm/SmartVM.cpp b/libevm/SmartVM.cpp index fe1c9e346..add43302e 100644 --- a/libevm/SmartVM.cpp +++ b/libevm/SmartVM.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include "VMFactory.h" @@ -92,20 +93,16 @@ namespace ~JitWorker() { - { - std::lock_guard lock{x_mutex}; + DEV_GUARDED(x_mutex) m_finished = true; - } m_cv.notify_one(); m_worker.join(); } void push(JitTask&& _task) { - { - std::lock_guard lock(x_mutex); - m_queue.push(std::move(_task)); - } + DEV_GUARDED(x_mutex) + m_queue.push(std::move(_task)); m_cv.notify_one(); } }; From 5bc72e037c439e9331459af7cfa1bcb4e6699c91 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Jul 2015 17:16:27 +0200 Subject: [PATCH 138/290] ethconsole on windows --- cmake/Findv8.cmake | 40 +++++++++++++++++++++++++++++++++---- ethconsole/CMakeLists.txt | 2 -- libjsconsole/CMakeLists.txt | 5 ++++- libjsconsole/JSConsole.h | 2 +- libjsengine/JSEngine.h | 2 +- 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/cmake/Findv8.cmake b/cmake/Findv8.cmake index 2451c708f..63e281820 100644 --- a/cmake/Findv8.cmake +++ b/cmake/Findv8.cmake @@ -31,12 +31,44 @@ set(V8_LIBRARIES ${V8_LIBRARY}) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") find_library( - V8_LIBRARY_DEBUG - NAMES v8d - DOC "v8 debug library" + V8_BASE_LIBRARY + NAMES v8_base + DOC "v8 base library" + ) + + find_library( + V8_NO_SNAPSHOT_LIBRARY + NAMES v8_nosnapshot + DOC "v8 nosnapshot library" + ) + + find_library( + V8_SNAPSHOT_LIBRARY + NAMES v8_snapshot + DOC "v8 snapshotlibrary" ) - set(V8_LIBRARIES optimized ${V8_LIBRARIES} debug ${V8_LIBRARY_DEBUG}) + set(V8_LIBRARIES ${V8_BASE_LIBRARY} ${V8_SNAPSHOT_LIBRARY} ${V8_NO_SNAPSHOT_LIBRARY}) + + find_library( + V8_BASE_LIBRARY_DEBUG + NAMES v8_based + DOC "v8 base library" + ) + + find_library( + V8_NO_SNAPSHOT_LIBRARY_DEBUG + NAMES v8_nosnapshotd + DOC "v8 nosnapshot library" + ) + + find_library( + V8_SNAPSHOT_LIBRARY_DEBUG + NAMES v8_snapshotd + DOC "v8 snapshotlibrary" + ) + + set(V8_LIBRARIES optimized ${V8_LIBRARIES} debug ${V8_BASE_LIBRARY_DEBUG} ${V8_SNAPSHOT_LIBRARY_DEBUG} ${V8_NO_SNAPSHOT_LIBRARY_DEBUG}) endif() diff --git a/ethconsole/CMakeLists.txt b/ethconsole/CMakeLists.txt index 08fa7ca83..0101320d0 100644 --- a/ethconsole/CMakeLists.txt +++ b/ethconsole/CMakeLists.txt @@ -13,9 +13,7 @@ set(EXECUTABLE ethconsole) file(GLOB HEADERS "*.h") add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) - target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES}) -target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${CURL_LIBRARIES}) if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) diff --git a/libjsconsole/CMakeLists.txt b/libjsconsole/CMakeLists.txt index f2bd8ac02..ab94a62dd 100644 --- a/libjsconsole/CMakeLists.txt +++ b/libjsconsole/CMakeLists.txt @@ -12,7 +12,9 @@ aux_source_directory(. SRC_LIST) include_directories(BEFORE ${V8_INCLUDE_DIRS}) include_directories(BEFORE ..) -include_directories(${READLINE_INCLUDE_DIRS}) +if (READLINE_FOUND) + include_directories(${READLINE_INCLUDE_DIRS}) +endif() include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) include_directories(${CURL_INCLUDE_DIRS}) @@ -31,6 +33,7 @@ target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${CURL_LIBRARIES}) if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) + target_link_libraries(${EXECUTABLE} "ws2_32" "winmm") eth_copy_dlls(${EXECUTABLE} CURL_DLLS) endif() diff --git a/libjsconsole/JSConsole.h b/libjsconsole/JSConsole.h index 8042dd6bb..9c7256557 100644 --- a/libjsconsole/JSConsole.h +++ b/libjsconsole/JSConsole.h @@ -65,7 +65,7 @@ public: free(buff); } #else - std::cout << propmtForIndentionLevel(openBrackets) << std::endl << std::flush; + std::cout << promptForIndentionLevel(openBrackets) << std::endl << std::flush; std::getline(std::cin, rl); #endif if (rl.length() > 0) diff --git a/libjsengine/JSEngine.h b/libjsengine/JSEngine.h index ce54379a1..afd7292bd 100644 --- a/libjsengine/JSEngine.h +++ b/libjsengine/JSEngine.h @@ -29,7 +29,7 @@ namespace eth { class JSException: public std::exception {}; -class JSPrintException: public JSException { char const* what() const noexcept { return "Cannot print expression!"; } }; +class JSPrintException: public JSException { char const* what() const { return "Cannot print expression!"; } }; class JSString { From d3ff3814476e8e30e7afde22ee822e388d5296f1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 30 Jun 2015 11:54:51 +0200 Subject: [PATCH 139/290] Memory structs. --- libsolidity/CompilerUtils.cpp | 55 +++++++-- libsolidity/ExpressionCompiler.cpp | 5 +- libsolidity/LValue.cpp | 74 ++++++----- libsolidity/LValue.h | 2 +- libsolidity/Types.cpp | 32 +++++ libsolidity/Types.h | 5 +- test/libsolidity/SolidityEndToEndTest.cpp | 143 ++++++++++++++++++++++ 7 files changed, 271 insertions(+), 45 deletions(-) diff --git a/libsolidity/CompilerUtils.cpp b/libsolidity/CompilerUtils.cpp index 208d7cecc..eab20e0eb 100644 --- a/libsolidity/CompilerUtils.cpp +++ b/libsolidity/CompilerUtils.cpp @@ -436,19 +436,54 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp } case Type::Category::Struct: { - //@todo we can probably use some of the code for arrays here. solAssert(targetTypeCategory == stackTypeCategory, ""); auto& targetType = dynamic_cast(_targetType); - auto& stackType = dynamic_cast(_typeOnStack); + auto& typeOnStack = dynamic_cast(_typeOnStack); solAssert( - targetType.location() == DataLocation::Storage && - stackType.location() == DataLocation::Storage, - "Non-storage structs not yet implemented." - ); - solAssert( - targetType.isPointer(), - "Type conversion to non-pointer struct requested." - ); + targetType.location() != DataLocation::CallData && + typeOnStack.location() != DataLocation::CallData + , ""); + switch (targetType.location()) + { + case DataLocation::Storage: + // Other cases are done explicitly in LValue::storeValue, and only possible by assignment. + solAssert( + targetType.isPointer() && + typeOnStack.location() == DataLocation::Storage, + "Invalid conversion to storage type." + ); + break; + case DataLocation::Memory: + // Copy the array to a free position in memory, unless it is already in memory. + if (typeOnStack.location() != DataLocation::Memory) + { + solAssert(typeOnStack.location() == DataLocation::Storage, ""); + // stack: + m_context << eth::Instruction::POP; + m_context << typeOnStack.memorySize(); + allocateMemory(); + m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2; + // stack: + for (auto const& member: typeOnStack.getMembers()) + { + if (!member.type->canLiveOutsideStorage()) + continue; + pair const& offsets = typeOnStack.getStorageOffsetsOfMember(member.name); + m_context << offsets.first << eth::Instruction::DUP3 << eth::Instruction::ADD; + m_context << u256(offsets.second); + StorageItem(m_context, *member.type).retrieveValue(SourceLocation(), true); + TypePointer targetMemberType = targetType.getMemberType(member.name); + solAssert(!!targetMemberType, "Member not found in target type."); + convertType(*member.type, *targetMemberType, true); + storeInMemoryDynamic(*targetMemberType, true); + } + m_context << eth::Instruction::POP << eth::Instruction::POP; + } + break; + case DataLocation::CallData: + solAssert(false, ""); + break; + } break; } default: diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 59907b14b..b36c72832 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -155,8 +155,6 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) TypePointer type = _assignment.getRightHandSide().getType(); if (!_assignment.getType()->dataStoredIn(DataLocation::Storage)) { - //@todo we should delay conversion here if RHS is not in memory, LHS is a MemoryItem - // and not dynamically-sized. utils().convertType(*type, *_assignment.getType()); type = _assignment.getType(); } @@ -691,7 +689,8 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) } case DataLocation::Memory: { - solAssert(false, "Member access for memory structs not yet implemented."); + m_context << type.memoryOffsetOfMember(member) << eth::Instruction::ADD; + setLValue(_memberAccess, *_memberAccess.getType()); break; } default: diff --git a/libsolidity/LValue.cpp b/libsolidity/LValue.cpp index 7eec478b3..f3be86783 100644 --- a/libsolidity/LValue.cpp +++ b/libsolidity/LValue.cpp @@ -47,6 +47,7 @@ void StackVariable::retrieveValue(SourceLocation const& _location, bool) const errinfo_sourceLocation(_location) << errinfo_comment("Stack too deep, try removing local variables.") ); + solAssert(stackPos + 1 >= m_size, "Size and stack pos mismatch."); for (unsigned i = 0; i < m_size; ++i) m_context << eth::dupInstruction(stackPos + 1); } @@ -175,6 +176,7 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _location, bool _move) const { + CompilerUtils utils(m_context); // stack: value storage_key storage_offset if (m_dataType.isValueType()) { @@ -238,52 +240,66 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc dynamic_cast(m_dataType), dynamic_cast(_sourceType)); if (_move) - CompilerUtils(m_context).popStackElement(_sourceType); + utils.popStackElement(_sourceType); } else if (m_dataType.getCategory() == Type::Category::Struct) { - // stack layout: source_ref source_offset target_ref target_offset + // stack layout: source_ref [source_offset] target_ref target_offset // note that we have structs, so offsets should be zero and are ignored auto const& structType = dynamic_cast(m_dataType); + auto const& sourceType = dynamic_cast(_sourceType); solAssert( - structType.structDefinition() == - dynamic_cast(_sourceType).structDefinition(), + structType.structDefinition() == sourceType.structDefinition(), "Struct assignment with conversion." ); + solAssert(sourceType.location() != DataLocation::CallData, "Structs in calldata not supported."); for (auto const& member: structType.getMembers()) { // assign each member that is not a mapping TypePointer const& memberType = member.type; if (memberType->getCategory() == Type::Category::Mapping) continue; + TypePointer sourceMemberType = sourceType.getMemberType(member.name); + if (sourceType.location() == DataLocation::Storage) + { + // stack layout: source_ref source_offset target_ref target_offset + pair const& offsets = sourceType.getStorageOffsetsOfMember(member.name); + m_context << offsets.first << eth::Instruction::DUP5 << eth::Instruction::ADD; + m_context << u256(offsets.second); + // stack: source_ref source_off target_ref target_off source_member_ref source_member_off + StorageItem(m_context, *sourceMemberType).retrieveValue(_location, true); + // stack: source_ref source_off target_ref target_off source_value... + } + else + { + solAssert(sourceType.location() == DataLocation::Memory, ""); + // stack layout: source_ref target_ref target_offset + TypePointer sourceMemberType = sourceType.getMemberType(member.name); + m_context << sourceType.memoryOffsetOfMember(member.name); + m_context << eth::Instruction::DUP4 << eth::Instruction::ADD; + MemoryItem(m_context, *sourceMemberType).retrieveValue(_location, true); + // stack layout: source_ref target_ref target_offset source_value... + } + unsigned stackSize = sourceMemberType->getSizeOnStack(); pair const& offsets = structType.getStorageOffsetsOfMember(member.name); - m_context - << offsets.first << u256(offsets.second) - << eth::Instruction::DUP6 << eth::Instruction::DUP3 - << eth::Instruction::ADD << eth::Instruction::DUP2; - // stack: source_ref source_off target_ref target_off member_slot_offset member_byte_offset source_member_ref source_member_off - StorageItem(m_context, *memberType).retrieveValue(_location, true); - // stack: source_ref source_off target_ref target_off member_offset source_value... - solAssert( - 4 + memberType->getSizeOnStack() <= 16, - "Stack too deep, try removing local varibales." - ); - m_context - << eth::dupInstruction(4 + memberType->getSizeOnStack()) - << eth::dupInstruction(3 + memberType->getSizeOnStack()) << eth::Instruction::ADD - << eth::dupInstruction(2 + memberType->getSizeOnStack()); - // stack: source_ref source_off target_ref target_off member_slot_offset member_byte_offset source_value... target_member_ref target_member_byte_off - StorageItem(m_context, *memberType).storeValue(*memberType, _location, true); - m_context << eth::Instruction::POP << eth::Instruction::POP; + m_context << eth::dupInstruction(2 + stackSize) << offsets.first << eth::Instruction::ADD; + m_context << u256(offsets.second); + // stack: source_ref [source_off] target_ref target_off source_value... target_member_ref target_member_byte_off + StorageItem(m_context, *memberType).storeValue(*sourceMemberType, _location, true); } + // stack layout: source_ref [source_offset] target_ref target_offset + unsigned sourceStackSize = sourceType.getSizeOnStack(); if (_move) - m_context - << eth::Instruction::POP << eth::Instruction::POP - << eth::Instruction::POP << eth::Instruction::POP; - else - m_context - << eth::Instruction::SWAP2 << eth::Instruction::POP - << eth::Instruction::SWAP2 << eth::Instruction::POP; + utils.popStackSlots(2 + sourceType.getSizeOnStack()); + else if (sourceType.getSizeOnStack() >= 1) + { + // remove the source ref + solAssert(sourceStackSize <= 2, ""); + m_context << eth::swapInstruction(sourceStackSize); + if (sourceStackSize == 2) + m_context << eth::Instruction::POP; + m_context << eth::Instruction::SWAP2 << eth::Instruction::POP; + } } else BOOST_THROW_EXCEPTION( diff --git a/libsolidity/LValue.h b/libsolidity/LValue.h index 882b3626e..a93df9f9d 100644 --- a/libsolidity/LValue.h +++ b/libsolidity/LValue.h @@ -103,7 +103,7 @@ private: class MemoryItem: public LValue { public: - MemoryItem(CompilerContext& _compilerContext, Type const& _type, bool _padded); + MemoryItem(CompilerContext& _compilerContext, Type const& _type, bool _padded = true); virtual unsigned sizeOnStack() const override { return 1; } virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; virtual void storeValue( diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index c1769d000..ef70f0e01 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -999,6 +999,15 @@ unsigned StructType::getCalldataEncodedSize(bool _padded) const return size; } +u256 StructType::memorySize() const +{ + u256 size; + for (auto const& member: getMembers()) + if (member.type->canLiveOutsideStorage()) + size += member.type->memoryHeadSize(); + return size; +} + u256 StructType::getStorageSize() const { return max(1, getMembers().getStorageSize()); @@ -1012,6 +1021,17 @@ bool StructType::canLiveOutsideStorage() const return true; } +unsigned StructType::getSizeOnStack() const +{ + switch (location()) + { + case DataLocation::Storage: + return 2; // slot and offset + default: + return 1; + } +} + string StructType::toString(bool _short) const { string ret = "struct " + m_struct.getName(); @@ -1054,6 +1074,18 @@ pair const& StructType::getStorageOffsetsOfMember(string const& return *offsets; } +u256 StructType::memoryOffsetOfMember(string const& _name) const +{ + u256 offset; + for (auto const& member: getMembers()) + if (member.name == _name) + return offset; + else + offset += member.type->memoryHeadSize(); + solAssert(false, "Member not found in struct."); + return 0; +} + TypePointer EnumType::unaryOperatorResult(Token::Value _operator) const { return _operator == Token::Delete ? make_shared() : TypePointer(); diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 6b03b1ae2..b64b1d9b3 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -543,14 +543,14 @@ class StructType: public ReferenceType public: virtual Category getCategory() const override { return Category::Struct; } explicit StructType(StructDefinition const& _struct): - //@todo only storage until we have non-storage structs ReferenceType(DataLocation::Storage), m_struct(_struct) {} virtual bool isImplicitlyConvertibleTo(const Type& _convertTo) const override; virtual bool operator==(Type const& _other) const override; virtual unsigned getCalldataEncodedSize(bool _padded) const override; + u256 memorySize() const; virtual u256 getStorageSize() const override; virtual bool canLiveOutsideStorage() const override; - virtual unsigned getSizeOnStack() const override { return 2; } + virtual unsigned getSizeOnStack() const override; virtual std::string toString(bool _short) const override; virtual MemberList const& getMembers() const override; @@ -558,6 +558,7 @@ public: TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override; std::pair const& getStorageOffsetsOfMember(std::string const& _name) const; + u256 memoryOffsetOfMember(std::string const& _name) const; StructDefinition const& structDefinition() const { return m_struct; } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index a2dbc35e6..5ad8e6f3d 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -4806,6 +4806,149 @@ BOOST_AUTO_TEST_CASE(memory_arrays_dynamic_index_access_write) BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x20), u256(4), data)); } +BOOST_AUTO_TEST_CASE(memory_structs_read_write) +{ + char const* sourceCode = R"( + contract Test { + struct S { uint8 x; uint16 y; uint z; uint8[2] a; } + S[5] data; + function testInit() returns (uint8 x, uint16 y, uint z, uint8 a, bool flag) { + S[2] memory d; + x = d[0].x; + y = d[0].y; + z = d[0].z; + a = d[0].a[1]; + flag = true; + } + function testCopyRead() returns (uint8 x, uint16 y, uint z, uint8 a) { + data[2].x = 1; + data[2].y = 2; + data[2].z = 3; + data[2].a[1] = 4; + S memory s = data[2]; + x = s.x; + y = s.y; + z = s.z; + a = s.a[1]; + } + function testAssign() returns (uint8 x, uint16 y, uint z, uint8 a) { + S memory s; + s.x = 1; + s.y = 2; + s.z = 3; + s.a[1] = 4; + x = s.x; + y = s.y; + z = s.z; + a = s.a[1]; + } + } + )"; + compileAndRun(sourceCode, 0, "Test"); + + BOOST_CHECK(callContractFunction("testInit()") == encodeArgs(u256(0), u256(0), u256(0), u256(0), true)); + BOOST_CHECK(callContractFunction("testCopyRead()") == encodeArgs(u256(1), u256(2), u256(3), u256(4))); + BOOST_CHECK(callContractFunction("testAssign()") == encodeArgs(u256(1), u256(2), u256(3), u256(4))); +} + +BOOST_AUTO_TEST_CASE(memory_structs_as_function_args) +{ + char const* sourceCode = R"( + contract Test { + struct S { uint8 x; uint16 y; uint z; } + function test() returns (uint x, uint y, uint z) { + S memory data = combine(1, 2, 3); + x = extract(data, 0); + y = extract(data, 1); + z = extract(data, 2); + } + function extract(S s, uint which) internal returns (uint x) { + if (which == 0) return s.x; + else if (which == 1) return s.y; + else return s.z; + } + function combine(uint8 x, uint16 y, uint z) internal returns (S s) { + s.x = x; + s.y = y; + s.z = z; + } + } + )"; + compileAndRun(sourceCode, 0, "Test"); + + BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(1), u256(2), u256(3))); +} + +BOOST_AUTO_TEST_CASE(memory_structs_wrapped) +{ + char const* sourceCode = R"( + contract Test { + struct S { uint8 x; uint16 y; uint z; } + struct X { uint8 x; S s; } + function test() returns (uint a, uint x, uint y, uint z) { + X memory d = combine(1, 2, 3, 4); + a = extract(d, 0); + x = extract(d, 1); + y = extract(d, 2); + z = extract(d, 3); + } + function extract(X s, uint which) internal returns (uint x) { + if (which == 0) return s.x; + else if (which == 1) return s.s.x; + else if (which == 2) return s.s.y; + else return s.s.z; + } + function combine(uint8 a, uint8 x, uint16 y, uint z) internal returns (X s) { + s.x = a; + s.s.x = x; + s.s.y = y; + s.s.z = z; + } + } + )"; + compileAndRun(sourceCode, 0, "Test"); + + BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(1), u256(2), u256(3), u256(4))); +} + +BOOST_AUTO_TEST_CASE(memory_structs_wrapped_load) +{ + char const* sourceCode = R"( + contract Test { + struct S { uint8 x; uint16 y; uint z; } + struct X { uint8 x; S s; } + X m_x; + function load() returns (uint a, uint x, uint y, uint z) { + m_x.x = 1; + m_x.s.x = 2; + m_x.s.y = 3; + m_x.s.z = 4; + X memory d = m_x; + a = d.x; + x = d.s.x; + y = d.s.y; + z = d.s.z; + } + function store() returns (uint a, uint x, uint y, uint z) { + X memory d = m_x; + d.x = 1; + d.s.x = 2; + d.s.y = 3; + d.s.z = 4; + m_x = d; + a = m_x.x; + x = m_x.s.x; + y = m_x.s.y; + z = m_x.s.z; + } + } + )"; + compileAndRun(sourceCode, 0, "Test"); + + BOOST_CHECK(callContractFunction("load()") == encodeArgs(u256(1), u256(2), u256(3), u256(4))); + BOOST_CHECK(callContractFunction("store()") == encodeArgs(u256(1), u256(2), u256(3), u256(4))); +} + BOOST_AUTO_TEST_SUITE_END() } From 97dc2d61f0f7edb678fb58b8754f26387b6e4ff4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 30 Jun 2015 21:03:23 +0200 Subject: [PATCH 140/290] Fix for copying arrays to storage. --- libsolidity/LValue.cpp | 2 +- test/libsolidity/SolidityEndToEndTest.cpp | 25 +++++++++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/libsolidity/LValue.cpp b/libsolidity/LValue.cpp index f3be86783..409446638 100644 --- a/libsolidity/LValue.cpp +++ b/libsolidity/LValue.cpp @@ -240,7 +240,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc dynamic_cast(m_dataType), dynamic_cast(_sourceType)); if (_move) - utils.popStackElement(_sourceType); + utils.popStackElement(m_dataType); } else if (m_dataType.getCategory() == Type::Category::Struct) { diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 5ad8e6f3d..c631b83b7 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -4879,7 +4879,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_as_function_args) BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(1), u256(2), u256(3))); } -BOOST_AUTO_TEST_CASE(memory_structs_wrapped) +BOOST_AUTO_TEST_CASE(memory_structs_nested) { char const* sourceCode = R"( contract Test { @@ -4911,42 +4911,51 @@ BOOST_AUTO_TEST_CASE(memory_structs_wrapped) BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(1), u256(2), u256(3), u256(4))); } -BOOST_AUTO_TEST_CASE(memory_structs_wrapped_load) +BOOST_AUTO_TEST_CASE(memory_structs_nested_load) { char const* sourceCode = R"( contract Test { struct S { uint8 x; uint16 y; uint z; } - struct X { uint8 x; S s; } + struct X { uint8 x; S s; uint8[2] a; } X m_x; - function load() returns (uint a, uint x, uint y, uint z) { + function load() returns (uint a, uint x, uint y, uint z, uint a1, uint a2) { m_x.x = 1; m_x.s.x = 2; m_x.s.y = 3; m_x.s.z = 4; + m_x.a[0] = 5; + m_x.a[1] = 6; X memory d = m_x; a = d.x; x = d.s.x; y = d.s.y; z = d.s.z; + a1 = d.a[0]; + a2 = d.a[1]; } - function store() returns (uint a, uint x, uint y, uint z) { - X memory d = m_x; + function store() returns (uint a, uint x, uint y, uint z, uint a1, uint a2) { + X memory d; d.x = 1; d.s.x = 2; d.s.y = 3; d.s.z = 4; + d.a[0] = 5; + d.a[1] = 6; m_x = d; a = m_x.x; x = m_x.s.x; y = m_x.s.y; z = m_x.s.z; + a1 = m_x.a[0]; + a2 = m_x.a[1]; } } )"; compileAndRun(sourceCode, 0, "Test"); - BOOST_CHECK(callContractFunction("load()") == encodeArgs(u256(1), u256(2), u256(3), u256(4))); - BOOST_CHECK(callContractFunction("store()") == encodeArgs(u256(1), u256(2), u256(3), u256(4))); + auto out = encodeArgs(u256(1), u256(2), u256(3), u256(4), u256(5), u256(6)); + BOOST_CHECK(callContractFunction("load()") == out); + BOOST_CHECK(callContractFunction("store()") == out); } BOOST_AUTO_TEST_SUITE_END() From 905da13c34b9c78c5ace58ae96c256abff1f5f05 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 30 Jun 2015 21:08:34 +0200 Subject: [PATCH 141/290] Struct constructors. --- libsolidity/AST.cpp | 162 ++++++++++-------- libsolidity/AST.h | 6 +- libsolidity/ExpressionCompiler.cpp | 74 +++++--- libsolidity/Types.cpp | 30 +++- libsolidity/Types.h | 4 + test/libsolidity/SolidityEndToEndTest.cpp | 43 +++++ .../SolidityNameAndTypeResolution.cpp | 41 +++++ 7 files changed, 255 insertions(+), 105 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index fac4360f1..161a7d35a 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -802,12 +802,11 @@ void FunctionCall::checkTypeRequirements(TypePointers const*) m_expression->checkTypeRequirements(isPositionalCall ? &argumentTypes : nullptr); - Type const* expressionType = m_expression->getType().get(); + TypePointer const& expressionType = m_expression->getType(); + FunctionTypePointer functionType; if (isTypeConversion()) { TypeType const& type = dynamic_cast(*expressionType); - //@todo for structs, we have to check the number of arguments to be equal to the - // number of non-mapping members if (m_arguments.size() != 1) BOOST_THROW_EXCEPTION(createTypeError("Exactly one argument expected for explicit type conversion.")); if (!isPositionalCall) @@ -815,87 +814,106 @@ void FunctionCall::checkTypeRequirements(TypePointers const*) if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type.getActualType())) BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed.")); m_type = type.getActualType(); + return; } - else if (FunctionType const* functionType = dynamic_cast(expressionType)) + + if (isStructConstructorCall()) { - //@todo would be nice to create a struct type from the arguments - // and then ask if that is implicitly convertible to the struct represented by the - // function parameters - TypePointers const& parameterTypes = functionType->getParameterTypes(); - if (!functionType->takesArbitraryParameters() && parameterTypes.size() != m_arguments.size()) - BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call.")); + TypeType const& type = dynamic_cast(*expressionType); + auto const& structType = dynamic_cast(*type.getActualType()); + functionType = structType.constructorType(); + } + else + functionType = dynamic_pointer_cast(expressionType); - if (isPositionalCall) - { - // call by positional arguments - for (size_t i = 0; i < m_arguments.size(); ++i) - if ( - !functionType->takesArbitraryParameters() && - !m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i]) - ) - BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError( - "Invalid type for argument in function call. " - "Invalid implicit conversion from " + - m_arguments[i]->getType()->toString() + - " to " + - parameterTypes[i]->toString() + - " requested." - )); - } - else - { - // call by named arguments - if (functionType->takesArbitraryParameters()) - BOOST_THROW_EXCEPTION(createTypeError("Named arguments cannnot be used for functions " - "that take arbitrary parameters.")); - auto const& parameterNames = functionType->getParameterNames(); - if (parameterNames.size() != m_names.size()) - BOOST_THROW_EXCEPTION(createTypeError("Some argument names are missing.")); - - // check duplicate names - for (size_t i = 0; i < m_names.size(); i++) - for (size_t j = i + 1; j < m_names.size(); j++) - if (*m_names[i] == *m_names[j]) - BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError("Duplicate named argument.")); - - for (size_t i = 0; i < m_names.size(); i++) { - bool found = false; - for (size_t j = 0; j < parameterNames.size(); j++) { - if (parameterNames[j] == *m_names[i]) { - // check type convertible - if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[j])) - BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError( - "Invalid type for argument in function call. " - "Invalid implicit conversion from " + - m_arguments[i]->getType()->toString() + - " to " + - parameterTypes[i]->toString() + - " requested." - )); - - found = true; - break; - } + if (!functionType) + BOOST_THROW_EXCEPTION(createTypeError("Type is not callable.")); + + //@todo would be nice to create a struct type from the arguments + // and then ask if that is implicitly convertible to the struct represented by the + // function parameters + TypePointers const& parameterTypes = functionType->getParameterTypes(); + if (!functionType->takesArbitraryParameters() && parameterTypes.size() != m_arguments.size()) + BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call.")); + + if (isPositionalCall) + { + // call by positional arguments + for (size_t i = 0; i < m_arguments.size(); ++i) + if ( + !functionType->takesArbitraryParameters() && + !m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i]) + ) + BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError( + "Invalid type for argument in function call. " + "Invalid implicit conversion from " + + m_arguments[i]->getType()->toString() + + " to " + + parameterTypes[i]->toString() + + " requested." + )); + } + else + { + // call by named arguments + if (functionType->takesArbitraryParameters()) + BOOST_THROW_EXCEPTION(createTypeError( + "Named arguments cannnot be used for functions that take arbitrary parameters." + )); + auto const& parameterNames = functionType->getParameterNames(); + if (parameterNames.size() != m_names.size()) + BOOST_THROW_EXCEPTION(createTypeError("Some argument names are missing.")); + + // check duplicate names + for (size_t i = 0; i < m_names.size(); i++) + for (size_t j = i + 1; j < m_names.size(); j++) + if (*m_names[i] == *m_names[j]) + BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError("Duplicate named argument.")); + + for (size_t i = 0; i < m_names.size(); i++) { + bool found = false; + for (size_t j = 0; j < parameterNames.size(); j++) { + if (parameterNames[j] == *m_names[i]) { + // check type convertible + if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[j])) + BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError( + "Invalid type for argument in function call. " + "Invalid implicit conversion from " + + m_arguments[i]->getType()->toString() + + " to " + + parameterTypes[i]->toString() + + " requested." + )); + + found = true; + break; } - if (!found) - BOOST_THROW_EXCEPTION(createTypeError("Named argument does not match function declaration.")); } + if (!found) + BOOST_THROW_EXCEPTION(createTypeError("Named argument does not match function declaration.")); } - - // @todo actually the return type should be an anonymous struct, - // but we change it to the type of the first return value until we have structs - if (functionType->getReturnParameterTypes().empty()) - m_type = make_shared(); - else - m_type = functionType->getReturnParameterTypes().front(); } + + // @todo actually the return type should be an anonymous struct, + // but we change it to the type of the first return value until we have anonymous + // structs and tuples + if (functionType->getReturnParameterTypes().empty()) + m_type = make_shared(); else - BOOST_THROW_EXCEPTION(createTypeError("Type is not callable.")); + m_type = functionType->getReturnParameterTypes().front(); } bool FunctionCall::isTypeConversion() const { - return m_expression->getType()->getCategory() == Type::Category::TypeType; + return m_expression->getType()->getCategory() == Type::Category::TypeType && !isStructConstructorCall(); +} + +bool FunctionCall::isStructConstructorCall() const +{ + if (auto const* type = dynamic_cast(m_expression->getType().get())) + return type->getActualType()->getCategory() == Type::Category::Struct; + else + return false; } void NewExpression::checkTypeRequirements(TypePointers const*) diff --git a/libsolidity/AST.h b/libsolidity/AST.h index ff0d708f5..658b3de9f 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -1136,9 +1136,11 @@ public: std::vector> getArguments() const { return {m_arguments.begin(), m_arguments.end()}; } std::vector> const& getNames() const { return m_names; } - /// Returns true if this is not an actual function call, but an explicit type conversion - /// or constructor call. + /// @returns true if this is not an actual function call, but an explicit type conversion. + /// Returns false for struct constructor calls. bool isTypeConversion() const; + /// @return true if this is a constructor call for a struct, i.e. StructName(...). + bool isStructConstructorCall() const; private: ASTPointer m_expression; diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index b36c72832..81f5d08a5 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -313,38 +313,66 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) using Location = FunctionType::Location; if (_functionCall.isTypeConversion()) { - //@todo struct construction solAssert(_functionCall.getArguments().size() == 1, ""); solAssert(_functionCall.getNames().empty(), ""); Expression const& firstArgument = *_functionCall.getArguments().front(); firstArgument.accept(*this); utils().convertType(*firstArgument.getType(), *_functionCall.getType()); + return false; } + + FunctionTypePointer functionType; + if (_functionCall.isStructConstructorCall()) + { + TypeType const& type = dynamic_cast(*_functionCall.getExpression().getType()); + auto const& structType = dynamic_cast(*type.getActualType()); + functionType = structType.constructorType(); + } + else + functionType = dynamic_pointer_cast(_functionCall.getExpression().getType()); + + TypePointers const& parameterTypes = functionType->getParameterTypes(); + vector> const& callArguments = _functionCall.getArguments(); + vector> const& callArgumentNames = _functionCall.getNames(); + if (!functionType->takesArbitraryParameters()) + solAssert(callArguments.size() == parameterTypes.size(), ""); + + vector> arguments; + if (callArgumentNames.empty()) + // normal arguments + arguments = callArguments; else + // named arguments + for (auto const& parameterName: functionType->getParameterNames()) + { + bool found = false; + for (size_t j = 0; j < callArgumentNames.size() && !found; j++) + if ((found = (parameterName == *callArgumentNames[j]))) + // we found the actual parameter position + arguments.push_back(callArguments[j]); + solAssert(found, ""); + } + + if (_functionCall.isStructConstructorCall()) { - FunctionType const& function = dynamic_cast(*_functionCall.getExpression().getType()); - TypePointers const& parameterTypes = function.getParameterTypes(); - vector> const& callArguments = _functionCall.getArguments(); - vector> const& callArgumentNames = _functionCall.getNames(); - if (!function.takesArbitraryParameters()) - solAssert(callArguments.size() == parameterTypes.size(), ""); - - vector> arguments; - if (callArgumentNames.empty()) - // normal arguments - arguments = callArguments; - else - // named arguments - for (auto const& parameterName: function.getParameterNames()) - { - bool found = false; - for (size_t j = 0; j < callArgumentNames.size() && !found; j++) - if ((found = (parameterName == *callArgumentNames[j]))) - // we found the actual parameter position - arguments.push_back(callArguments[j]); - solAssert(found, ""); - } + TypeType const& type = dynamic_cast(*_functionCall.getExpression().getType()); + auto const& structType = dynamic_cast(*type.getActualType()); + + m_context << u256(max(32u, structType.getCalldataEncodedSize(true))); + utils().allocateMemory(); + m_context << eth::Instruction::DUP1; + for (unsigned i = 0; i < arguments.size(); ++i) + { + arguments[i]->accept(*this); + utils().convertType(*arguments[i]->getType(), *functionType->getParameterTypes()[i]); + utils().storeInMemoryDynamic(*functionType->getParameterTypes()[i]); + } + m_context << eth::Instruction::POP; + } + else + { + FunctionType const& function = *functionType; switch (function.getLocation()) { case Location::Internal: diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index ef70f0e01..96cf3f7ef 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -30,11 +30,8 @@ #include using namespace std; - -namespace dev -{ -namespace solidity -{ +using namespace dev; +using namespace dev::solidity; void StorageOffsets::computeOffsets(TypePointers const& _types) { @@ -1067,6 +1064,26 @@ TypePointer StructType::copyForLocation(DataLocation _location, bool _isPointer) return copy; } +FunctionTypePointer StructType::constructorType() const +{ + TypePointers paramTypes; + strings paramNames; + for (auto const& member: getMembers()) + { + if (!member.type->canLiveOutsideStorage()) + continue; + paramNames.push_back(member.name); + paramTypes.push_back(copyForLocationIfReference(DataLocation::Memory, member.type)); + } + return make_shared( + paramTypes, + TypePointers{copyForLocation(DataLocation::Memory, false)}, + paramNames, + strings(), + FunctionType::Location::Internal + ); +} + pair const& StructType::getStorageOffsetsOfMember(string const& _name) const { auto const* offsets = getMembers().getMemberStorageOffset(_name); @@ -1695,6 +1712,3 @@ string MagicType::toString(bool) const BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown kind of magic.")); } } - -} -} diff --git a/libsolidity/Types.h b/libsolidity/Types.h index b64b1d9b3..ba53a913b 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -557,6 +557,10 @@ public: TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override; + /// @returns a function that peforms the type conversion between a list of struct members + /// and a memory struct of this type. + FunctionTypePointer constructorType() const; + std::pair const& getStorageOffsetsOfMember(std::string const& _name) const; u256 memoryOffsetOfMember(std::string const& _name) const; diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index c631b83b7..3ddb05528 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -4958,6 +4958,49 @@ BOOST_AUTO_TEST_CASE(memory_structs_nested_load) BOOST_CHECK(callContractFunction("store()") == out); } +BOOST_AUTO_TEST_CASE(struct_constructor_nested) +{ + char const* sourceCode = R"( + contract C { + struct X { uint x1; uint x2; } + struct S { uint s1; uint[3] s2; X s3; } + S s; + function C() { + uint[3] memory s2; + s2[1] = 9; + s = S(1, s2, X(4, 5)); + } + function get() returns (uint s1, uint[3] s2, uint x1, uint x2) + { + s1 = s.s1; + s2 = s.s2; + x1 = s.s3.x1; + x2 = s.s3.x2; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + + auto out = encodeArgs(u256(1), u256(0), u256(9), u256(0), u256(4), u256(5)); + BOOST_CHECK(callContractFunction("get()") == out); +} + +BOOST_AUTO_TEST_CASE(struct_named_constructor) +{ + char const* sourceCode = R"( + contract C { + struct S { uint a; bool x; } + S public s; + function C() { + s = S({a: 1, x: true}); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + + BOOST_CHECK(callContractFunction("s()") == encodeArgs(u256(1), true)); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 4914ef975..50fcdbbe5 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2056,6 +2056,47 @@ BOOST_AUTO_TEST_CASE(memory_arrays_not_resizeable) BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); } +BOOST_AUTO_TEST_CASE(struct_constructor) +{ + char const* sourceCode = R"( + contract C { + struct S { uint a; bool x; } + function f() { + S memory s = S(1, true); + } + } + )"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCode)); +} + +BOOST_AUTO_TEST_CASE(struct_constructor_nested) +{ + char const* sourceCode = R"( + contract C { + struct X { uint x1; uint x2; } + struct S { uint s1; uint[3] s2; X s3; } + function f() { + uint[3] memory s2; + S memory s = S(1, s2, X(4, 5)); + } + } + )"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCode)); +} + +BOOST_AUTO_TEST_CASE(struct_named_constructor) +{ + char const* sourceCode = R"( + contract C { + struct S { uint a; bool x; } + function f() { + S memory s = S({a: 1, x: true}); + } + } + )"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCode)); +} + BOOST_AUTO_TEST_SUITE_END() } From c7f8bcf9c5bc6c562946b9e20c1cc3824e4f6cb8 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 3 Jul 2015 18:15:05 +0200 Subject: [PATCH 142/290] Style and some assertion messages. --- libsolidity/CompilerUtils.cpp | 2 +- libsolidity/ExpressionCompiler.cpp | 2 +- libsolidity/LValue.cpp | 2 +- libsolidity/Types.cpp | 7 ++----- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/libsolidity/CompilerUtils.cpp b/libsolidity/CompilerUtils.cpp index eab20e0eb..ed6a6cf7c 100644 --- a/libsolidity/CompilerUtils.cpp +++ b/libsolidity/CompilerUtils.cpp @@ -481,7 +481,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp } break; case DataLocation::CallData: - solAssert(false, ""); + solAssert(false, "Invalid type conversion target location CallData."); break; } break; diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 81f5d08a5..13cd40327 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -324,7 +324,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) FunctionTypePointer functionType; if (_functionCall.isStructConstructorCall()) { - TypeType const& type = dynamic_cast(*_functionCall.getExpression().getType()); + auto const& type = dynamic_cast(*_functionCall.getExpression().getType()); auto const& structType = dynamic_cast(*type.getActualType()); functionType = structType.constructorType(); } diff --git a/libsolidity/LValue.cpp b/libsolidity/LValue.cpp index 409446638..7b5879e44 100644 --- a/libsolidity/LValue.cpp +++ b/libsolidity/LValue.cpp @@ -294,7 +294,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc else if (sourceType.getSizeOnStack() >= 1) { // remove the source ref - solAssert(sourceStackSize <= 2, ""); + solAssert(sourceStackSize <= 2, "Invalid stack size."); m_context << eth::swapInstruction(sourceStackSize); if (sourceStackSize == 2) m_context << eth::Instruction::POP; diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 96cf3f7ef..5a949299e 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -1020,13 +1020,10 @@ bool StructType::canLiveOutsideStorage() const unsigned StructType::getSizeOnStack() const { - switch (location()) - { - case DataLocation::Storage: + if (location() == DataLocation::Storage) return 2; // slot and offset - default: + else return 1; - } } string StructType::toString(bool _short) const From 5cca2fa4f4d6e6a9877bb4713a5646432733840b Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 3 Jul 2015 22:02:47 +0200 Subject: [PATCH 143/290] fixed "eth --console" --- eth/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index e60da08f5..cf68d98a7 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -1736,13 +1736,13 @@ int main(int argc, char** argv) { #if ETH_JSCONSOLE || !ETH_TRUE JSLocalConsole console; - // TODO: set port properly? + shared_ptr rpcServer = make_shared(*console.connector(), web3, make_shared([&](){ return web3.ethereum(); }, getAccountPassword, keyManager), vector(), keyManager, *gasPricer); while (!g_exit) { console.readExpression(); stopMiningAfterXBlocks(c, n, mining); } - jsonrpcServer->StopListening(); + rpcServer->StopListening(); #endif } else From d272ff8ceeba49b60760411082745b6cdb33d83c Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Thu, 2 Jul 2015 22:21:37 +0200 Subject: [PATCH 144/290] intermediate --- libwhisper/WhisperHost.cpp | 2 +- libwhisper/WhisperPeer.cpp | 17 +++++++++++------ test/libwhisper/whisperMessage.cpp | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/libwhisper/WhisperHost.cpp b/libwhisper/WhisperHost.cpp index f9ff33658..4a1f4c8b4 100644 --- a/libwhisper/WhisperHost.cpp +++ b/libwhisper/WhisperHost.cpp @@ -68,7 +68,7 @@ void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p) m_expiryQueue.insert(make_pair(_m.expiry(), h)); } - int rating = 1; // rating for local host is based upon: 1. installed watch; 2. proof of work + int rating = 1; // rating for local host is based upon: 1. installed watch; 2. ttl; 3. proof of work if (_p) // incoming message from remote peer DEV_GUARDED(m_filterLock) diff --git a/libwhisper/WhisperPeer.cpp b/libwhisper/WhisperPeer.cpp index 393c3749c..27662926e 100644 --- a/libwhisper/WhisperPeer.cpp +++ b/libwhisper/WhisperPeer.cpp @@ -121,17 +121,22 @@ unsigned WhisperPeer::ratingForPeer(Envelope const& e) const { // we try to estimate, how valuable this nessage will be for the remote peer, // according to the following criteria: - // 1. bloom filter - // 2. proof of work + // 1. bloom filter + // 2. time to live + // 3. proof of work - static const unsigned BloomFilterMatchReward = 256; // vlad todo: move to common.h unsigned rating = 0; DEV_GUARDED(x_bloom) if (e.matchesBloomFilter(m_bloom)) - rating += BloomFilterMatchReward; - - rating += e.sha3().firstBitSet(); + ++rating; + + rating *= 256; + unsigned ttlReward = (256 > e.ttl() ? 256 - e.ttl() : 0); + rating += ttlReward; + + rating *= 256; + rating += e.workProved(); return rating; } diff --git a/test/libwhisper/whisperMessage.cpp b/test/libwhisper/whisperMessage.cpp index 343573713..1db3352ac 100644 --- a/test/libwhisper/whisperMessage.cpp +++ b/test/libwhisper/whisperMessage.cpp @@ -89,4 +89,18 @@ BOOST_AUTO_TEST_CASE(seal) sealAndOpenSingleMessage(i); } +BOOST_AUTO_TEST_CASE(work) +{ + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing proof of work..."; + + Secret zero; + Topics topics = createRandomTopics(0xDEAD); + bytes const payload = createRandomPayload(0xFFFFF); + Message m(payload); + Envelope e = m.seal(zero, topics, 1, 50); + unsigned x = e.workProved(); + BOOST_REQUIRE(x > 0); +} + BOOST_AUTO_TEST_SUITE_END() From 8dfabff96c707bc56d8b8082c750011b656b5447 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Fri, 3 Jul 2015 01:14:56 +0200 Subject: [PATCH 145/290] proof of work bugfix --- libwhisper/Message.cpp | 10 +++++----- libwhisper/Message.h | 1 + test/libwhisper/whisperMessage.cpp | 18 ++++++++++++------ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/libwhisper/Message.cpp b/libwhisper/Message.cpp index 0b235b984..2d15ee315 100644 --- a/libwhisper/Message.cpp +++ b/libwhisper/Message.cpp @@ -161,24 +161,24 @@ unsigned Envelope::workProved() const void Envelope::proveWork(unsigned _ms) { - // PoW h256 d[2]; d[0] = sha3(WithoutNonce); - uint32_t& n = *(uint32_t*)&(d[1][28]); unsigned bestBitSet = 0; bytesConstRef chuck(d[0].data(), 64); chrono::high_resolution_clock::time_point then = chrono::high_resolution_clock::now() + chrono::milliseconds(_ms); - for (n = 0; chrono::high_resolution_clock::now() < then; ) + while (chrono::high_resolution_clock::now() < then) // do it rounds of 1024 for efficiency - for (unsigned i = 0; i < 1024; ++i, ++n) + for (unsigned i = 0; i < 1024; ++i) { auto fbs = dev::sha3(chuck).firstBitSet(); if (fbs > bestBitSet) { bestBitSet = fbs; - m_nonce = n; + m_nonce = (h256::Arith)d[1]; } + + incrementHash(d[1]); } } diff --git a/libwhisper/Message.h b/libwhisper/Message.h index ae61f210a..e382a328b 100644 --- a/libwhisper/Message.h +++ b/libwhisper/Message.h @@ -81,6 +81,7 @@ public: void proveWork(unsigned _ms); bool matchesBloomFilter(TopicBloomFilterHash const& f) const; + static void incrementHash(h256& _h) { for (unsigned i = h256::size; i > 0 && ++_h[--i] > 0; ) {} } private: Envelope(unsigned _exp, unsigned _ttl, AbridgedTopics const& _topic): m_expiry(_exp), m_ttl(_ttl), m_topic(_topic) {} diff --git a/test/libwhisper/whisperMessage.cpp b/test/libwhisper/whisperMessage.cpp index 1db3352ac..8d9a29579 100644 --- a/test/libwhisper/whisperMessage.cpp +++ b/test/libwhisper/whisperMessage.cpp @@ -95,12 +95,18 @@ BOOST_AUTO_TEST_CASE(work) cnote << "Testing proof of work..."; Secret zero; - Topics topics = createRandomTopics(0xDEAD); - bytes const payload = createRandomPayload(0xFFFFF); - Message m(payload); - Envelope e = m.seal(zero, topics, 1, 50); - unsigned x = e.workProved(); - BOOST_REQUIRE(x > 0); + unsigned r = 0xC0DEFEED; + + for (int i = 0; i < 20; ++i) + { + Topics topics = createRandomTopics(++r); + bytes const payload = createRandomPayload(++r); + Message m(payload); + Envelope e = m.seal(zero, topics, 1, 50); + unsigned x = e.workProved(); + cnote << x; + BOOST_REQUIRE(x > 4); + } } BOOST_AUTO_TEST_SUITE_END() From db2be2a15b24834fdb376bc8b1d13a39a0d00306 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Fri, 3 Jul 2015 13:19:07 +0200 Subject: [PATCH 146/290] rating system updated --- libwhisper/Message.h | 2 +- libwhisper/WhisperHost.cpp | 26 +++++++++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/libwhisper/Message.h b/libwhisper/Message.h index e382a328b..fb89576e9 100644 --- a/libwhisper/Message.h +++ b/libwhisper/Message.h @@ -81,7 +81,7 @@ public: void proveWork(unsigned _ms); bool matchesBloomFilter(TopicBloomFilterHash const& f) const; - static void incrementHash(h256& _h) { for (unsigned i = h256::size; i > 0 && ++_h[--i] > 0; ) {} } + static void incrementHash(h256& _h) { for (unsigned i = h256::size; i > 0 && !++_h[--i]; ) {} } private: Envelope(unsigned _exp, unsigned _ttl, AbridgedTopics const& _topic): m_expiry(_exp), m_ttl(_ttl), m_topic(_topic) {} diff --git a/libwhisper/WhisperHost.cpp b/libwhisper/WhisperHost.cpp index 4a1f4c8b4..5d83dd399 100644 --- a/libwhisper/WhisperHost.cpp +++ b/libwhisper/WhisperHost.cpp @@ -51,7 +51,8 @@ void WhisperHost::streamMessage(h256 _m, RLPStream& _s) const void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p) { - // this function processes messages originated both by local host (_p == null), and by remote peers (_p != null) + // this function processes both outgoing messages originated both by local host (_p == null) + // and incoming messages from remote peers (_p != null) cnote << this << ": inject: " << _m.expiry() << _m.ttl() << _m.topic() << toHex(_m.data()); @@ -68,18 +69,33 @@ void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p) m_expiryQueue.insert(make_pair(_m.expiry(), h)); } - int rating = 1; // rating for local host is based upon: 1. installed watch; 2. ttl; 3. proof of work + // rating of incoming message from remote host is assessed according to the following criteria: + // 1. installed watch match; 2. bloom filter match; 2. ttl; 3. proof of work - if (_p) // incoming message from remote peer - DEV_GUARDED(m_filterLock) + int rating = 0; + + DEV_GUARDED(m_filterLock) + if (_m.matchesBloomFilter(m_bloom)) + { + ++rating; for (auto const& f: m_filters) if (f.second.filter.matches(_m)) for (auto& i: m_watches) if (i.second.id == f.first) { i.second.changes.push_back(h); - rating += 10; // subject to review + rating += 2; } + } + + if (_p) // incoming message from remote peer + { + rating *= 256; + unsigned ttlReward = (256 > _m.ttl() ? 256 - _m.ttl() : 0); + rating += ttlReward; + rating *= 256; + rating += _m.workProved(); + } // TODO p2p: capability-based rating for (auto i: peerSessions()) From 15106cef742909134dc61c5d86fd577642ca744d Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Fri, 3 Jul 2015 16:33:36 +0200 Subject: [PATCH 147/290] another test introduced --- libwhisper/WhisperPeer.cpp | 5 ++--- test/libwhisper/whisperTopic.cpp | 36 +++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/libwhisper/WhisperPeer.cpp b/libwhisper/WhisperPeer.cpp index 27662926e..30a188f2d 100644 --- a/libwhisper/WhisperPeer.cpp +++ b/libwhisper/WhisperPeer.cpp @@ -127,9 +127,8 @@ unsigned WhisperPeer::ratingForPeer(Envelope const& e) const unsigned rating = 0; - DEV_GUARDED(x_bloom) - if (e.matchesBloomFilter(m_bloom)) - ++rating; + if (e.matchesBloomFilter(bloom())) + ++rating; rating *= 256; unsigned ttlReward = (256 > e.ttl() ? 256 - e.ttl() : 0); diff --git a/test/libwhisper/whisperTopic.cpp b/test/libwhisper/whisperTopic.cpp index 82825c5d0..8d0f603bb 100644 --- a/test/libwhisper/whisperTopic.cpp +++ b/test/libwhisper/whisperTopic.cpp @@ -78,7 +78,6 @@ BOOST_AUTO_TEST_CASE(topic) } this_thread::sleep_for(chrono::milliseconds(50)); } - }); Host host2("Test", NetworkPreferences("127.0.0.1", 30300, false)); @@ -384,4 +383,39 @@ BOOST_AUTO_TEST_CASE(topicAdvertising) whost2->uninstallWatch(w2); } +BOOST_AUTO_TEST_CASE(selfAddressed) +{ + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing self-addressed messaging with bloom filter matching..."; + + char const* text = "deterministic pseudorandom test"; + BuildTopicMask mask(text); + + Host host("first", NetworkPreferences("127.0.0.1", 30305, false)); + auto wh = host.registerCapability(new WhisperHost()); + auto watch = wh->installWatch(BuildTopicMask(text)); + + unsigned const sample = 0xFEED; + KeyPair us = KeyPair::create(); + wh->post(us.sec(), RLPStream().append(sample).out(), BuildTopic(text)); + + TopicBloomFilterHash f = wh->bloom(); + Envelope e = Message(RLPStream().append(sample).out()).seal(us.sec(), BuildTopic(text), 50, 50); + bool ok = e.matchesBloomFilter(f); + BOOST_REQUIRE(ok); + + this_thread::sleep_for(chrono::milliseconds(50)); + + unsigned single = 0; + unsigned result = 0; + for (auto j: wh->checkWatch(watch)) + { + Message msg = wh->envelope(j).open(wh->fullTopics(watch)); + single = RLP(msg.payload()).toInt(); + result += single; + } + + BOOST_REQUIRE_EQUAL(sample, result); +} + BOOST_AUTO_TEST_SUITE_END() From 52f4f289c1bf71f9a6e96529b8c76178f838d004 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Sat, 4 Jul 2015 01:09:31 +0200 Subject: [PATCH 148/290] rating initial version complete --- libwhisper/BloomFilter.h | 54 ++++++++++++++++++++++++++---- libwhisper/Common.cpp | 2 +- libwhisper/Message.cpp | 3 +- test/libwhisper/bloomFilter.cpp | 23 +++++++++---- test/libwhisper/whisperMessage.cpp | 2 +- 5 files changed, 68 insertions(+), 16 deletions(-) diff --git a/libwhisper/BloomFilter.h b/libwhisper/BloomFilter.h index 7b5d179c6..32ac15043 100644 --- a/libwhisper/BloomFilter.h +++ b/libwhisper/BloomFilter.h @@ -35,17 +35,20 @@ public: TopicBloomFilterBase() { init(); } TopicBloomFilterBase(FixedHash const& _h): FixedHash(_h) { init(); } - void addBloom(dev::shh::AbridgedTopic const& _h) { addRaw(_h.template bloomPart()); } - void removeBloom(dev::shh::AbridgedTopic const& _h) { removeRaw(_h.template bloomPart()); } - bool containsBloom(dev::shh::AbridgedTopic const& _h) const { return this->contains(_h.template bloomPart()); } + void addBloom(AbridgedTopic const& _h) { addRaw(bloom(_h)); } + void removeBloom(AbridgedTopic const& _h) { removeRaw(bloom(_h)); } + bool containsBloom(AbridgedTopic const& _h) const { return this->contains(bloom(_h)); } void addRaw(FixedHash const& _h); void removeRaw(FixedHash const& _h); bool containsRaw(FixedHash const& _h) const { return this->contains(_h); } + + static FixedHash bloom(AbridgedTopic const& _h); + static void setBit(FixedHash& _h, unsigned index); + static bool isBitSet(FixedHash const& _h, unsigned _index); private: void init() { for (unsigned i = 0; i < CounterSize; ++i) m_refCounter[i] = 0; } - static bool isBitSet(FixedHash const& _h, unsigned _index); static const unsigned CounterSize = N * 8; std::array m_refCounter; @@ -83,12 +86,51 @@ void TopicBloomFilterBase::removeRaw(FixedHash const& _h) template bool TopicBloomFilterBase::isBitSet(FixedHash const& _h, unsigned _index) -{ +{ unsigned iByte = _index / 8; - unsigned iBit = _index % 8; + unsigned iBit = _index & 0x7; return (_h[iByte] & c_powerOfTwoBitMmask[iBit]) != 0; } +template +void TopicBloomFilterBase::setBit(FixedHash& _h, unsigned _index) +{ + unsigned iByte = _index / 8; + unsigned iBit = _index & 0x7; + _h[iByte] |= c_powerOfTwoBitMmask[iBit]; +} + +template +FixedHash TopicBloomFilterBase::bloom(AbridgedTopic const& _h) +{ + // The size of AbridgedTopic is 32 bits, and 27 of them participate in this algorithm. + + // We need to review the algorithm if any of the following constants will be changed. + static_assert(4 == AbridgedTopic::size, "wrong template parameter in TopicBloomFilterBase::bloom()"); + static_assert(3 == BitsPerBloom, "wrong template parameter in TopicBloomFilterBase::bloom()"); + + FixedHash ret; + + if (TopicBloomFilterSize == N) + for (unsigned i = 0; i < BitsPerBloom; ++i) + { + unsigned x = _h[i]; + if (_h[BitsPerBloom] & c_powerOfTwoBitMmask[i]) + x += 256; + + setBit(ret, x); + } + else + for (unsigned i = 0; i < BitsPerBloom; ++i) + { + unsigned x = unsigned(_h[i]) + unsigned(_h[i + 1]); + x %= N * 8; + setBit(ret, x); + } + + return ret; +} + using TopicBloomFilter = TopicBloomFilterBase; } diff --git a/libwhisper/Common.cpp b/libwhisper/Common.cpp index 7c7a9801b..4681a21b3 100644 --- a/libwhisper/Common.cpp +++ b/libwhisper/Common.cpp @@ -100,7 +100,7 @@ TopicBloomFilterHash TopicFilter::exportBloom() const TopicBloomFilterHash ret; for (TopicMask const& t: m_topicMasks) for (auto const& i: t) - ret |= i.first.template bloomPart(); + ret |= TopicBloomFilter::bloom(i.first); return ret; } diff --git a/libwhisper/Message.cpp b/libwhisper/Message.cpp index 2d15ee315..435811a3b 100644 --- a/libwhisper/Message.cpp +++ b/libwhisper/Message.cpp @@ -20,6 +20,7 @@ */ #include "Message.h" +#include "BloomFilter.h" using namespace std; using namespace dev; @@ -185,7 +186,7 @@ void Envelope::proveWork(unsigned _ms) bool Envelope::matchesBloomFilter(TopicBloomFilterHash const& f) const { for (AbridgedTopic t: m_topic) - if (f.contains(t.template bloomPart())) + if (f.contains(TopicBloomFilter::bloom(t))) return true; return false; diff --git a/test/libwhisper/bloomFilter.cpp b/test/libwhisper/bloomFilter.cpp index 197a7258d..d7d4bd849 100644 --- a/test/libwhisper/bloomFilter.cpp +++ b/test/libwhisper/bloomFilter.cpp @@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(bloomFilterRaw) BOOST_REQUIRE(!f.contains(b00110111)); } -static const unsigned DistributionTestSize = 8; +static const unsigned DistributionTestSize = TopicBloomFilterSize; static const unsigned TestArrSize = 8 * DistributionTestSize; void updateDistribution(FixedHash const& _h, array& _distribution) @@ -271,10 +271,10 @@ BOOST_AUTO_TEST_CASE(distributionRate) Topic x(0xC0FFEE); // deterministic pseudorandom value - for (unsigned i = 0; i < 22000; ++i) + for (unsigned i = 0; i < 26000; ++i) { x = sha3(x); - FixedHash h = x.template bloomPart(); + FixedHash h = TopicBloomFilter::bloom(abridge(x)); updateDistribution(h, distribution); } @@ -283,16 +283,25 @@ BOOST_AUTO_TEST_CASE(distributionRate) average += distribution[i]; average /= TestArrSize; - unsigned deviation = average / 10; // approx. 10% + unsigned deviation = average / 3; unsigned maxAllowed = average + deviation; unsigned minAllowed = average - deviation; + unsigned maximum = 0; + unsigned minimum = 0xFFFFFFFF; + for (unsigned i = 0; i < TestArrSize; ++i) { - //cnote << i << ":" << distribution[i]; - BOOST_REQUIRE(distribution[i] > minAllowed); - BOOST_REQUIRE(distribution[i] < maxAllowed); + unsigned const& z = distribution[i]; + if (z > maximum) + maximum = z; + else if (z < minimum) + minimum = z; } + + cnote << minimum << average << maximum; + BOOST_REQUIRE(minimum > minAllowed); + BOOST_REQUIRE(maximum < maxAllowed); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libwhisper/whisperMessage.cpp b/test/libwhisper/whisperMessage.cpp index 8d9a29579..f0c0aedc9 100644 --- a/test/libwhisper/whisperMessage.cpp +++ b/test/libwhisper/whisperMessage.cpp @@ -104,7 +104,7 @@ BOOST_AUTO_TEST_CASE(work) Message m(payload); Envelope e = m.seal(zero, topics, 1, 50); unsigned x = e.workProved(); - cnote << x; + //cnote << x; BOOST_REQUIRE(x > 4); } } From 1b4f530735b289771e2db3c8ec02e23e95f8fcfc Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Sat, 4 Jul 2015 13:45:45 +0200 Subject: [PATCH 149/290] FixedHash::bloomPart() bugfix: out of range --- libdevcore/FixedHash.h | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index c7c551c2b..d235dae41 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -31,6 +31,10 @@ namespace dev { +/// Compile-time calculation of Log2 of constant values. +template struct StaticLog2 { enum { result = 1 + StaticLog2::result }; }; +template <> struct StaticLog2<1> { enum { result = 0 }; }; + extern std::random_device s_fixedHashEngine; /// Fixed-size raw-byte array container type, with an API optimised for storing hashes. @@ -171,18 +175,21 @@ public: template inline FixedHash bloomPart() const { - static_assert((M & (M - 1)) == 0, "M must be power-of-two"); - static const unsigned c_bloomBits = M * 8; - unsigned mask = c_bloomBits - 1; - unsigned bloomBytes = (dev::toLog2(c_bloomBits) + 7) / 8; + unsigned const c_bloomBits = M * 8; + unsigned const c_mask = c_bloomBits - 1; + unsigned const c_bloomBytes = (StaticLog2::result + 7) / 8; + + static_assert((M & (M - 1)) == 0, "M must be power-of-two"); + static_assert(P * c_bloomBytes <= N, "out of range"); + FixedHash ret; byte const* p = data(); for (unsigned i = 0; i < P; ++i) { unsigned index = 0; - for (unsigned j = 0; j < bloomBytes; ++j, ++p) + for (unsigned j = 0; j < c_bloomBytes; ++j, ++p) index = (index << 8) | *p; - index &= mask; + index &= c_mask; ret[M - 1 - index / 8] |= (1 << (index % 8)); } return ret; From c7a516714d315eb52ceaa1ee8f3d218730c13f29 Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 3 Jul 2015 16:10:47 +0200 Subject: [PATCH 150/290] prioritized transaction queue Conflicts: libethereum/TransactionQueue.cpp msvc build fix --- libethereum/EthereumHost.cpp | 25 +-- libethereum/State.cpp | 61 ++++---- libethereum/TransactionQueue.cpp | 210 ++++++++++++++++---------- libethereum/TransactionQueue.h | 55 +++++-- libethereum/VerifiedBlock.h | 2 +- libp2p/Common.h | 2 +- test/libethereum/blockchain.cpp | 4 +- test/libethereum/transactionqueue.cpp | 108 +++++++++++++ 8 files changed, 331 insertions(+), 136 deletions(-) diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 55a1d1bf0..23089896d 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -41,6 +41,7 @@ using namespace dev::eth; using namespace p2p; unsigned const EthereumHost::c_oldProtocolVersion = 60; //TODO: remove this once v61+ is common +static unsigned const c_maxSendTransactions = 256; char const* const EthereumHost::s_stateNames[static_cast(SyncState::Size)] = {"Idle", "Waiting", "Hashes", "Blocks", "NewBlocks" }; @@ -67,8 +68,7 @@ bool EthereumHost::ensureInitialised() m_latestBlockSent = m_chain.currentHash(); clog(NetNote) << "Initialising: latest=" << m_latestBlockSent; - for (auto const& i: m_tq.transactions()) - m_transactionsSent.insert(i.first); + m_transactionsSent = m_tq.knownTransactions(); return true; } return false; @@ -114,25 +114,26 @@ void EthereumHost::doWork() void EthereumHost::maintainTransactions() { // Send any new transactions. - unordered_map, h256s> peerTransactions; - auto ts = m_tq.transactions(); - for (auto const& i: ts) + unordered_map, std::vector> peerTransactions; + auto ts = m_tq.topTransactions(c_maxSendTransactions); + for (size_t i = 0; i < ts.size(); ++i) { - bool unsent = !m_transactionsSent.count(i.first); - auto peers = get<1>(randomSelection(0, [&](EthereumPeer* p) { return p->m_requireTransactions || (unsent && !p->m_knownTransactions.count(i.first)); })); + auto const& t = ts[i]; + bool unsent = !m_transactionsSent.count(t.sha3()); + auto peers = get<1>(randomSelection(0, [&](EthereumPeer* p) { return p->m_requireTransactions || (unsent && !p->m_knownTransactions.count(t.sha3())); })); for (auto const& p: peers) - peerTransactions[p].push_back(i.first); + peerTransactions[p].push_back(i); } for (auto const& t: ts) - m_transactionsSent.insert(t.first); + m_transactionsSent.insert(t.sha3()); foreachPeer([&](shared_ptr _p) { bytes b; unsigned n = 0; - for (auto const& h: peerTransactions[_p]) + for (auto const& i: peerTransactions[_p]) { - _p->m_knownTransactions.insert(h); - b += ts[h].rlp(); + _p->m_knownTransactions.insert(ts[i].sha3()); + b += ts[i].rlp(); ++n; } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index a000d628a..5362f6f68 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -47,6 +47,7 @@ namespace fs = boost::filesystem; #define ETH_TIMED_ENACTMENTS 0 static const u256 c_blockReward = c_network == Network::Olympic ? (1500 * finney) : (5 * ether); +static const unsigned c_maxSyncTransactions = 256; const char* StateSafeExceptions::name() { return EthViolet "⚙" EthBlue " ℹ"; } const char* StateDetail::name() { return EthViolet "⚙" EthWhite " ◌"; } @@ -495,7 +496,7 @@ pair State::sync(BlockChain const& _bc, TransactionQu pair ret; ret.second = false; - auto ts = _tq.transactions(); + auto ts = _tq.topTransactions(c_maxSyncTransactions); LastHashes lh; @@ -504,27 +505,26 @@ pair State::sync(BlockChain const& _bc, TransactionQu for (int goodTxs = 1; goodTxs; ) { goodTxs = 0; - for (auto const& i: ts) - if (!m_transactionSet.count(i.first)) + for (auto const& t: ts) + if (!m_transactionSet.count(t.sha3())) { try { - if (i.second.gasPrice() >= _gp.ask(*this)) + if (t.gasPrice() >= _gp.ask(*this)) { // Timer t; if (lh.empty()) lh = _bc.lastHashes(); - execute(lh, i.second); + execute(lh, t); ret.first.push_back(m_receipts.back()); - _tq.noteGood(i); ++goodTxs; // cnote << "TX took:" << t.elapsed() * 1000; } - else if (i.second.gasPrice() < _gp.ask(*this) * 9 / 10) + else if (t.gasPrice() < _gp.ask(*this) * 9 / 10) { // less than 90% of our ask price for gas. drop. - cnote << i.first << "Dropping El Cheapo transaction (<90% of ask price)"; - _tq.drop(i.first); + cnote << t.sha3() << "Dropping El Cheapo transaction (<90% of ask price)"; + _tq.drop(t.sha3()); } } catch (InvalidNonce const& in) @@ -535,57 +535,54 @@ pair State::sync(BlockChain const& _bc, TransactionQu if (req > got) { // too old - for (Transaction const& t: m_transactions) - if (t.from() == i.second.from()) + for (Transaction const& mt: m_transactions) + { + if (mt.from() == t.from()) { - if (t.nonce() < i.second.nonce()) - { - cnote << i.first << "Dropping old transaction (nonce too low)"; - _tq.drop(i.first); - } - else if (t.nonce() == i.second.nonce() && t.gasPrice() <= i.second.gasPrice()) - { - cnote << i.first << "Dropping old transaction (gas price lower)"; - _tq.drop(i.first); - } + if (mt.nonce() < t.nonce()) + cnote << t.sha3() << "Dropping old transaction (nonce too low)"; + else if (mt.nonce() == t.nonce() && mt.gasPrice() <= t.gasPrice()) + cnote << t.sha3() << "Dropping old transaction (gas price lower)"; } + } + _tq.drop(t.sha3()); } - else if (got > req + _tq.waiting(i.second.sender())) + else if (got > req + _tq.waiting(t.sender())) { // too new - cnote << i.first << "Dropping new transaction (too many nonces ahead)"; - _tq.drop(i.first); + cnote << t.sha3() << "Dropping new transaction (too many nonces ahead)"; + _tq.drop(t.sha3()); } else - _tq.setFuture(i); + _tq.setFuture(t.sha3()); } catch (BlockGasLimitReached const& e) { bigint const& got = *boost::get_error_info(e); if (got > m_currentBlock.gasLimit) { - cnote << i.first << "Dropping over-gassy transaction (gas > block's gas limit)"; - _tq.drop(i.first); + cnote << t.sha3() << "Dropping over-gassy transaction (gas > block's gas limit)"; + _tq.drop(t.sha3()); } else { // Temporarily no gas left in current block. // OPTIMISE: could note this and then we don't evaluate until a block that does have the gas left. // for now, just leave alone. -// _tq.setFuture(i); +// _tq.setFuture(t.sha3()); } } catch (Exception const& _e) { // Something else went wrong - drop it. - cnote << i.first << "Dropping invalid transaction:" << diagnostic_information(_e); - _tq.drop(i.first); + cnote << t.sha3() << "Dropping invalid transaction:" << diagnostic_information(_e); + _tq.drop(t.sha3()); } catch (std::exception const&) { // Something else went wrong - drop it. - _tq.drop(i.first); - cnote << i.first << "Transaction caused low-level exception :("; + _tq.drop(t.sha3()); + cnote << t.sha3() << "Transaction caused low-level exception :("; } } if (chrono::steady_clock::now() > deadline) diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index d2ced467e..478b4ff3c 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -95,10 +95,20 @@ ImportResult TransactionQueue::import(Transaction const& _transaction, ImportCal return ret; } -std::unordered_map TransactionQueue::transactions() const +Transactions TransactionQueue::topTransactions(unsigned _limit) const { ReadGuard l(m_lock); - return m_current; + Transactions res; + unsigned n = _limit; + for (auto t = m_current.begin(); n != 0 && t != m_current.end(); ++t, --n) + res.push_back(t->transaction); + return res; +} + +h256Hash TransactionQueue::knownTransactions() const +{ + ReadGuard l(m_lock); + return m_known; } ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transaction const& _transaction, ImportCallback const& _cb) @@ -108,35 +118,50 @@ ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transactio // Check validity of _transactionRLP as a transaction. To do this we just deserialise and attempt to determine the sender. // If it doesn't work, the signature is bad. // The transaction's nonce may yet be invalid (or, it could be "valid" but we may be missing a marginally older transaction). + assert(_h == _transaction.sha3()); // Remove any prior transaction with the same nonce but a lower gas price. // Bomb out if there's a prior transaction with higher gas price. - auto r = m_senders.equal_range(_transaction.from()); - for (auto it = r.first; it != r.second; ++it) - if (m_current.count(it->second) && m_current[it->second].nonce() == _transaction.nonce()) - if (_transaction.gasPrice() < m_current[it->second].gasPrice()) + auto cs = m_currentByAddressAndNonce.find(_transaction.from()); + if (cs != m_currentByAddressAndNonce.end()) + { + auto t = cs->second.find(_transaction.nonce()); + if (t != cs->second.end()) + { + if (_transaction.gasPrice() < (*t->second).transaction.gasPrice()) return ImportResult::OverbidGasPrice; else - { - remove_WITH_LOCK(it->second); - break; - } - else if (m_future.count(it->second) && m_future[it->second].nonce() == _transaction.nonce()) - if (_transaction.gasPrice() < m_future[it->second].gasPrice()) + remove_WITH_LOCK((*t->second).transaction.sha3()); + } + } + auto fs = m_future.find(_transaction.from()); + if (fs != m_future.end()) + { + auto t = fs->second.find(_transaction.nonce()); + if (t != fs->second.end()) + { + if (_transaction.gasPrice() < t->second.transaction.gasPrice()) return ImportResult::OverbidGasPrice; else { - remove_WITH_LOCK(it->second); - break; + fs->second.erase(t); + --m_futureSize; } - else {} - + } + } // If valid, append to blocks. insertCurrent_WITH_LOCK(make_pair(_h, _transaction)); m_known.insert(_h); if (_cb) m_callbacks[_h] = _cb; clog(TransactionQueueTraceChannel) << "Queued vaguely legit-looking transaction" << _h; + + while (m_current.size() > m_limit) + { + clog(TransactionQueueTraceChannel) << "Dropping out of bounds transaction" << _h; + remove_WITH_LOCK(m_current.rbegin()->transaction.sha3()); + } + m_onReady(); } catch (Exception const& _e) @@ -163,93 +188,111 @@ u256 TransactionQueue::maxNonce(Address const& _a) const u256 TransactionQueue::maxNonce_WITH_LOCK(Address const& _a) const { u256 ret = 0; - auto r = m_senders.equal_range(_a); - for (auto it = r.first; it != r.second; ++it) - if (m_current.count(it->second)) - { -// cdebug << it->first << "1+" << m_current.at(it->second).nonce(); - ret = max(ret, m_current.at(it->second).nonce() + 1); - } - else if (m_future.count(it->second)) - { -// cdebug << it->first << "1+" << m_future.at(it->second).nonce(); - ret = max(ret, m_future.at(it->second).nonce() + 1); - } - else - { - cwarn << "ERRROR!!!!! m_senders references non-current transaction"; - cwarn << "Sender" << it->first << "has transaction" << it->second; - cwarn << "Count of m_current for" << it->second << "is" << m_current.count(it->second); - } - return ret; + auto cs = m_currentByAddressAndNonce.find(_a); + if (cs != m_currentByAddressAndNonce.end() && !cs->second.empty()) + ret = cs->second.rbegin()->first; + auto fs = m_future.find(_a); + if (fs != m_future.end() && !fs->second.empty()) + ret = std::max(ret, fs->second.rbegin()->first); + return ret + 1; } void TransactionQueue::insertCurrent_WITH_LOCK(std::pair const& _p) { -// cdebug << "txQ::insertCurrent" << _p.first << _p.second.sender() << _p.second.nonce(); - m_senders.insert(make_pair(_p.second.sender(), _p.first)); - if (m_current.count(_p.first)) + if (m_currentByHash.count(_p.first)) + { cwarn << "Transaction hash" << _p.first << "already in current?!"; - m_current.insert(_p); -} + return; + } -bool TransactionQueue::remove_WITH_LOCK(h256 const& _txHash) -{ -// cdebug << "txQ::remove" << _txHash; - for (std::unordered_map* pool: { &m_current, &m_future }) + Transaction const& t = _p.second; + // Insert into current + auto inserted = m_currentByAddressAndNonce[t.from()].insert(std::make_pair(t.nonce(), PriorityQueue::iterator())); + PriorityQueue::iterator handle = m_current.emplace(VerifiedTransaction(t)); + inserted.first->second = handle; + m_currentByHash[_p.first] = handle; + + // Move following transactions from future to current + auto fs = m_future.find(t.from()); + if (fs != m_future.end()) { - auto pit = pool->find(_txHash); - if (pit != pool->end()) + u256 nonce = t.nonce() + 1; + auto fb = fs->second.find(nonce); + if (fb != fs->second.end()) { - auto r = m_senders.equal_range(pit->second.sender()); - for (auto i = r.first; i != r.second; ++i) - if (i->second == _txHash) - { - m_senders.erase(i); - break; - } -// cdebug << "=> nonce" << pit->second.nonce(); - pool->erase(pit); - return true; + auto ft = fb; + while (ft != fs->second.end() && ft->second.transaction.nonce() == nonce) + { + inserted = m_currentByAddressAndNonce[t.from()].insert(std::make_pair(ft->second.transaction.nonce(), PriorityQueue::iterator())); + PriorityQueue::iterator handle = m_current.emplace(move(ft->second)); + inserted.first->second = handle; + m_currentByHash[(*handle).transaction.sha3()] = handle; + --m_futureSize; + ++ft; + ++nonce; + } + fs->second.erase(fb, ft); + if (fs->second.empty()) + m_future.erase(t.from()); } } - return false; +} + +bool TransactionQueue::remove_WITH_LOCK(h256 const& _txHash) +{ + auto t = m_currentByHash.find(_txHash); + if (t == m_currentByHash.end()) + return false; + + Address from = (*t->second).transaction.from(); + auto it = m_currentByAddressAndNonce.find(from); + assert (it != m_currentByAddressAndNonce.end()); + it->second.erase((*t->second).transaction.nonce()); + m_current.erase(t->second); + m_currentByHash.erase(t); + if (it->second.empty()) + m_currentByAddressAndNonce.erase(it); + return true; } unsigned TransactionQueue::waiting(Address const& _a) const { ReadGuard l(m_lock); - auto it = m_senders.equal_range(_a); unsigned ret = 0; - for (auto i = it.first; i != it.second; ++i, ++ret) {} + auto cs = m_currentByAddressAndNonce.find(_a); + if (cs != m_currentByAddressAndNonce.end()) + ret = cs->second.size(); + auto fs = m_future.find(_a); + if (fs != m_future.end()) + ret += fs->second.size(); return ret; } -void TransactionQueue::setFuture(std::pair const& _t) +void TransactionQueue::setFuture(h256 const& _txHash) { // cdebug << "txQ::setFuture" << _t.first; WriteGuard l(m_lock); - if (m_current.count(_t.first)) - { - m_future.insert(_t); - m_current.erase(_t.first); - } -} + auto it = m_currentByHash.find(_txHash); + if (it == m_currentByHash.end()) + return; -void TransactionQueue::noteGood(std::pair const& _t) -{ -// cdebug << "txQ::noteGood" << _t.first; - WriteGuard l(m_lock); - auto r = m_senders.equal_range(_t.second.sender()); - for (auto it = r.first; it != r.second; ++it) + VerifiedTransaction const& st = *(it->second); + + Address from = st.transaction.from(); + auto& queue = m_currentByAddressAndNonce[from]; + auto& target = m_future[from]; + auto cutoff = queue.lower_bound(st.transaction.nonce()); + for (auto m = cutoff; m != queue.end(); ++m) { - auto fit = m_future.find(it->second); - if (fit != m_future.end()) - { - m_current.insert(*fit); - m_future.erase(fit); - } + VerifiedTransaction& t = const_cast(*(m->second)); // set has only const iterators. Since we are moving out of container that's fine + m_currentByHash.erase(t.transaction.sha3()); + target.emplace(t.transaction.nonce(), move(t)); + m_current.erase(m->second); + ++m_futureSize; } + queue.erase(cutoff, queue.end()); + if (queue.empty()) + m_currentByAddressAndNonce.erase(from); } void TransactionQueue::drop(h256 const& _txHash) @@ -265,3 +308,14 @@ void TransactionQueue::drop(h256 const& _txHash) remove_WITH_LOCK(_txHash); } + +void TransactionQueue::clear() +{ + WriteGuard l(m_lock); + m_known.clear(); + m_current.clear(); + m_currentByAddressAndNonce.clear(); + m_currentByHash.clear(); + m_future.clear(); + m_futureSize = 0; +} diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index d9bfef847..d92a73dab 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -43,6 +43,7 @@ enum class IfDropped { Ignore, Retry }; /** * @brief A queue of Transactions, each stored as RLP. + * Maintains a transaction queue sorted by nonce diff and gas price * @threadsafe */ class TransactionQueue @@ -50,6 +51,10 @@ class TransactionQueue public: using ImportCallback = std::function; + /// @brief TransactionQueue + /// @param _limit Maximum number of pending transactions in the queue + /// @param _futureLimit Maximum number of future nonce transactions + TransactionQueue(unsigned _limit = 1024, unsigned _futureLimit = 1024): m_current(PriorityCompare { *this }), m_limit(_limit), m_futureLimit(_futureLimit) {} ImportResult import(Transaction const& _tx, ImportCallback const& _cb = ImportCallback(), IfDropped _ik = IfDropped::Ignore); ImportResult import(bytes const& _tx, ImportCallback const& _cb = ImportCallback(), IfDropped _ik = IfDropped::Ignore) { return import(&_tx, _cb, _ik); } ImportResult import(bytesConstRef _tx, ImportCallback const& _cb = ImportCallback(), IfDropped _ik = IfDropped::Ignore); @@ -57,17 +62,40 @@ public: void drop(h256 const& _txHash); unsigned waiting(Address const& _a) const; - std::unordered_map transactions() const; - std::pair items() const { ReadGuard l(m_lock); return std::make_pair(m_current.size(), m_future.size()); } + Transactions topTransactions(unsigned _limit) const; + h256Hash knownTransactions() const; u256 maxNonce(Address const& _a) const; + void setFuture(h256 const& _t); - void setFuture(std::pair const& _t); - void noteGood(std::pair const& _t); - - void clear() { WriteGuard l(m_lock); m_senders.clear(); m_known.clear(); m_current.clear(); m_future.clear(); } + void clear(); template Handler onReady(T const& _t) { return m_onReady.add(_t); } private: + struct VerifiedTransaction + { + VerifiedTransaction(Transaction const& _t): transaction(_t) {} + VerifiedTransaction(VerifiedTransaction&& _t): transaction(std::move(_t.transaction)) {} + + VerifiedTransaction(VerifiedTransaction const&) = delete; + VerifiedTransaction operator=(VerifiedTransaction const&) = delete; + + Transaction transaction; + }; + + struct PriorityCompare + { + TransactionQueue& queue; + bool operator()(VerifiedTransaction const& _first, VerifiedTransaction const& _second) const + { + u256 const& height1 = _first.transaction.nonce() - queue.m_currentByAddressAndNonce[_first.transaction.sender()].begin()->first; + u256 const& height2 = _second.transaction.nonce() - queue.m_currentByAddressAndNonce[_second.transaction.sender()].begin()->first; + return height1 < height2 || (height1 == height2 && _first.transaction.gasPrice() > _second.transaction.gasPrice()); + } + }; + + // Use a set with dynamic comparator for minmax priority queue. The comparator takes into account min account nonce. Updating it does not affect the order. + using PriorityQueue = std::multiset; + ImportResult check_WITH_LOCK(h256 const& _h, IfDropped _ik); ImportResult manageImport_WITH_LOCK(h256 const& _h, Transaction const& _transaction, ImportCallback const& _cb); @@ -77,12 +105,19 @@ private: mutable SharedMutex m_lock; ///< General lock. h256Hash m_known; ///< Hashes of transactions in both sets. - std::unordered_multimap m_senders; ///< Mapping from the sender address to the transaction hash; useful for determining the nonce of a given sender. - std::unordered_map m_current; ///< Map of SHA3(tx) to tx. - std::unordered_map m_future; ///< For transactions that have a future nonce; we re-insert into current once the sender has a valid TX. + std::unordered_map> m_callbacks; ///< Called once. - h256Hash m_dropped; ///< Transactions that have previously been dropped. + h256Hash m_dropped; ///< Transactions that have previously been dropped + + PriorityQueue m_current; + std::unordered_map m_currentByHash; ///< Transaction hash to set ref + std::unordered_map> m_currentByAddressAndNonce; ///< Transactions grouped by account and nonce + std::unordered_map> m_future; /// Future transactions + Signal m_onReady; ///< Called when a subsequent call to import transactions will return a non-empty container. Be nice and exit fast. + unsigned m_limit; ///< Max number of pending transactions + unsigned m_futureLimit; ///< Max number of future transactions + unsigned m_futureSize = 0; ///< Current number of future transactions }; } diff --git a/libethereum/VerifiedBlock.h b/libethereum/VerifiedBlock.h index 6cafe4b2f..5d1efb7d0 100644 --- a/libethereum/VerifiedBlock.h +++ b/libethereum/VerifiedBlock.h @@ -43,7 +43,7 @@ struct VerifiedBlockRef /// @brief Verified block info, combines block data and verified info/transactions struct VerifiedBlock { - VerifiedBlock() {}; + VerifiedBlock() {} VerifiedBlock(BlockInfo&& _bi) { diff --git a/libp2p/Common.h b/libp2p/Common.h index 445ba0cca..c124115f9 100644 --- a/libp2p/Common.h +++ b/libp2p/Common.h @@ -236,7 +236,7 @@ template <> struct hash return boost::hash_range(range.begin(), range.end()); } if (_a.is_unspecified()) - return static_cast(0x3487194039229152ul); // Chosen by fair dice roll, guaranteed to be random + return static_cast(0x3487194039229152ull); // Chosen by fair dice roll, guaranteed to be random return std::hash()(_a.to_string()); } }; diff --git a/test/libethereum/blockchain.cpp b/test/libethereum/blockchain.cpp index 0314de78b..6455eee17 100644 --- a/test/libethereum/blockchain.cpp +++ b/test/libethereum/blockchain.cpp @@ -200,8 +200,8 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) //get valid transactions Transactions txList; - for (auto const& txi: txs.transactions()) - txList.push_back(txi.second); + for (auto const& txi: txs.topTransactions(std::numeric_limits::max())) + txList.push_back(txi); blObj["transactions"] = writeTransactionsToJson(txList); BlockInfo current_BlockHeader = state.info(); diff --git a/test/libethereum/transactionqueue.cpp b/test/libethereum/transactionqueue.cpp index ab85350a5..aa76681c5 100644 --- a/test/libethereum/transactionqueue.cpp +++ b/test/libethereum/transactionqueue.cpp @@ -61,4 +61,112 @@ BOOST_AUTO_TEST_CASE(maxNonce) } +BOOST_AUTO_TEST_CASE(priority) +{ + dev::eth::TransactionQueue txq; + + const u256 gasCostCheap = 10 * szabo; + const u256 gasCostMed = 20 * szabo; + const u256 gasCostHigh = 30 * szabo; + const u256 gas = 25000; + Address dest = Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"); + Secret sender1 = Secret("0x3333333333333333333333333333333333333333333333333333333333333333"); + Secret sender2 = Secret("0x4444444444444444444444444444444444444444444444444444444444444444"); + Transaction tx0(0, gasCostCheap, gas, dest, bytes(), 0, sender1 ); + Transaction tx0_1(1, gasCostMed, gas, dest, bytes(), 0, sender1 ); + Transaction tx1(0, gasCostCheap, gas, dest, bytes(), 1, sender1 ); + Transaction tx2(0, gasCostHigh, gas, dest, bytes(), 0, sender2 ); + Transaction tx3(0, gasCostCheap + 1, gas, dest, bytes(), 1, sender2 ); + Transaction tx4(0, gasCostHigh, gas, dest, bytes(), 2, sender1 ); + Transaction tx5(0, gasCostMed, gas, dest, bytes(), 2, sender2 ); + + txq.import(tx0); + BOOST_CHECK(Transactions { tx0 } == txq.topTransactions(256)); + txq.import(tx0); + BOOST_CHECK(Transactions { tx0 } == txq.topTransactions(256)); + txq.import(tx0_1); + BOOST_CHECK(Transactions { tx0_1 } == txq.topTransactions(256)); + txq.import(tx1); + BOOST_CHECK((Transactions { tx0_1, tx1 }) == txq.topTransactions(256)); + txq.import(tx2); + BOOST_CHECK((Transactions { tx2, tx0_1, tx1 }) == txq.topTransactions(256)); + txq.import(tx3); + BOOST_CHECK((Transactions { tx2, tx0_1, tx1, tx3 }) == txq.topTransactions(256)); + txq.import(tx4); + BOOST_CHECK((Transactions { tx2, tx0_1, tx1, tx3, tx4 }) == txq.topTransactions(256)); + txq.import(tx5); + BOOST_CHECK((Transactions { tx2, tx0_1, tx1, tx3, tx5, tx4 }) == txq.topTransactions(256)); + + txq.drop(tx0_1.sha3()); + BOOST_CHECK((Transactions { tx2, tx1, tx3, tx5, tx4 }) == txq.topTransactions(256)); + txq.drop(tx1.sha3()); + BOOST_CHECK((Transactions { tx2, tx3, tx5, tx4 }) == txq.topTransactions(256)); + txq.drop(tx5.sha3()); + BOOST_CHECK((Transactions { tx2, tx3, tx4 }) == txq.topTransactions(256)); + + Transaction tx6(0, gasCostMed, gas, dest, bytes(), 20, sender1 ); + txq.import(tx6); + BOOST_CHECK((Transactions { tx2, tx3, tx4, tx6 }) == txq.topTransactions(256)); + + Transaction tx7(0, gasCostMed, gas, dest, bytes(), 2, sender2 ); + txq.import(tx7); + BOOST_CHECK((Transactions { tx2, tx3, tx4, tx6, tx7 }) == txq.topTransactions(256)); +} + +BOOST_AUTO_TEST_CASE(future) +{ + dev::eth::TransactionQueue txq; + + // from a94f5374fce5edbc8e2a8697c15331677e6ebf0b + const u256 gasCostMed = 20 * szabo; + const u256 gas = 25000; + Address dest = Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"); + Secret sender = Secret("0x3333333333333333333333333333333333333333333333333333333333333333"); + Transaction tx0(0, gasCostMed, gas, dest, bytes(), 0, sender ); + Transaction tx1(0, gasCostMed, gas, dest, bytes(), 1, sender ); + Transaction tx2(0, gasCostMed, gas, dest, bytes(), 2, sender ); + Transaction tx3(0, gasCostMed, gas, dest, bytes(), 3, sender ); + Transaction tx4(0, gasCostMed, gas, dest, bytes(), 4, sender ); + + txq.import(tx0); + txq.import(tx1); + txq.import(tx2); + txq.import(tx3); + txq.import(tx4); + BOOST_CHECK((Transactions { tx0, tx1, tx2, tx3, tx4 }) == txq.topTransactions(256)); + + txq.setFuture(tx2.sha3()); + BOOST_CHECK((Transactions { tx0, tx1 }) == txq.topTransactions(256)); + + Transaction tx2_2(1, gasCostMed, gas, dest, bytes(), 2, sender ); + txq.import(tx2_2); + BOOST_CHECK((Transactions { tx0, tx1, tx2_2, tx3, tx4 }) == txq.topTransactions(256)); +} + + +BOOST_AUTO_TEST_CASE(lmits) +{ + dev::eth::TransactionQueue txq(3, 3); + const u256 gasCostMed = 20 * szabo; + const u256 gas = 25000; + Address dest = Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"); + Secret sender = Secret("0x3333333333333333333333333333333333333333333333333333333333333333"); + Secret sender2 = Secret("0x4444444444444444444444444444444444444444444444444444444444444444"); + Transaction tx0(0, gasCostMed, gas, dest, bytes(), 0, sender ); + Transaction tx1(0, gasCostMed, gas, dest, bytes(), 1, sender ); + Transaction tx2(0, gasCostMed, gas, dest, bytes(), 2, sender ); + Transaction tx3(0, gasCostMed, gas, dest, bytes(), 3, sender ); + Transaction tx4(0, gasCostMed, gas, dest, bytes(), 4, sender ); + Transaction tx5(0, gasCostMed + 1, gas, dest, bytes(), 0, sender2 ); + + txq.import(tx0); + txq.import(tx1); + txq.import(tx2); + txq.import(tx3); + txq.import(tx4); + txq.import(tx5); + BOOST_CHECK((Transactions { tx5, tx0, tx1 }) == txq.topTransactions(256)); +} + + BOOST_AUTO_TEST_SUITE_END() From 10a1ca3f11bc09d760f5f732891a0aac5cb9659f Mon Sep 17 00:00:00 2001 From: Lu Guanqun Date: Sat, 4 Jul 2015 23:51:20 +0800 Subject: [PATCH 151/290] add missing dependencies for BuildInfo.h in libwebthree and solc --- libwebthree/CMakeLists.txt | 2 ++ solc/CMakeLists.txt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libwebthree/CMakeLists.txt b/libwebthree/CMakeLists.txt index f960ac00c..bda2e7e11 100644 --- a/libwebthree/CMakeLists.txt +++ b/libwebthree/CMakeLists.txt @@ -21,6 +21,8 @@ file(GLOB HEADERS "*.h") add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) +add_dependencies(${EXECUTABLE} BuildInfo.h) + target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} lll) diff --git a/solc/CMakeLists.txt b/solc/CMakeLists.txt index e60d3c8cf..df72f52dd 100644 --- a/solc/CMakeLists.txt +++ b/solc/CMakeLists.txt @@ -13,6 +13,8 @@ set(EXECUTABLE solc) file(GLOB HEADERS "*.h") add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) +add_dependencies(${EXECUTABLE} BuildInfo.h) + target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARIES}) target_link_libraries(${EXECUTABLE} solidity) From e989cdaf367715985a59c990b7db8260c415dc0c Mon Sep 17 00:00:00 2001 From: subtly Date: Sat, 4 Jul 2015 15:18:15 -0400 Subject: [PATCH 152/290] use local integer for v parameter of signature --- libdevcrypto/Common.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index eca0521cf..219b28f3a 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -198,8 +198,10 @@ Signature dev::sign(Secret const& _k, h256 const& _hash) { #ifdef ETH_HAVE_SECP256K1 Signature s; - if (!secp256k1_ecdsa_sign_compact(_hash.data(), h256::size, s.data(), _k.data(), Nonce::get().data(), (int*)(s.data()+64))) + int v; + if (!secp256k1_ecdsa_sign_compact(_hash.data(), h256::size, s.data(), _k.data(), Nonce::get().data(), &v)) return Signature(); + s[64] = v; return s; #else return s_secp256k1pp.sign(_k, _hash); From bf5156bcd60ccc929df13245df6c3cfac70e2863 Mon Sep 17 00:00:00 2001 From: arkpar Date: Sun, 5 Jul 2015 09:28:28 +0200 Subject: [PATCH 153/290] fixed m_known handling --- libethereum/TransactionQueue.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 478b4ff3c..0e34292d6 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -33,6 +33,7 @@ const char* TransactionQueueTraceChannel::name() { return EthCyan " ┅▶"; } ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallback const& _cb, IfDropped _ik) { + m_limit = 256; // Check if we already know this transaction. h256 h = sha3(_transactionRLP); @@ -151,7 +152,6 @@ ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transactio } // If valid, append to blocks. insertCurrent_WITH_LOCK(make_pair(_h, _transaction)); - m_known.insert(_h); if (_cb) m_callbacks[_h] = _cb; clog(TransactionQueueTraceChannel) << "Queued vaguely legit-looking transaction" << _h; @@ -236,6 +236,7 @@ void TransactionQueue::insertCurrent_WITH_LOCK(std::pair cons m_future.erase(t.from()); } } + m_known.insert(_p.first); } bool TransactionQueue::remove_WITH_LOCK(h256 const& _txHash) @@ -252,6 +253,7 @@ bool TransactionQueue::remove_WITH_LOCK(h256 const& _txHash) m_currentByHash.erase(t); if (it->second.empty()) m_currentByAddressAndNonce.erase(it); + m_known.erase(_txHash); return true; } @@ -304,9 +306,9 @@ void TransactionQueue::drop(h256 const& _txHash) UpgradeGuard ul(l); m_dropped.insert(_txHash); - m_known.erase(_txHash); remove_WITH_LOCK(_txHash); + } void TransactionQueue::clear() From cd06dfae5d02c79bc0a07a957623c044cde26c73 Mon Sep 17 00:00:00 2001 From: arkpar Date: Sun, 5 Jul 2015 09:35:16 +0200 Subject: [PATCH 154/290] removed dbg limit --- libethereum/TransactionQueue.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 0e34292d6..235c2a34e 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -33,7 +33,6 @@ const char* TransactionQueueTraceChannel::name() { return EthCyan " ┅▶"; } ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallback const& _cb, IfDropped _ik) { - m_limit = 256; // Check if we already know this transaction. h256 h = sha3(_transactionRLP); From 0c75272b589d6772c1a4d90f5a4e45f58e1dd09b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 5 Jul 2015 12:08:15 -0400 Subject: [PATCH 155/290] Transaction queue does async data imports. --- libethcore/Transaction.cpp | 5 +- libethcore/Transaction.h | 4 +- libethereum/BlockQueue.cpp | 7 ++- libethereum/Client.cpp | 4 +- libethereum/Transaction.cpp | 4 +- libethereum/Transaction.h | 4 +- libethereum/TransactionQueue.cpp | 85 ++++++++++++++++++++++++++++---- libethereum/TransactionQueue.h | 29 ++++++++++- 8 files changed, 119 insertions(+), 23 deletions(-) diff --git a/libethcore/Transaction.cpp b/libethcore/Transaction.cpp index 5e08acd4d..3c974cb94 100644 --- a/libethcore/Transaction.cpp +++ b/libethcore/Transaction.cpp @@ -29,7 +29,8 @@ using namespace std; using namespace dev; using namespace dev::eth; -TransactionBase::TransactionBase(bytesConstRef _rlpData, CheckTransaction _checkSig) +TransactionBase::TransactionBase(bytesConstRef _rlpData, CheckTransaction _checkSig, h256 const& _precomputed): + m_hashWith(_precomputed) { int field = 0; RLP rlp(_rlpData); @@ -54,7 +55,7 @@ TransactionBase::TransactionBase(bytesConstRef _rlpData, CheckTransaction _check h256 s = rlp[field = 8].toInt(); if (rlp.itemCount() > 9) - BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("to many fields in the transaction RLP")); + BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("too many fields in the transaction RLP")); m_vrs = SignatureStruct{ r, s, v }; if (_checkSig >= CheckTransaction::Cheap && !m_vrs.isValid()) diff --git a/libethcore/Transaction.h b/libethcore/Transaction.h index e5eeb74b4..8c1facf13 100644 --- a/libethcore/Transaction.h +++ b/libethcore/Transaction.h @@ -64,10 +64,10 @@ public: TransactionBase(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data, u256 const& _nonce = 0): m_type(ContractCreation), m_nonce(_nonce), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {} /// Constructs a transaction from the given RLP. - explicit TransactionBase(bytesConstRef _rlp, CheckTransaction _checkSig); + explicit TransactionBase(bytesConstRef _rlp, CheckTransaction _checkSig, h256 const& _precomputed = h256()); /// Constructs a transaction from the given RLP. - explicit TransactionBase(bytes const& _rlp, CheckTransaction _checkSig): TransactionBase(&_rlp, _checkSig) {} + explicit TransactionBase(bytes const& _rlp, CheckTransaction _checkSig, h256 const& _precomputed = h256()): TransactionBase(&_rlp, _checkSig, _precomputed) {} /// Checks equality of transactions. diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index 3a5138ca3..95ab62ea7 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -53,7 +53,7 @@ BlockQueue::BlockQueue(): unsigned verifierThreads = std::max(thread::hardware_concurrency(), 3U) - 2U; for (unsigned i = 0; i < verifierThreads; ++i) m_verifiers.emplace_back([=](){ - setThreadName("verifier" + toString(i)); + setThreadName("blockcheck" + toString(i)); this->verifierBody(); }); } @@ -93,6 +93,7 @@ void BlockQueue::verifierBody() UnverifiedBlock work; { + DEV_INVARIANT_CHECK; unique_lock l(m_verification); m_moreToVerify.wait(l, [&](){ return !m_unverified.empty() || m_deleting; }); if (m_deleting) @@ -116,6 +117,7 @@ void BlockQueue::verifierBody() // bad block. // has to be this order as that's how invariants() assumes. WriteGuard l2(m_lock); + DEV_INVARIANT_CHECK; unique_lock l(m_verification); m_readySet.erase(work.hash); m_knownBad.insert(work.hash); @@ -134,6 +136,7 @@ void BlockQueue::verifierBody() bool ready = false; { WriteGuard l2(m_lock); + DEV_INVARIANT_CHECK; unique_lock l(m_verification); if (!m_verifying.empty() && m_verifying.front().verified.info.mixHash == work.hash) { @@ -460,6 +463,8 @@ void BlockQueue::drain(VerifiedBlocks& o_out, unsigned _max) auto h = bs.verified.info.hash(); m_drainingSet.insert(h); m_drainingDifficulty += bs.verified.info.difficulty; + if (!m_readySet.count(h)) + cwarn << "ODD: Invariant will fail: ready set doesn't contain drained verified block" << h; m_readySet.erase(h); m_knownSize -= bs.verified.block.size(); m_knownCount--; diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index e812fb4e9..86f881940 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -604,7 +604,7 @@ void Client::onChainChanged(ImportRoute const& _ir) for (auto const& t: m_bc.transactions(h)) { clog(ClientTrace) << "Resubmitting dead-block transaction " << Transaction(t, CheckTransaction::None); - m_tq.import(t, TransactionQueue::ImportCallback(), IfDropped::Retry); + m_tq.import(t, ImportCallback(), IfDropped::Retry); } } @@ -651,7 +651,7 @@ void Client::onChainChanged(ImportRoute const& _ir) for (auto const& t: m_postMine.pending()) { clog(ClientTrace) << "Resubmitting post-mine transaction " << t; - auto ir = m_tq.import(t, TransactionQueue::ImportCallback(), IfDropped::Retry); + auto ir = m_tq.import(t, ImportCallback(), IfDropped::Retry); if (ir != ImportResult::Success) onTransactionQueueReady(); } diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp index b634ef1d3..988518e3d 100644 --- a/libethereum/Transaction.cpp +++ b/libethereum/Transaction.cpp @@ -94,8 +94,8 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, TransactionException cons return _out; } -Transaction::Transaction(bytesConstRef _rlpData, CheckTransaction _checkSig): - TransactionBase(_rlpData, _checkSig) +Transaction::Transaction(bytesConstRef _rlpData, CheckTransaction _checkSig, h256 const& _precomputed): + TransactionBase(_rlpData, _checkSig, _precomputed) { if (_checkSig >= CheckTransaction::Cheap && !checkPayment()) BOOST_THROW_EXCEPTION(OutOfGasIntrinsic() << RequirementError(gasRequired(), (bigint)gas())); diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h index 77ba1824d..584495e10 100644 --- a/libethereum/Transaction.h +++ b/libethereum/Transaction.h @@ -106,10 +106,10 @@ public: {} /// Constructs a transaction from the given RLP. - explicit Transaction(bytesConstRef _rlp, CheckTransaction _checkSig); + explicit Transaction(bytesConstRef _rlp, CheckTransaction _checkSig, h256 const& _precomputed = h256()); /// Constructs a transaction from the given RLP. - explicit Transaction(bytes const& _rlp, CheckTransaction _checkSig): Transaction(&_rlp, _checkSig) {} + explicit Transaction(bytes const& _rlp, CheckTransaction _checkSig, h256 const& _precomputed = h256()): Transaction(&_rlp, _checkSig, _precomputed) {} /// @returns true if the transaction contains enough gas for the basic payment. bool checkPayment() const { return m_gas >= gasRequired(); } diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index d2ced467e..116231f78 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -31,12 +31,34 @@ using namespace dev::eth; const char* TransactionQueueChannel::name() { return EthCyan "┉┅▶"; } const char* TransactionQueueTraceChannel::name() { return EthCyan " ┅▶"; } +TransactionQueue::TransactionQueue() +{ + // Allow some room for other activity + unsigned verifierThreads = std::max(thread::hardware_concurrency(), 3U) - 2U; + for (unsigned i = 0; i < verifierThreads; ++i) + m_verifiers.emplace_back([=](){ + setThreadName("txcheck" + toString(i)); + this->verifierBody(); + }); +} + +TransactionQueue::~TransactionQueue() +{ + m_deleting = true; + m_moreToVerify.notify_all(); + for (auto& i: m_verifiers) + i.join(); +} + +bool TransactionQueue::invariants() const +{ + return true; +} + ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallback const& _cb, IfDropped _ik) { // Check if we already know this transaction. - h256 h = sha3(_transactionRLP); - - Transaction t; + auto h = sha3(_transactionRLP); ImportResult ir; { UpgradableGuard l(m_lock); @@ -45,24 +67,67 @@ ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallb if (ir != ImportResult::Success) return ir; + UpgradeGuard ll(l); + m_submitted.insert(h); + DEV_GUARDED(m_verification) + { + m_unverified.push_back(UnverifiedTransaction{h, _transactionRLP.toBytes(), _cb}); + m_moreToVerify.notify_one(); + } + } +// cdebug << "import-END: Nonce of" << t.sender() << "now" << maxNonce(t.sender()); + return ir; +} + +void TransactionQueue::verifierBody() +{ + while (!m_deleting) + { + UnverifiedTransaction work; + + { + DEV_INVARIANT_CHECK; + unique_lock l(m_verification); + m_moreToVerify.wait(l, [&](){ return !m_unverified.empty() || m_deleting; }); + if (m_deleting) + return; + swap(work, m_unverified.front()); + m_unverified.pop_front(); + } + + Transaction res; try { - t = Transaction(_transactionRLP, CheckTransaction::Everything); - UpgradeGuard ul(l); - ir = manageImport_WITH_LOCK(h, t, _cb); + res = Transaction(work.data, CheckTransaction::Everything, work.hash); } catch (...) { - return ImportResult::Malformed; + // bad transaction. + // has to be this order as that's how invariants() assumes. + WriteGuard l(m_lock); + DEV_INVARIANT_CHECK; + m_submitted.erase(work.hash); + m_dropped.insert(work.hash); + if (work.cb) + work.cb(ImportResult::Malformed); + continue; } + + ImportResult ir; + { + WriteGuard l(m_lock); + DEV_INVARIANT_CHECK; + m_submitted.erase(work.hash); + ir = manageImport_WITH_LOCK(work.hash, res, work.cb); + } + if (ir != ImportResult::Success && work.cb) + work.cb(ir); } -// cdebug << "import-END: Nonce of" << t.sender() << "now" << maxNonce(t.sender()); - return ir; } ImportResult TransactionQueue::check_WITH_LOCK(h256 const& _h, IfDropped _ik) { - if (m_known.count(_h)) + if (m_known.count(_h) || m_submitted.count(_h)) return ImportResult::AlreadyKnown; if (m_dropped.count(_h) && _ik == IfDropped::Ignore) diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index d9bfef847..80034d057 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -21,6 +21,9 @@ #pragma once +#include +#include +#include #include #include #include @@ -41,14 +44,24 @@ struct TransactionQueueTraceChannel: public LogChannel { static const char* name enum class IfDropped { Ignore, Retry }; +using ImportCallback = std::function; + +struct UnverifiedTransaction +{ + h256 hash; + bytes data; + ImportCallback cb; +}; + /** * @brief A queue of Transactions, each stored as RLP. * @threadsafe */ -class TransactionQueue +class TransactionQueue: HasInvariants { public: - using ImportCallback = std::function; + TransactionQueue(); + virtual ~TransactionQueue(); ImportResult import(Transaction const& _tx, ImportCallback const& _cb = ImportCallback(), IfDropped _ik = IfDropped::Ignore); ImportResult import(bytes const& _tx, ImportCallback const& _cb = ImportCallback(), IfDropped _ik = IfDropped::Ignore) { return import(&_tx, _cb, _ik); } @@ -75,6 +88,10 @@ private: bool remove_WITH_LOCK(h256 const& _txHash); u256 maxNonce_WITH_LOCK(Address const& _a) const; + bool invariants() const override; + + void verifierBody(); + mutable SharedMutex m_lock; ///< General lock. h256Hash m_known; ///< Hashes of transactions in both sets. std::unordered_multimap m_senders; ///< Mapping from the sender address to the transaction hash; useful for determining the nonce of a given sender. @@ -82,7 +99,15 @@ private: std::unordered_map m_future; ///< For transactions that have a future nonce; we re-insert into current once the sender has a valid TX. std::unordered_map> m_callbacks; ///< Called once. h256Hash m_dropped; ///< Transactions that have previously been dropped. + h256Hash m_submitted; ///< Hashes of transactions that have been submitted but not yet processed (unverified or verifying). Signal m_onReady; ///< Called when a subsequent call to import transactions will return a non-empty container. Be nice and exit fast. + + mutable Mutex m_verification; ///< Mutex that allows writing to m_unverified & m_moreToVerify. + std::condition_variable m_moreToVerify; ///< Signaled when m_unverified has a new entry. + std::deque m_unverified; ///< List of ready for verification. + + std::vector m_verifiers; ///< Threads who only verify. + bool m_deleting = false; ///< Exit condition for verifiers. }; } From 4346b80f06205c0a0fcee85eeb76c6909f95640a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 5 Jul 2015 13:10:46 -0400 Subject: [PATCH 156/290] Revert "Txqueueasyncverify" --- libdevcore/Guards.h | 29 ------- libethcore/Common.h | 7 +- libethcore/Ethash.cpp | 23 ++++++ libethcore/Transaction.cpp | 5 +- libethcore/Transaction.h | 4 +- libethereum/BlockQueue.cpp | 10 +-- libethereum/Client.cpp | 4 +- libethereum/State.cpp | 14 ++-- libethereum/Transaction.cpp | 4 +- libethereum/Transaction.h | 4 +- libethereum/TransactionQueue.cpp | 114 +++----------------------- libethereum/TransactionQueue.h | 32 +------- test/libethereum/transactionqueue.cpp | 15 ++-- 13 files changed, 65 insertions(+), 200 deletions(-) diff --git a/libdevcore/Guards.h b/libdevcore/Guards.h index a008c50ba..2d3eced32 100644 --- a/libdevcore/Guards.h +++ b/libdevcore/Guards.h @@ -23,7 +23,6 @@ #include #include -#include #include namespace dev @@ -34,7 +33,6 @@ using RecursiveMutex = std::recursive_mutex; using SharedMutex = boost::shared_mutex; using Guard = std::lock_guard; -using UniqueGuard = std::unique_lock; using RecursiveGuard = std::lock_guard; using ReadGuard = boost::shared_lock; using UpgradableGuard = boost::upgrade_lock; @@ -124,31 +122,4 @@ using SpinGuard = std::lock_guard; #define DEV_WRITE_UNGUARDED(MUTEX) \ for (GenericUnguardBool __eth_l(MUTEX); __eth_l.b; __eth_l.b = false) -template -class Notified -{ -public: - Notified() {} - Notified(N const& _v): m_value(_v) {} - Notified(Notified const&) = delete; - Notified& operator=(N const& _v) { UniqueGuard l(m_mutex); m_value = _v; m_cv.notify_all(); return *this; } - - operator N() const { UniqueGuard l(m_mutex); return m_value; } - - void wait() const { UniqueGuard l(m_mutex); m_cv.wait(l); } - void wait(N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait(l, [&](){return m_value == _v;}); } - void wait_not(N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait(l, [&](){return m_value != _v;}); } - template void wait(F const& _f) const { UniqueGuard l(m_mutex); m_cv.wait(l, _f); } - - template void wait(std::chrono::duration const& _duration) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _duration); } - template void wait(std::chrono::duration const& _duration, N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _duration, [&](){return m_value == _v;}); } - template void wait_not(std::chrono::duration const& _duration, N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _duration, [&](){return m_value != _v;}); } - template void wait(std::chrono::duration const& _duration, F const& _f) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _duration, _f); } - -private: - mutable Mutex m_mutex; - mutable std::condition_variable m_cv; - N m_value; -}; - } diff --git a/libethcore/Common.h b/libethcore/Common.h index 472a47279..732d09981 100644 --- a/libethcore/Common.h +++ b/libethcore/Common.h @@ -113,12 +113,7 @@ enum class ImportResult AlreadyKnown, Malformed, OverbidGasPrice, - GasPriceTooLow, - BadChain, - NonceTooLow, - FarAway, - TooMuchGas, - Unknown + BadChain }; struct ImportRequirements diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index d1fa60e90..46d19d164 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -225,6 +225,29 @@ std::string Ethash::CPUMiner::platformInfo() #if ETH_ETHASHCL || !ETH_TRUE +using UniqueGuard = std::unique_lock; + +template +class Notified +{ +public: + Notified() {} + Notified(N const& _v): m_value(_v) {} + Notified(Notified const&) = delete; + Notified& operator=(N const& _v) { UniqueGuard l(m_mutex); m_value = _v; m_cv.notify_all(); return *this; } + + operator N() const { UniqueGuard l(m_mutex); return m_value; } + + void wait() const { UniqueGuard l(m_mutex); m_cv.wait(l); } + void wait(N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait(l, [&](){return m_value == _v;}); } + template void wait(F const& _f) const { UniqueGuard l(m_mutex); m_cv.wait(l, _f); } + +private: + mutable Mutex m_mutex; + mutable std::condition_variable m_cv; + N m_value; +}; + class EthashCLHook: public ethash_cl_miner::search_hook { public: diff --git a/libethcore/Transaction.cpp b/libethcore/Transaction.cpp index 3c974cb94..5e08acd4d 100644 --- a/libethcore/Transaction.cpp +++ b/libethcore/Transaction.cpp @@ -29,8 +29,7 @@ using namespace std; using namespace dev; using namespace dev::eth; -TransactionBase::TransactionBase(bytesConstRef _rlpData, CheckTransaction _checkSig, h256 const& _precomputed): - m_hashWith(_precomputed) +TransactionBase::TransactionBase(bytesConstRef _rlpData, CheckTransaction _checkSig) { int field = 0; RLP rlp(_rlpData); @@ -55,7 +54,7 @@ TransactionBase::TransactionBase(bytesConstRef _rlpData, CheckTransaction _check h256 s = rlp[field = 8].toInt(); if (rlp.itemCount() > 9) - BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("too many fields in the transaction RLP")); + BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("to many fields in the transaction RLP")); m_vrs = SignatureStruct{ r, s, v }; if (_checkSig >= CheckTransaction::Cheap && !m_vrs.isValid()) diff --git a/libethcore/Transaction.h b/libethcore/Transaction.h index 8c1facf13..e5eeb74b4 100644 --- a/libethcore/Transaction.h +++ b/libethcore/Transaction.h @@ -64,10 +64,10 @@ public: TransactionBase(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data, u256 const& _nonce = 0): m_type(ContractCreation), m_nonce(_nonce), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {} /// Constructs a transaction from the given RLP. - explicit TransactionBase(bytesConstRef _rlp, CheckTransaction _checkSig, h256 const& _precomputed = h256()); + explicit TransactionBase(bytesConstRef _rlp, CheckTransaction _checkSig); /// Constructs a transaction from the given RLP. - explicit TransactionBase(bytes const& _rlp, CheckTransaction _checkSig, h256 const& _precomputed = h256()): TransactionBase(&_rlp, _checkSig, _precomputed) {} + explicit TransactionBase(bytes const& _rlp, CheckTransaction _checkSig): TransactionBase(&_rlp, _checkSig) {} /// Checks equality of transactions. diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index fe0bc7a76..3a5138ca3 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -53,7 +53,7 @@ BlockQueue::BlockQueue(): unsigned verifierThreads = std::max(thread::hardware_concurrency(), 3U) - 2U; for (unsigned i = 0; i < verifierThreads; ++i) m_verifiers.emplace_back([=](){ - setThreadName("blockcheck" + toString(i)); + setThreadName("verifier" + toString(i)); this->verifierBody(); }); } @@ -92,8 +92,6 @@ void BlockQueue::verifierBody() { UnverifiedBlock work; - DEV_READ_GUARDED(m_lock) - DEV_INVARIANT_CHECK; { unique_lock l(m_verification); m_moreToVerify.wait(l, [&](){ return !m_unverified.empty() || m_deleting; }); @@ -106,8 +104,6 @@ void BlockQueue::verifierBody() bi.parentHash = work.parentHash; m_verifying.emplace_back(move(bi)); } - DEV_READ_GUARDED(m_lock) - DEV_INVARIANT_CHECK; VerifiedBlock res; swap(work.block, res.blockData); @@ -120,7 +116,6 @@ void BlockQueue::verifierBody() // bad block. // has to be this order as that's how invariants() assumes. WriteGuard l2(m_lock); - DEV_INVARIANT_CHECK; unique_lock l(m_verification); m_readySet.erase(work.hash); m_knownBad.insert(work.hash); @@ -139,7 +134,6 @@ void BlockQueue::verifierBody() bool ready = false; { WriteGuard l2(m_lock); - DEV_INVARIANT_CHECK; unique_lock l(m_verification); if (!m_verifying.empty() && m_verifying.front().verified.info.mixHash == work.hash) { @@ -466,8 +460,6 @@ void BlockQueue::drain(VerifiedBlocks& o_out, unsigned _max) auto h = bs.verified.info.hash(); m_drainingSet.insert(h); m_drainingDifficulty += bs.verified.info.difficulty; - if (!m_readySet.count(h)) - cwarn << "ODD: Invariant will fail: ready set doesn't contain drained verified block" << h; m_readySet.erase(h); m_knownSize -= bs.verified.block.size(); m_knownCount--; diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 86f881940..e812fb4e9 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -604,7 +604,7 @@ void Client::onChainChanged(ImportRoute const& _ir) for (auto const& t: m_bc.transactions(h)) { clog(ClientTrace) << "Resubmitting dead-block transaction " << Transaction(t, CheckTransaction::None); - m_tq.import(t, ImportCallback(), IfDropped::Retry); + m_tq.import(t, TransactionQueue::ImportCallback(), IfDropped::Retry); } } @@ -651,7 +651,7 @@ void Client::onChainChanged(ImportRoute const& _ir) for (auto const& t: m_postMine.pending()) { clog(ClientTrace) << "Resubmitting post-mine transaction " << t; - auto ir = m_tq.import(t, ImportCallback(), IfDropped::Retry); + auto ir = m_tq.import(t, TransactionQueue::ImportCallback(), IfDropped::Retry); if (ir != ImportResult::Success) onTransactionQueueReady(); } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 85cd05dce..a000d628a 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -524,7 +524,7 @@ pair State::sync(BlockChain const& _bc, TransactionQu { // less than 90% of our ask price for gas. drop. cnote << i.first << "Dropping El Cheapo transaction (<90% of ask price)"; - _tq.drop(i.first, ImportResult::GasPriceTooLow); + _tq.drop(i.first); } } catch (InvalidNonce const& in) @@ -541,12 +541,12 @@ pair State::sync(BlockChain const& _bc, TransactionQu if (t.nonce() < i.second.nonce()) { cnote << i.first << "Dropping old transaction (nonce too low)"; - _tq.drop(i.first, ImportResult::NonceTooLow); + _tq.drop(i.first); } else if (t.nonce() == i.second.nonce() && t.gasPrice() <= i.second.gasPrice()) { cnote << i.first << "Dropping old transaction (gas price lower)"; - _tq.drop(i.first, ImportResult::OverbidGasPrice); + _tq.drop(i.first); } } } @@ -554,7 +554,7 @@ pair State::sync(BlockChain const& _bc, TransactionQu { // too new cnote << i.first << "Dropping new transaction (too many nonces ahead)"; - _tq.drop(i.first, ImportResult::FarAway); + _tq.drop(i.first); } else _tq.setFuture(i); @@ -565,7 +565,7 @@ pair State::sync(BlockChain const& _bc, TransactionQu if (got > m_currentBlock.gasLimit) { cnote << i.first << "Dropping over-gassy transaction (gas > block's gas limit)"; - _tq.drop(i.first, ImportResult::TooMuchGas); + _tq.drop(i.first); } else { @@ -579,12 +579,12 @@ pair State::sync(BlockChain const& _bc, TransactionQu { // Something else went wrong - drop it. cnote << i.first << "Dropping invalid transaction:" << diagnostic_information(_e); - _tq.drop(i.first, ImportResult::Malformed); + _tq.drop(i.first); } catch (std::exception const&) { // Something else went wrong - drop it. - _tq.drop(i.first, ImportResult::Malformed); + _tq.drop(i.first); cnote << i.first << "Transaction caused low-level exception :("; } } diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp index 988518e3d..b634ef1d3 100644 --- a/libethereum/Transaction.cpp +++ b/libethereum/Transaction.cpp @@ -94,8 +94,8 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, TransactionException cons return _out; } -Transaction::Transaction(bytesConstRef _rlpData, CheckTransaction _checkSig, h256 const& _precomputed): - TransactionBase(_rlpData, _checkSig, _precomputed) +Transaction::Transaction(bytesConstRef _rlpData, CheckTransaction _checkSig): + TransactionBase(_rlpData, _checkSig) { if (_checkSig >= CheckTransaction::Cheap && !checkPayment()) BOOST_THROW_EXCEPTION(OutOfGasIntrinsic() << RequirementError(gasRequired(), (bigint)gas())); diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h index 584495e10..77ba1824d 100644 --- a/libethereum/Transaction.h +++ b/libethereum/Transaction.h @@ -106,10 +106,10 @@ public: {} /// Constructs a transaction from the given RLP. - explicit Transaction(bytesConstRef _rlp, CheckTransaction _checkSig, h256 const& _precomputed = h256()); + explicit Transaction(bytesConstRef _rlp, CheckTransaction _checkSig); /// Constructs a transaction from the given RLP. - explicit Transaction(bytes const& _rlp, CheckTransaction _checkSig, h256 const& _precomputed = h256()): Transaction(&_rlp, _checkSig, _precomputed) {} + explicit Transaction(bytes const& _rlp, CheckTransaction _checkSig): Transaction(&_rlp, _checkSig) {} /// @returns true if the transaction contains enough gas for the basic payment. bool checkPayment() const { return m_gas >= gasRequired(); } diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 549e7aede..d2ced467e 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -31,34 +31,12 @@ using namespace dev::eth; const char* TransactionQueueChannel::name() { return EthCyan "┉┅▶"; } const char* TransactionQueueTraceChannel::name() { return EthCyan " ┅▶"; } -TransactionQueue::TransactionQueue() -{ - // Allow some room for other activity - unsigned verifierThreads = std::max(thread::hardware_concurrency(), 3U) - 2U; - for (unsigned i = 0; i < verifierThreads; ++i) - m_verifiers.emplace_back([=](){ - setThreadName("txcheck" + toString(i)); - this->verifierBody(); - }); -} - -TransactionQueue::~TransactionQueue() -{ - m_deleting = true; - m_moreToVerify.notify_all(); - for (auto& i: m_verifiers) - i.join(); -} - -bool TransactionQueue::invariants() const -{ - return true; -} - ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallback const& _cb, IfDropped _ik) { // Check if we already know this transaction. - auto h = sha3(_transactionRLP); + h256 h = sha3(_transactionRLP); + + Transaction t; ImportResult ir; { UpgradableGuard l(m_lock); @@ -67,69 +45,24 @@ ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallb if (ir != ImportResult::Success) return ir; - UpgradeGuard ll(l); - m_submitted.insert(h); - DEV_GUARDED(m_verification) - { - m_unverified.push_back(UnverifiedTransaction{h, _transactionRLP.toBytes(), _cb}); - m_moreToVerify.notify_one(); - } - } -// cdebug << "import-END: Nonce of" << t.sender() << "now" << maxNonce(t.sender()); - return ir; -} - -void TransactionQueue::verifierBody() -{ - while (!m_deleting) - { - UnverifiedTransaction work; - - { - DEV_INVARIANT_CHECK; - unique_lock l(m_verification); - m_moreToVerify.wait(l, [&](){ return !m_unverified.empty() || m_deleting; }); - if (m_deleting) - return; - swap(work, m_unverified.front()); - m_unverified.pop_front(); - } - - Transaction res; try { - res = Transaction(work.data, CheckTransaction::Everything, work.hash); - } - catch (Exception& ex) - { - cdebug << "Bad transation inserted" << ex.what(); - cdebug << boost::diagnostic_information(ex); - // bad transaction. - // has to be this order as that's how invariants() assumes. - WriteGuard l(m_lock); - DEV_INVARIANT_CHECK; - m_submitted.erase(work.hash); - m_dropped.insert(work.hash); - if (work.cb) - work.cb(ImportResult::Malformed); - continue; + t = Transaction(_transactionRLP, CheckTransaction::Everything); + UpgradeGuard ul(l); + ir = manageImport_WITH_LOCK(h, t, _cb); } - - ImportResult ir; + catch (...) { - WriteGuard l(m_lock); - DEV_INVARIANT_CHECK; - m_submitted.erase(work.hash); - ir = manageImport_WITH_LOCK(work.hash, res, work.cb); + return ImportResult::Malformed; } - if (ir != ImportResult::Success && work.cb) - work.cb(ir); } +// cdebug << "import-END: Nonce of" << t.sender() << "now" << maxNonce(t.sender()); + return ir; } ImportResult TransactionQueue::check_WITH_LOCK(h256 const& _h, IfDropped _ik) { - if (m_known.count(_h) || m_submitted.count(_h)) + if (m_known.count(_h)) return ImportResult::AlreadyKnown; if (m_dropped.count(_h) && _ik == IfDropped::Ignore) @@ -306,24 +239,7 @@ void TransactionQueue::setFuture(std::pair const& _t) void TransactionQueue::noteGood(std::pair const& _t) { // cdebug << "txQ::noteGood" << _t.first; - UpgradableGuard l(m_lock); - - if (!m_known.count(_t.first)) - return; - - // Point out it has been successfully been placed in a block. - if (m_callbacks.count(_t.first) && m_callbacks[_t.first]) - m_callbacks[_t.first](ImportResult::Success); - - UpgradeGuard l2(l); - - // Erase the transaction itself. - m_current.erase(_t.first); - m_callbacks.erase(_t.first); - - // Bring the a now-value transaction with the next nonce from m_future into m_current. - // At present it reinserts all transactions from the good transaction's sender. - // TODO: Should really just insert the transaction with the following nonce. + WriteGuard l(m_lock); auto r = m_senders.equal_range(_t.second.sender()); for (auto it = r.first; it != r.second; ++it) { @@ -336,20 +252,16 @@ void TransactionQueue::noteGood(std::pair const& _t) } } -void TransactionQueue::drop(h256 const& _txHash, ImportResult _ir) +void TransactionQueue::drop(h256 const& _txHash) { UpgradableGuard l(m_lock); if (!m_known.count(_txHash)) return; - if (m_callbacks.count(_txHash) && m_callbacks[_txHash]) - m_callbacks[_txHash](_ir); - UpgradeGuard ul(l); m_dropped.insert(_txHash); m_known.erase(_txHash); - m_callbacks.erase(_txHash); remove_WITH_LOCK(_txHash); } diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index 483571dd8..d9bfef847 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -21,11 +21,7 @@ #pragma once -#include -#include -#include #include -#include #include #include #include @@ -45,30 +41,20 @@ struct TransactionQueueTraceChannel: public LogChannel { static const char* name enum class IfDropped { Ignore, Retry }; -using ImportCallback = std::function; - -struct UnverifiedTransaction -{ - h256 hash; - bytes data; - ImportCallback cb; -}; - /** * @brief A queue of Transactions, each stored as RLP. * @threadsafe */ -class TransactionQueue: HasInvariants +class TransactionQueue { public: - TransactionQueue(); - virtual ~TransactionQueue(); + using ImportCallback = std::function; ImportResult import(Transaction const& _tx, ImportCallback const& _cb = ImportCallback(), IfDropped _ik = IfDropped::Ignore); ImportResult import(bytes const& _tx, ImportCallback const& _cb = ImportCallback(), IfDropped _ik = IfDropped::Ignore) { return import(&_tx, _cb, _ik); } ImportResult import(bytesConstRef _tx, ImportCallback const& _cb = ImportCallback(), IfDropped _ik = IfDropped::Ignore); - void drop(h256 const& _txHash, ImportResult _ir = ImportResult::Unknown); + void drop(h256 const& _txHash); unsigned waiting(Address const& _a) const; std::unordered_map transactions() const; @@ -89,10 +75,6 @@ private: bool remove_WITH_LOCK(h256 const& _txHash); u256 maxNonce_WITH_LOCK(Address const& _a) const; - bool invariants() const override; - - void verifierBody(); - mutable SharedMutex m_lock; ///< General lock. h256Hash m_known; ///< Hashes of transactions in both sets. std::unordered_multimap m_senders; ///< Mapping from the sender address to the transaction hash; useful for determining the nonce of a given sender. @@ -100,15 +82,7 @@ private: std::unordered_map m_future; ///< For transactions that have a future nonce; we re-insert into current once the sender has a valid TX. std::unordered_map> m_callbacks; ///< Called once. h256Hash m_dropped; ///< Transactions that have previously been dropped. - h256Hash m_submitted; ///< Hashes of transactions that have been submitted but not yet processed (unverified or verifying). Signal m_onReady; ///< Called when a subsequent call to import transactions will return a non-empty container. Be nice and exit fast. - - mutable Mutex m_verification; ///< Mutex that allows writing to m_unverified & m_moreToVerify. - std::condition_variable m_moreToVerify; ///< Signaled when m_unverified has a new entry. - std::deque m_unverified; ///< List of ready for verification. - - std::vector m_verifiers; ///< Threads who only verify. - bool m_deleting = false; ///< Exit condition for verifiers. }; } diff --git a/test/libethereum/transactionqueue.cpp b/test/libethereum/transactionqueue.cpp index bff8893b6..ab85350a5 100644 --- a/test/libethereum/transactionqueue.cpp +++ b/test/libethereum/transactionqueue.cpp @@ -40,15 +40,13 @@ BOOST_AUTO_TEST_CASE(maxNonce) Address dest = Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"); Address to = Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"); Secret sec = Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8"); - Transaction tx0(0, gasCost, gas, dest, bytes(), 0, sec); - Transaction tx0_1(1, gasCost, gas, dest, bytes(), 0, sec); - Transaction tx1(0, gasCost, gas, dest, bytes(), 1, sec); - Transaction tx2(0, gasCost, gas, dest, bytes(), 2, sec); - Transaction tx9(0, gasCost, gas, dest, bytes(), 9, sec); + Transaction tx0(0, gasCost, gas, dest, bytes(), 0, sec ); + Transaction tx0_1(1, gasCost, gas, dest, bytes(), 0, sec ); + Transaction tx1(0, gasCost, gas, dest, bytes(), 1, sec ); + Transaction tx2(0, gasCost, gas, dest, bytes(), 2, sec ); + Transaction tx9(0, gasCost, gas, dest, bytes(), 9, sec ); - txq.import(tx0.rlp()); - while (txq.transactions().empty()) - this_thread::sleep_for(chrono::milliseconds(20)); + txq.import(tx0); BOOST_CHECK(1 == txq.maxNonce(to)); txq.import(tx0); BOOST_CHECK(1 == txq.maxNonce(to)); @@ -60,6 +58,7 @@ BOOST_AUTO_TEST_CASE(maxNonce) BOOST_CHECK(10 == txq.maxNonce(to)); txq.import(tx2); BOOST_CHECK(10 == txq.maxNonce(to)); + } BOOST_AUTO_TEST_SUITE_END() From d73209158edbc6c3e6999ded37d1c10f06b2e2d3 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 5 Jul 2015 14:08:54 -0400 Subject: [PATCH 157/290] test for new transaction queue. Some cleanups and enhacements to Guards & Notifier. Fix an invariant TransactionQueue. --- libdevcore/Guards.h | 29 +++++++++++++++++++++++++++ libethcore/Common.h | 7 ++++++- libethcore/Ethash.cpp | 23 --------------------- libethereum/BlockQueue.cpp | 5 ++++- libethereum/State.cpp | 14 ++++++------- libethereum/TransactionQueue.cpp | 29 ++++++++++++++++++++++++--- libethereum/TransactionQueue.h | 2 +- test/libethereum/transactionqueue.cpp | 15 +++++++------- 8 files changed, 81 insertions(+), 43 deletions(-) diff --git a/libdevcore/Guards.h b/libdevcore/Guards.h index 2d3eced32..a008c50ba 100644 --- a/libdevcore/Guards.h +++ b/libdevcore/Guards.h @@ -23,6 +23,7 @@ #include #include +#include #include namespace dev @@ -33,6 +34,7 @@ using RecursiveMutex = std::recursive_mutex; using SharedMutex = boost::shared_mutex; using Guard = std::lock_guard; +using UniqueGuard = std::unique_lock; using RecursiveGuard = std::lock_guard; using ReadGuard = boost::shared_lock; using UpgradableGuard = boost::upgrade_lock; @@ -122,4 +124,31 @@ using SpinGuard = std::lock_guard; #define DEV_WRITE_UNGUARDED(MUTEX) \ for (GenericUnguardBool __eth_l(MUTEX); __eth_l.b; __eth_l.b = false) +template +class Notified +{ +public: + Notified() {} + Notified(N const& _v): m_value(_v) {} + Notified(Notified const&) = delete; + Notified& operator=(N const& _v) { UniqueGuard l(m_mutex); m_value = _v; m_cv.notify_all(); return *this; } + + operator N() const { UniqueGuard l(m_mutex); return m_value; } + + void wait() const { UniqueGuard l(m_mutex); m_cv.wait(l); } + void wait(N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait(l, [&](){return m_value == _v;}); } + void wait_not(N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait(l, [&](){return m_value != _v;}); } + template void wait(F const& _f) const { UniqueGuard l(m_mutex); m_cv.wait(l, _f); } + + template void wait(std::chrono::duration const& _duration) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _duration); } + template void wait(std::chrono::duration const& _duration, N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _duration, [&](){return m_value == _v;}); } + template void wait_not(std::chrono::duration const& _duration, N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _duration, [&](){return m_value != _v;}); } + template void wait(std::chrono::duration const& _duration, F const& _f) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _duration, _f); } + +private: + mutable Mutex m_mutex; + mutable std::condition_variable m_cv; + N m_value; +}; + } diff --git a/libethcore/Common.h b/libethcore/Common.h index 732d09981..472a47279 100644 --- a/libethcore/Common.h +++ b/libethcore/Common.h @@ -113,7 +113,12 @@ enum class ImportResult AlreadyKnown, Malformed, OverbidGasPrice, - BadChain + GasPriceTooLow, + BadChain, + NonceTooLow, + FarAway, + TooMuchGas, + Unknown }; struct ImportRequirements diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 46d19d164..d1fa60e90 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -225,29 +225,6 @@ std::string Ethash::CPUMiner::platformInfo() #if ETH_ETHASHCL || !ETH_TRUE -using UniqueGuard = std::unique_lock; - -template -class Notified -{ -public: - Notified() {} - Notified(N const& _v): m_value(_v) {} - Notified(Notified const&) = delete; - Notified& operator=(N const& _v) { UniqueGuard l(m_mutex); m_value = _v; m_cv.notify_all(); return *this; } - - operator N() const { UniqueGuard l(m_mutex); return m_value; } - - void wait() const { UniqueGuard l(m_mutex); m_cv.wait(l); } - void wait(N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait(l, [&](){return m_value == _v;}); } - template void wait(F const& _f) const { UniqueGuard l(m_mutex); m_cv.wait(l, _f); } - -private: - mutable Mutex m_mutex; - mutable std::condition_variable m_cv; - N m_value; -}; - class EthashCLHook: public ethash_cl_miner::search_hook { public: diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index 95ab62ea7..fe0bc7a76 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -92,8 +92,9 @@ void BlockQueue::verifierBody() { UnverifiedBlock work; - { + DEV_READ_GUARDED(m_lock) DEV_INVARIANT_CHECK; + { unique_lock l(m_verification); m_moreToVerify.wait(l, [&](){ return !m_unverified.empty() || m_deleting; }); if (m_deleting) @@ -105,6 +106,8 @@ void BlockQueue::verifierBody() bi.parentHash = work.parentHash; m_verifying.emplace_back(move(bi)); } + DEV_READ_GUARDED(m_lock) + DEV_INVARIANT_CHECK; VerifiedBlock res; swap(work.block, res.blockData); diff --git a/libethereum/State.cpp b/libethereum/State.cpp index a000d628a..85cd05dce 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -524,7 +524,7 @@ pair State::sync(BlockChain const& _bc, TransactionQu { // less than 90% of our ask price for gas. drop. cnote << i.first << "Dropping El Cheapo transaction (<90% of ask price)"; - _tq.drop(i.first); + _tq.drop(i.first, ImportResult::GasPriceTooLow); } } catch (InvalidNonce const& in) @@ -541,12 +541,12 @@ pair State::sync(BlockChain const& _bc, TransactionQu if (t.nonce() < i.second.nonce()) { cnote << i.first << "Dropping old transaction (nonce too low)"; - _tq.drop(i.first); + _tq.drop(i.first, ImportResult::NonceTooLow); } else if (t.nonce() == i.second.nonce() && t.gasPrice() <= i.second.gasPrice()) { cnote << i.first << "Dropping old transaction (gas price lower)"; - _tq.drop(i.first); + _tq.drop(i.first, ImportResult::OverbidGasPrice); } } } @@ -554,7 +554,7 @@ pair State::sync(BlockChain const& _bc, TransactionQu { // too new cnote << i.first << "Dropping new transaction (too many nonces ahead)"; - _tq.drop(i.first); + _tq.drop(i.first, ImportResult::FarAway); } else _tq.setFuture(i); @@ -565,7 +565,7 @@ pair State::sync(BlockChain const& _bc, TransactionQu if (got > m_currentBlock.gasLimit) { cnote << i.first << "Dropping over-gassy transaction (gas > block's gas limit)"; - _tq.drop(i.first); + _tq.drop(i.first, ImportResult::TooMuchGas); } else { @@ -579,12 +579,12 @@ pair State::sync(BlockChain const& _bc, TransactionQu { // Something else went wrong - drop it. cnote << i.first << "Dropping invalid transaction:" << diagnostic_information(_e); - _tq.drop(i.first); + _tq.drop(i.first, ImportResult::Malformed); } catch (std::exception const&) { // Something else went wrong - drop it. - _tq.drop(i.first); + _tq.drop(i.first, ImportResult::Malformed); cnote << i.first << "Transaction caused low-level exception :("; } } diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 116231f78..549e7aede 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -100,8 +100,10 @@ void TransactionQueue::verifierBody() { res = Transaction(work.data, CheckTransaction::Everything, work.hash); } - catch (...) + catch (Exception& ex) { + cdebug << "Bad transation inserted" << ex.what(); + cdebug << boost::diagnostic_information(ex); // bad transaction. // has to be this order as that's how invariants() assumes. WriteGuard l(m_lock); @@ -304,7 +306,24 @@ void TransactionQueue::setFuture(std::pair const& _t) void TransactionQueue::noteGood(std::pair const& _t) { // cdebug << "txQ::noteGood" << _t.first; - WriteGuard l(m_lock); + UpgradableGuard l(m_lock); + + if (!m_known.count(_t.first)) + return; + + // Point out it has been successfully been placed in a block. + if (m_callbacks.count(_t.first) && m_callbacks[_t.first]) + m_callbacks[_t.first](ImportResult::Success); + + UpgradeGuard l2(l); + + // Erase the transaction itself. + m_current.erase(_t.first); + m_callbacks.erase(_t.first); + + // Bring the a now-value transaction with the next nonce from m_future into m_current. + // At present it reinserts all transactions from the good transaction's sender. + // TODO: Should really just insert the transaction with the following nonce. auto r = m_senders.equal_range(_t.second.sender()); for (auto it = r.first; it != r.second; ++it) { @@ -317,16 +336,20 @@ void TransactionQueue::noteGood(std::pair const& _t) } } -void TransactionQueue::drop(h256 const& _txHash) +void TransactionQueue::drop(h256 const& _txHash, ImportResult _ir) { UpgradableGuard l(m_lock); if (!m_known.count(_txHash)) return; + if (m_callbacks.count(_txHash) && m_callbacks[_txHash]) + m_callbacks[_txHash](_ir); + UpgradeGuard ul(l); m_dropped.insert(_txHash); m_known.erase(_txHash); + m_callbacks.erase(_txHash); remove_WITH_LOCK(_txHash); } diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index 80034d057..7573fdf87 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -67,7 +67,7 @@ public: ImportResult import(bytes const& _tx, ImportCallback const& _cb = ImportCallback(), IfDropped _ik = IfDropped::Ignore) { return import(&_tx, _cb, _ik); } ImportResult import(bytesConstRef _tx, ImportCallback const& _cb = ImportCallback(), IfDropped _ik = IfDropped::Ignore); - void drop(h256 const& _txHash); + void drop(h256 const& _txHash, ImportResult _ir = ImportResult::Unknown); unsigned waiting(Address const& _a) const; std::unordered_map transactions() const; diff --git a/test/libethereum/transactionqueue.cpp b/test/libethereum/transactionqueue.cpp index ab85350a5..bff8893b6 100644 --- a/test/libethereum/transactionqueue.cpp +++ b/test/libethereum/transactionqueue.cpp @@ -40,13 +40,15 @@ BOOST_AUTO_TEST_CASE(maxNonce) Address dest = Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"); Address to = Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"); Secret sec = Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8"); - Transaction tx0(0, gasCost, gas, dest, bytes(), 0, sec ); - Transaction tx0_1(1, gasCost, gas, dest, bytes(), 0, sec ); - Transaction tx1(0, gasCost, gas, dest, bytes(), 1, sec ); - Transaction tx2(0, gasCost, gas, dest, bytes(), 2, sec ); - Transaction tx9(0, gasCost, gas, dest, bytes(), 9, sec ); + Transaction tx0(0, gasCost, gas, dest, bytes(), 0, sec); + Transaction tx0_1(1, gasCost, gas, dest, bytes(), 0, sec); + Transaction tx1(0, gasCost, gas, dest, bytes(), 1, sec); + Transaction tx2(0, gasCost, gas, dest, bytes(), 2, sec); + Transaction tx9(0, gasCost, gas, dest, bytes(), 9, sec); - txq.import(tx0); + txq.import(tx0.rlp()); + while (txq.transactions().empty()) + this_thread::sleep_for(chrono::milliseconds(20)); BOOST_CHECK(1 == txq.maxNonce(to)); txq.import(tx0); BOOST_CHECK(1 == txq.maxNonce(to)); @@ -58,7 +60,6 @@ BOOST_AUTO_TEST_CASE(maxNonce) BOOST_CHECK(10 == txq.maxNonce(to)); txq.import(tx2); BOOST_CHECK(10 == txq.maxNonce(to)); - } BOOST_AUTO_TEST_SUITE_END() From 69760bc3f68b98d05be6aedc6fe27752145cf392 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 5 Jul 2015 14:38:46 -0400 Subject: [PATCH 158/290] include deque. --- libethereum/TransactionQueue.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index 7573fdf87..483571dd8 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include From 440f6e7dc2d867098ff3eda5675e3621eac0a68e Mon Sep 17 00:00:00 2001 From: arkpar Date: Sun, 5 Jul 2015 22:11:40 +0200 Subject: [PATCH 159/290] import transactions in a separate thread --- libethcore/Common.h | 13 +-- libethereum/BlockChain.cpp | 8 +- libethereum/BlockChainSync.h | 2 +- libethereum/BlockQueue.h | 8 +- libethereum/Client.cpp | 15 ++-- libethereum/Client.h | 4 +- libethereum/EthereumHost.cpp | 79 +++++++++++------- libethereum/EthereumHost.h | 2 + libethereum/State.cpp | 1 + libethereum/State.h | 2 +- libethereum/TransactionQueue.cpp | 138 ++++++++++++++++++++++--------- libethereum/TransactionQueue.h | 47 ++++++++--- libp2p/Host.h | 7 +- test/libethereum/blockchain.cpp | 1 + 14 files changed, 225 insertions(+), 102 deletions(-) diff --git a/libethcore/Common.h b/libethcore/Common.h index 732d09981..ba8c554fb 100644 --- a/libethcore/Common.h +++ b/libethcore/Common.h @@ -97,10 +97,13 @@ enum class RelativeBlock: BlockNumber Pending = PendingBlock }; +class Transaction; + struct ImportRoute { h256s deadBlocks; h256s liveBlocks; + std::vector goodTranactions; }; enum class ImportResult @@ -129,10 +132,10 @@ struct ImportRequirements }; /// Super-duper signal mechanism. TODO: replace with somthing a bit heavier weight. -class Signal +template class Signal { public: - using Callback = std::function; + using Callback = std::function; class HandlerAux { @@ -141,7 +144,7 @@ public: public: ~HandlerAux() { if (m_s) m_s->m_fire.erase(m_i); m_s = nullptr; } void reset() { m_s = nullptr; } - void fire() { m_h(); } + void fire(Args&&... _args) { m_h(std::forward(_args)...); } private: HandlerAux(unsigned _i, Signal* _s, Callback const& _h): m_i(_i), m_s(_s), m_h(_h) {} @@ -165,13 +168,13 @@ public: return h; } - void operator()() { for (auto const& f: m_fire) f.second->fire(); } + void operator()(Args&... _args) { for (auto const& f: m_fire) f.second->fire(std::forward(_args)...); } private: std::map> m_fire; }; -using Handler = std::shared_ptr; +template using Handler = std::shared_ptr::HandlerAux>; struct TransactionSkeleton { diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 4e0266b5b..d8dbd266f 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -337,6 +337,7 @@ tuple BlockChain::sync(BlockQueue& _bq, OverlayDB c h256s fresh; h256s dead; h256s badBlocks; + Transactions goodTransactions; unsigned count = 0; for (VerifiedBlock const& block: blocks) if (!badBlocks.empty()) @@ -351,6 +352,7 @@ tuple BlockChain::sync(BlockQueue& _bq, OverlayDB c r = import(block.verified, _stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce & ~ImportRequirements::CheckUncles); fresh += r.liveBlocks; dead += r.deadBlocks; + goodTransactions += r.goodTranactions; ++count; } catch (dev::eth::UnknownParent) @@ -377,7 +379,7 @@ tuple BlockChain::sync(BlockQueue& _bq, OverlayDB c badBlocks.push_back(block.verified.info.hash()); } } - return make_tuple(ImportRoute{dead, fresh}, _bq.doneDrain(badBlocks), count); + return make_tuple(ImportRoute{dead, fresh, goodTransactions}, _bq.doneDrain(badBlocks), count); } pair BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, ImportRequirements::value _ir) noexcept @@ -497,6 +499,7 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const& BlockReceipts br; u256 td; + Transactions goodTransactions; #if ETH_CATCH try #endif @@ -510,6 +513,7 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const& { blb.blooms.push_back(s.receipt(i).bloom()); br.receipts.push_back(s.receipt(i)); + goodTransactions.push_back(s.pending()[i]); } s.cleanup(true); @@ -750,7 +754,7 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const& dead.push_back(h); else fresh.push_back(h); - return ImportRoute{dead, fresh}; + return ImportRoute{dead, fresh, move(goodTransactions)}; } void BlockChain::clearBlockBlooms(unsigned _begin, unsigned _end) diff --git a/libethereum/BlockChainSync.h b/libethereum/BlockChainSync.h index 5501075fd..6f1c4306d 100644 --- a/libethereum/BlockChainSync.h +++ b/libethereum/BlockChainSync.h @@ -114,7 +114,7 @@ protected: void requestBlocks(std::shared_ptr _peer); protected: - Handler m_bqRoomAvailable; ///< Triggered once block queue + Handler<> m_bqRoomAvailable; ///< Triggered once block queue mutable RecursiveMutex x_sync; SyncState m_state = SyncState::Idle; ///< Current sync state unsigned m_estimatedHashes = 0; ///< Number of estimated hashes for the last peer over PV60. Used for status reporting only. diff --git a/libethereum/BlockQueue.h b/libethereum/BlockQueue.h index fc9d62300..b9e6f5b3b 100644 --- a/libethereum/BlockQueue.h +++ b/libethereum/BlockQueue.h @@ -111,8 +111,8 @@ public: /// Get some infomration on the given block's status regarding us. QueueStatus blockStatus(h256 const& _h) const; - template Handler onReady(T const& _t) { return m_onReady.add(_t); } - template Handler onRoomAvailable(T const& _t) { return m_onRoomAvailable.add(_t); } + template Handler<> onReady(T const& _t) { return m_onReady.add(_t); } + template Handler<> onRoomAvailable(T const& _t) { return m_onRoomAvailable.add(_t); } template void setOnBad(T const& _t) { m_onBad = _t; } @@ -145,8 +145,8 @@ private: std::unordered_multimap> m_unknown; ///< For blocks that have an unknown parent; we map their parent hash to the block stuff, and insert once the block appears. h256Hash m_knownBad; ///< Set of blocks that we know will never be valid. std::multimap> m_future; ///< Set of blocks that are not yet valid. Ordered by timestamp - Signal m_onReady; ///< Called when a subsequent call to import blocks will return a non-empty container. Be nice and exit fast. - Signal m_onRoomAvailable; ///< Called when space for new blocks becomes availabe after a drain. Be nice and exit fast. + Signal<> m_onReady; ///< Called when a subsequent call to import blocks will return a non-empty container. Be nice and exit fast. + Signal<> m_onRoomAvailable; ///< Called when space for new blocks becomes availabe after a drain. Be nice and exit fast. mutable Mutex m_verification; ///< Mutex that allows writing to m_verified, m_verifying and m_unverified. std::condition_variable m_moreToVerify; ///< Signaled when m_unverified has a new entry. diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index e812fb4e9..fba8d51fa 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -604,19 +604,18 @@ void Client::onChainChanged(ImportRoute const& _ir) for (auto const& t: m_bc.transactions(h)) { clog(ClientTrace) << "Resubmitting dead-block transaction " << Transaction(t, CheckTransaction::None); - m_tq.import(t, TransactionQueue::ImportCallback(), IfDropped::Retry); + m_tq.import(t, IfDropped::Retry); } } // remove transactions from m_tq nicely rather than relying on out of date nonce later on. for (auto const& h: _ir.liveBlocks) - { clog(ClientTrace) << "Live block:" << h; - for (auto const& th: m_bc.transactionHashes(h)) - { - clog(ClientTrace) << "Safely dropping transaction " << th; - m_tq.drop(th); - } + + for (auto const& t: _ir.goodTranactions) + { + clog(ClientTrace) << "Safely dropping transaction " << t.sha3(); + m_tq.dropGood(t); } if (auto h = m_host.lock()) @@ -651,7 +650,7 @@ void Client::onChainChanged(ImportRoute const& _ir) for (auto const& t: m_postMine.pending()) { clog(ClientTrace) << "Resubmitting post-mine transaction " << t; - auto ir = m_tq.import(t, TransactionQueue::ImportCallback(), IfDropped::Retry); + auto ir = m_tq.import(t, IfDropped::Retry); if (ir != ImportResult::Success) onTransactionQueueReady(); } diff --git a/libethereum/Client.h b/libethereum/Client.h index 343ca5b60..7f9a65875 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -310,8 +310,8 @@ private: GenericFarm m_farm; ///< Our mining farm. - Handler m_tqReady; - Handler m_bqReady; + Handler<> m_tqReady; + Handler<> m_bqReady; bool m_wouldMine = false; ///< True if we /should/ be mining. bool m_turboMining = false; ///< Don't squander all of our time mining actually just sleeping. diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index ab3b91ba5..186eb6fa8 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -54,6 +54,7 @@ EthereumHost::EthereumHost(BlockChain const& _ch, TransactionQueue& _tq, BlockQu m_networkId (_networkId) { m_latestBlockSent = _ch.currentHash(); + m_tq.onImport([this](ImportResult _ir, h256 const& _h, h512 const& _nodeId) { onTransactionImported(_ir, _h, _nodeId); }); } EthereumHost::~EthereumHost() @@ -68,6 +69,7 @@ bool EthereumHost::ensureInitialised() m_latestBlockSent = m_chain.currentHash(); clog(NetNote) << "Initialising: latest=" << m_latestBlockSent; + Guard l(x_transactions); m_transactionsSent = m_tq.knownTransactions(); return true; } @@ -82,6 +84,7 @@ void EthereumHost::reset() m_sync.reset(); m_latestBlockSent = h256(); + Guard tl(x_transactions); m_transactionsSent.clear(); } @@ -116,16 +119,19 @@ void EthereumHost::maintainTransactions() // Send any new transactions. unordered_map, std::vector> peerTransactions; auto ts = m_tq.topTransactions(c_maxSendTransactions); - for (size_t i = 0; i < ts.size(); ++i) { - auto const& t = ts[i]; - bool unsent = !m_transactionsSent.count(t.sha3()); - auto peers = get<1>(randomSelection(0, [&](EthereumPeer* p) { return p->m_requireTransactions || (unsent && !p->m_knownTransactions.count(t.sha3())); })); - for (auto const& p: peers) - peerTransactions[p].push_back(i); + Guard l(x_transactions); + for (size_t i = 0; i < ts.size(); ++i) + { + auto const& t = ts[i]; + bool unsent = !m_transactionsSent.count(t.sha3()); + auto peers = get<1>(randomSelection(0, [&](EthereumPeer* p) { return p->m_requireTransactions || (unsent && !p->m_knownTransactions.count(t.sha3())); })); + for (auto const& p: peers) + peerTransactions[p].push_back(i); + } + for (auto const& t: ts) + m_transactionsSent.insert(t.sha3()); } - for (auto const& t: ts) - m_transactionsSent.insert(t.sha3()); foreachPeer([&](shared_ptr _p) { bytes b; @@ -291,28 +297,7 @@ void EthereumHost::onPeerTransactions(std::shared_ptr _peer, RLP c } unsigned itemCount = _r.itemCount(); clog(NetAllDetail) << "Transactions (" << dec << itemCount << "entries)"; - Guard l(_peer->x_knownTransactions); - for (unsigned i = 0; i < min(itemCount, 32); ++i) // process 256 transactions at most. TODO: much better solution. - { - auto h = sha3(_r[i].data()); - _peer->m_knownTransactions.insert(h); - ImportResult ir = m_tq.import(_r[i].data()); - switch (ir) - { - case ImportResult::Malformed: - _peer->addRating(-100); - break; - case ImportResult::AlreadyKnown: - // if we already had the transaction, then don't bother sending it on. - m_transactionsSent.insert(h); - _peer->addRating(0); - break; - case ImportResult::Success: - _peer->addRating(100); - break; - default:; - } - } + m_tq.enqueue(_r, _peer->session()->id()); } void EthereumHost::onPeerAborting() @@ -344,3 +329,37 @@ SyncStatus EthereumHost::status() const return SyncStatus(); return m_sync->status(); } + +void EthereumHost::onTransactionImported(ImportResult _ir, h256 const& _h, h512 const& _nodeId) +{ + auto session = host()->peerSession(_nodeId); + if (!session) + return; + + std::shared_ptr peer = session->cap(); + if (!peer) + peer = session->cap(c_oldProtocolVersion); + if (!peer) + return; + + Guard l(peer->x_knownTransactions); + peer->m_knownTransactions.insert(_h); + switch (_ir) + { + case ImportResult::Malformed: + peer->addRating(-100); + break; + case ImportResult::AlreadyKnown: + // if we already had the transaction, then don't bother sending it on. + { + Guard l(x_transactions); + m_transactionsSent.insert(_h); + } + peer->addRating(0); + break; + case ImportResult::Success: + peer->addRating(100); + break; + default:; + } +} diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index 5c5f16ff7..b65ddb5d0 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -105,6 +105,7 @@ private: void maintainTransactions(); void maintainBlocks(h256 const& _currentBlock); + void onTransactionImported(ImportResult _ir, h256 const& _h, h512 const& _nodeId); /// Check to see if the network peer-state initialisation has happened. bool isInitialised() const { return (bool)m_latestBlockSent; } @@ -132,6 +133,7 @@ private: bool m_newBlocks = false; mutable Mutex x_sync; + mutable Mutex x_transactions; DownloadMan m_man; std::unique_ptr m_sync; }; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 5362f6f68..d1afd0403 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -38,6 +38,7 @@ #include "Executive.h" #include "CachedAddressState.h" #include "CanonBlockChain.h" +#include "TransactionQueue.h" using namespace std; using namespace dev; using namespace dev::eth; diff --git a/libethereum/State.h b/libethereum/State.h index 2a63aeda4..ef8a3251a 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -32,7 +32,6 @@ #include #include #include -#include "TransactionQueue.h" #include "Account.h" #include "Transaction.h" #include "TransactionReceipt.h" @@ -67,6 +66,7 @@ using LogBloomRequirementError = boost::tupleverifierBody(); + }) +{ +} + +TransactionQueue::~TransactionQueue() +{ + m_aborting = true; + m_queueReady.notify_all(); + m_verifier.join(); +} + +ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, IfDropped _ik) { // Check if we already know this transaction. h256 h = sha3(_transactionRLP); @@ -49,14 +67,13 @@ ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallb { t = Transaction(_transactionRLP, CheckTransaction::Everything); UpgradeGuard ul(l); - ir = manageImport_WITH_LOCK(h, t, _cb); + ir = manageImport_WITH_LOCK(h, t); } catch (...) { return ImportResult::Malformed; } } -// cdebug << "import-END: Nonce of" << t.sender() << "now" << maxNonce(t.sender()); return ir; } @@ -71,27 +88,24 @@ ImportResult TransactionQueue::check_WITH_LOCK(h256 const& _h, IfDropped _ik) return ImportResult::Success; } -ImportResult TransactionQueue::import(Transaction const& _transaction, ImportCallback const& _cb, IfDropped _ik) +ImportResult TransactionQueue::import(Transaction const& _transaction, IfDropped _ik) { // Check if we already know this transaction. h256 h = _transaction.sha3(WithSignature); -// cdebug << "import-BEGIN: Nonce of sender" << maxNonce(_transaction.sender()); ImportResult ret; { UpgradableGuard l(m_lock); // TODO: keep old transactions around and check in State for nonce validity - auto ir = check_WITH_LOCK(h, _ik); if (ir != ImportResult::Success) return ir; { UpgradeGuard ul(l); - ret = manageImport_WITH_LOCK(h, _transaction, _cb); + ret = manageImport_WITH_LOCK(h, _transaction); } } -// cdebug << "import-END: Nonce of" << _transaction.sender() << "now" << maxNonce(_transaction.sender()); return ret; } @@ -111,7 +125,7 @@ h256Hash TransactionQueue::knownTransactions() const return m_known; } -ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transaction const& _transaction, ImportCallback const& _cb) +ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transaction const& _transaction) { try { @@ -149,10 +163,8 @@ ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transactio } } } - // If valid, append to blocks. + // If valid, append to transactions. insertCurrent_WITH_LOCK(make_pair(_h, _transaction)); - if (_cb) - m_callbacks[_h] = _cb; clog(TransactionQueueTraceChannel) << "Queued vaguely legit-looking transaction" << _h; while (m_current.size() > m_limit) @@ -179,7 +191,6 @@ ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transactio u256 TransactionQueue::maxNonce(Address const& _a) const { -// cdebug << "txQ::maxNonce" << _a; ReadGuard l(m_lock); return maxNonce_WITH_LOCK(_a); } @@ -212,29 +223,7 @@ void TransactionQueue::insertCurrent_WITH_LOCK(std::pair cons m_currentByHash[_p.first] = handle; // Move following transactions from future to current - auto fs = m_future.find(t.from()); - if (fs != m_future.end()) - { - u256 nonce = t.nonce() + 1; - auto fb = fs->second.find(nonce); - if (fb != fs->second.end()) - { - auto ft = fb; - while (ft != fs->second.end() && ft->second.transaction.nonce() == nonce) - { - inserted = m_currentByAddressAndNonce[t.from()].insert(std::make_pair(ft->second.transaction.nonce(), PriorityQueue::iterator())); - PriorityQueue::iterator handle = m_current.emplace(move(ft->second)); - inserted.first->second = handle; - m_currentByHash[(*handle).transaction.sha3()] = handle; - --m_futureSize; - ++ft; - ++nonce; - } - fs->second.erase(fb, ft); - if (fs->second.empty()) - m_future.erase(t.from()); - } - } + makeCurrent_WITH_LOCK(t); m_known.insert(_p.first); } @@ -296,6 +285,33 @@ void TransactionQueue::setFuture(h256 const& _txHash) m_currentByAddressAndNonce.erase(from); } +void TransactionQueue::makeCurrent_WITH_LOCK(Transaction const& _t) +{ + auto fs = m_future.find(_t.from()); + if (fs != m_future.end()) + { + u256 nonce = _t.nonce() + 1; + auto fb = fs->second.find(nonce); + if (fb != fs->second.end()) + { + auto ft = fb; + while (ft != fs->second.end() && ft->second.transaction.nonce() == nonce) + { + auto inserted = m_currentByAddressAndNonce[_t.from()].insert(std::make_pair(ft->second.transaction.nonce(), PriorityQueue::iterator())); + PriorityQueue::iterator handle = m_current.emplace(move(ft->second)); + inserted.first->second = handle; + m_currentByHash[(*handle).transaction.sha3()] = handle; + --m_futureSize; + ++ft; + ++nonce; + } + fs->second.erase(fb, ft); + if (fs->second.empty()) + m_future.erase(_t.from()); + } + } +} + void TransactionQueue::drop(h256 const& _txHash) { UpgradableGuard l(m_lock); @@ -305,9 +321,17 @@ void TransactionQueue::drop(h256 const& _txHash) UpgradeGuard ul(l); m_dropped.insert(_txHash); - remove_WITH_LOCK(_txHash); +} +void TransactionQueue::dropGood(Transaction const& _t) +{ + WriteGuard l(m_lock); + makeCurrent_WITH_LOCK(_t); + if (!m_known.count(_t.sha3())) + return; + m_dropped.insert(_t.sha3()); + remove_WITH_LOCK(_t.sha3()); } void TransactionQueue::clear() @@ -320,3 +344,43 @@ void TransactionQueue::clear() m_future.clear(); m_futureSize = 0; } + +void TransactionQueue::enqueue(RLP const& _data, h512 const& _nodeId) +{ + unique_lock l(x_queue); + unsigned itemCount = _data.itemCount(); + for (unsigned i = 0; i < itemCount; ++i) + m_unverified.emplace_back(UnverifiedTransaction(_data[i].data(), _nodeId)); + m_queueReady.notify_all(); +} + +void TransactionQueue::verifierBody() +{ + while (!m_aborting) + { + UnverifiedTransaction work; + + { + unique_lock l(x_queue); + m_queueReady.wait(l, [&](){ return !m_unverified.empty() || m_aborting; }); + if (m_aborting) + return; + work = move(m_unverified.front()); + m_unverified.pop_front(); + } + + try + { + + Transaction t(work.transaction, CheckTransaction::Cheap); + ImportResult ir = import(t); + m_onImport(ir, t.sha3(), work.nodeId); + } + catch (...) + { + // should not happen as exceptions are handled in import. + cwarn << "Bad transaction:" << boost::current_exception_diagnostic_information(); + } + } +} + diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index d92a73dab..cc6b1ca3e 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -22,6 +22,8 @@ #pragma once #include +#include +#include #include #include #include @@ -49,15 +51,14 @@ enum class IfDropped { Ignore, Retry }; class TransactionQueue { public: - using ImportCallback = std::function; - /// @brief TransactionQueue /// @param _limit Maximum number of pending transactions in the queue /// @param _futureLimit Maximum number of future nonce transactions - TransactionQueue(unsigned _limit = 1024, unsigned _futureLimit = 1024): m_current(PriorityCompare { *this }), m_limit(_limit), m_futureLimit(_futureLimit) {} - ImportResult import(Transaction const& _tx, ImportCallback const& _cb = ImportCallback(), IfDropped _ik = IfDropped::Ignore); - ImportResult import(bytes const& _tx, ImportCallback const& _cb = ImportCallback(), IfDropped _ik = IfDropped::Ignore) { return import(&_tx, _cb, _ik); } - ImportResult import(bytesConstRef _tx, ImportCallback const& _cb = ImportCallback(), IfDropped _ik = IfDropped::Ignore); + TransactionQueue(unsigned _limit = 1024, unsigned _futureLimit = 1024); + ~TransactionQueue(); + void enqueue(RLP const& _data, h512 const& _nodeId); + ImportResult import(bytes const& _tx, IfDropped _ik = IfDropped::Ignore) { return import(&_tx, _ik); } + ImportResult import(Transaction const& _tx, IfDropped _ik = IfDropped::Ignore); void drop(h256 const& _txHash); @@ -66,9 +67,11 @@ public: h256Hash knownTransactions() const; u256 maxNonce(Address const& _a) const; void setFuture(h256 const& _t); + void dropGood(Transaction const& _t); void clear(); - template Handler onReady(T const& _t) { return m_onReady.add(_t); } + template Handler<> onReady(T const& _t) { return m_onReady.add(_t); } + template Handler onImport(T const& _t) { return m_onImport.add(_t); } private: struct VerifiedTransaction @@ -77,11 +80,25 @@ private: VerifiedTransaction(VerifiedTransaction&& _t): transaction(std::move(_t.transaction)) {} VerifiedTransaction(VerifiedTransaction const&) = delete; - VerifiedTransaction operator=(VerifiedTransaction const&) = delete; + VerifiedTransaction& operator=(VerifiedTransaction const&) = delete; Transaction transaction; }; + struct UnverifiedTransaction + { + UnverifiedTransaction() {} + UnverifiedTransaction(bytesConstRef const& _t, h512 const& _nodeId): transaction(std::move(_t.toBytes())), nodeId(_nodeId) {} + UnverifiedTransaction(UnverifiedTransaction&& _t): transaction(std::move(_t.transaction)) {} + UnverifiedTransaction& operator=(UnverifiedTransaction&& _other) { transaction = std::move(_other.transaction); nodeId = std::move(_other.nodeId); return *this; } + + UnverifiedTransaction(UnverifiedTransaction const&) = delete; + UnverifiedTransaction& operator=(UnverifiedTransaction const&) = delete; + + bytes transaction; + h512 nodeId; + }; + struct PriorityCompare { TransactionQueue& queue; @@ -96,12 +113,15 @@ private: // Use a set with dynamic comparator for minmax priority queue. The comparator takes into account min account nonce. Updating it does not affect the order. using PriorityQueue = std::multiset; + ImportResult import(bytesConstRef _tx, IfDropped _ik = IfDropped::Ignore); ImportResult check_WITH_LOCK(h256 const& _h, IfDropped _ik); - ImportResult manageImport_WITH_LOCK(h256 const& _h, Transaction const& _transaction, ImportCallback const& _cb); + ImportResult manageImport_WITH_LOCK(h256 const& _h, Transaction const& _transaction); void insertCurrent_WITH_LOCK(std::pair const& _p); + void makeCurrent_WITH_LOCK(Transaction const& _t); bool remove_WITH_LOCK(h256 const& _txHash); u256 maxNonce_WITH_LOCK(Address const& _a) const; + void verifierBody(); mutable SharedMutex m_lock; ///< General lock. h256Hash m_known; ///< Hashes of transactions in both sets. @@ -114,10 +134,17 @@ private: std::unordered_map> m_currentByAddressAndNonce; ///< Transactions grouped by account and nonce std::unordered_map> m_future; /// Future transactions - Signal m_onReady; ///< Called when a subsequent call to import transactions will return a non-empty container. Be nice and exit fast. + Signal<> m_onReady; ///< Called when a subsequent call to import transactions will return a non-empty container. Be nice and exit fast. + Signal m_onImport; ///< Called for each import attempt. Arguments are result, transaction id an node id. Be nice and exit fast. unsigned m_limit; ///< Max number of pending transactions unsigned m_futureLimit; ///< Max number of future transactions unsigned m_futureSize = 0; ///< Current number of future transactions + + std::condition_variable m_queueReady; ///< Signaled when m_unverified has a new entry. + std::thread m_verifier; ///< Verification thread + std::deque m_unverified; ///< Pending verification queue + mutable Mutex x_queue; ///< Verification queue mutex + bool m_aborting = false; ///< Exit condition for verifier. }; } diff --git a/libp2p/Host.h b/libp2p/Host.h index b7ebb3951..17e98f8f6 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -202,6 +202,9 @@ public: /// Validates and starts peer session, taking ownership of _io. Disconnects and returns false upon error. void startPeerSession(Public const& _id, RLP const& _hello, RLPXFrameCoder* _io, std::shared_ptr const& _s); + /// Get session by id + std::shared_ptr peerSession(NodeId const& _id) { RecursiveGuard l(x_sessions); return m_sessions.count(_id) ? m_sessions[_id].lock() : std::shared_ptr(); } + protected: void onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e); @@ -211,8 +214,8 @@ protected: private: enum PeerSlotRatio { Egress = 2, Ingress = 9 }; - bool havePeerSession(NodeId _id) { RecursiveGuard l(x_sessions); return m_sessions.count(_id) ? !!m_sessions[_id].lock() : false; } - + bool havePeerSession(NodeId const& _id) { return !!peerSession(_id); } + /// Determines and sets m_tcpPublic to publicly advertised address. void determinePublic(); diff --git a/test/libethereum/blockchain.cpp b/test/libethereum/blockchain.cpp index 6455eee17..6dea609e2 100644 --- a/test/libethereum/blockchain.cpp +++ b/test/libethereum/blockchain.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include using namespace std; From 3751eabfa8fbc0839558e6c131c801e1f70693f9 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 6 Jul 2015 00:01:11 +0200 Subject: [PATCH 160/290] mutiple threads, added m_future limit check --- libethereum/TransactionQueue.cpp | 28 +++++++++++++++++++++------- libethereum/TransactionQueue.h | 2 +- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 5f4709cb5..28a56cdf8 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -34,19 +34,22 @@ const char* TransactionQueueTraceChannel::name() { return EthCyan " ┅▶"; } TransactionQueue::TransactionQueue(unsigned _limit, unsigned _futureLimit): m_current(PriorityCompare { *this }), m_limit(_limit), - m_futureLimit(_futureLimit), - m_verifier([=](){ - setThreadName("tr verified"); - this->verifierBody(); - }) + m_futureLimit(_futureLimit) { + unsigned verifierThreads = std::max(thread::hardware_concurrency(), 3U) - 2U; + for (unsigned i = 0; i < verifierThreads; ++i) + m_verifiers.emplace_back([=](){ + setThreadName("txcheck" + toString(i)); + this->verifierBody(); + }); } TransactionQueue::~TransactionQueue() { m_aborting = true; m_queueReady.notify_all(); - m_verifier.join(); + for (auto& i: m_verifiers) + i.join(); } ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, IfDropped _ik) @@ -310,6 +313,17 @@ void TransactionQueue::makeCurrent_WITH_LOCK(Transaction const& _t) m_future.erase(_t.from()); } } + + while (m_futureSize > m_futureLimit) + { + // TODO: priority queue for future transactions + // For now just drop random chain end + --m_futureSize; + clog(TransactionQueueTraceChannel) << "Dropping out of bounds future transaction" << m_future.begin()->second.rbegin()->second.transaction.sha3(); + m_future.begin()->second.erase(--m_future.begin()->second.end()); + if (m_future.begin()->second.empty()) + m_future.erase(m_future.begin()); + } } void TransactionQueue::drop(h256 const& _txHash) @@ -372,7 +386,7 @@ void TransactionQueue::verifierBody() try { - Transaction t(work.transaction, CheckTransaction::Cheap); + Transaction t(work.transaction, CheckTransaction::Cheap); //Signature will be checked later ImportResult ir = import(t); m_onImport(ir, t.sha3(), work.nodeId); } diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index cc6b1ca3e..000681363 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -141,7 +141,7 @@ private: unsigned m_futureSize = 0; ///< Current number of future transactions std::condition_variable m_queueReady; ///< Signaled when m_unverified has a new entry. - std::thread m_verifier; ///< Verification thread + std::vector m_verifiers; std::deque m_unverified; ///< Pending verification queue mutable Mutex x_queue; ///< Verification queue mutex bool m_aborting = false; ///< Exit condition for verifier. From 8689bc8164d2eaf54907e335a033fc180b3fe9e4 Mon Sep 17 00:00:00 2001 From: "arkady.paronyan@gmail.com" Date: Mon, 6 Jul 2015 00:34:10 +0200 Subject: [PATCH 161/290] msvc compilation/warnings --- libethash-cl/CMakeLists.txt | 1 + libethash-cl/ethash_cl_miner.cpp | 2 +- libethcore/Common.h | 2 +- libethereum/TransactionQueue.h | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libethash-cl/CMakeLists.txt b/libethash-cl/CMakeLists.txt index 6da254cfb..9dc45fcf5 100644 --- a/libethash-cl/CMakeLists.txt +++ b/libethash-cl/CMakeLists.txt @@ -20,6 +20,7 @@ file(GLOB OUR_HEADERS "*.h") set(HEADERS ${OUR_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/ethash_cl_miner_kernel.h) include_directories(${CMAKE_CURRENT_BINARY_DIR}) +include_directories(${Boost_INCLUDE_DIRS}) include_directories(${OpenCL_INCLUDE_DIRS}) include_directories(..) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 3a72810fa..9e2d51286 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -323,7 +323,7 @@ bool ethash_cl_miner::init( ETHCL_LOG("Printing program log"); ETHCL_LOG(program.getBuildInfo(device).c_str()); } - catch (cl::Error const& err) + catch (cl::Error const&) { ETHCL_LOG(program.getBuildInfo(device).c_str()); return false; diff --git a/libethcore/Common.h b/libethcore/Common.h index ba8c554fb..190774126 100644 --- a/libethcore/Common.h +++ b/libethcore/Common.h @@ -171,7 +171,7 @@ public: void operator()(Args&... _args) { for (auto const& f: m_fire) f.second->fire(std::forward(_args)...); } private: - std::map> m_fire; + std::map> m_fire; }; template using Handler = std::shared_ptr::HandlerAux>; diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index 000681363..407250530 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include From 42d9edc9b085fbde29810e5d0393bdcafe984a17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 6 Jul 2015 09:22:09 +0200 Subject: [PATCH 162/290] Fix up rvalue references. Avoid a copy of an EVM code in ExtVM. --- libethereum/Account.h | 4 +--- libethereum/VerifiedBlock.h | 2 +- libevm/ExtVMFace.cpp | 6 ++---- libevm/ExtVMFace.h | 2 +- libp2p/Session.cpp | 7 +++---- libtestutils/StateLoader.cpp | 10 +++++----- mix/DebuggingStateWrapper.h | 8 ++++---- mix/HttpServer.h | 2 +- test/TestHelper.cpp | 4 ++-- 9 files changed, 20 insertions(+), 25 deletions(-) diff --git a/libethereum/Account.h b/libethereum/Account.h index 87fc82b6c..4ab98e3ab 100644 --- a/libethereum/Account.h +++ b/libethereum/Account.h @@ -152,8 +152,7 @@ public: h256 codeHash() const { assert(!isFreshCode()); return m_codeHash; } /// Sets the code of the account. Must only be called when isFreshCode() returns true. - void setCode(bytes&& _code) { assert(isFreshCode()); m_codeCache = _code; changed(); } - void setCode(bytes const& _code) { assert(isFreshCode()); m_codeCache = _code; changed(); } + void setCode(bytes&& _code) { assert(isFreshCode()); m_codeCache = std::move(_code); changed(); } /// @returns true if the account's code is available through code(). bool codeCacheValid() const { return m_codeHash == EmptySHA3 || m_codeHash == c_contractConceptionCodeHash || m_codeCache.size(); } @@ -206,4 +205,3 @@ private: } } - diff --git a/libethereum/VerifiedBlock.h b/libethereum/VerifiedBlock.h index 5d1efb7d0..8bac12f90 100644 --- a/libethereum/VerifiedBlock.h +++ b/libethereum/VerifiedBlock.h @@ -47,7 +47,7 @@ struct VerifiedBlock VerifiedBlock(BlockInfo&& _bi) { - verified.info = _bi; + verified.info = std::move(_bi); } VerifiedBlock(VerifiedBlock&& _other): diff --git a/libevm/ExtVMFace.cpp b/libevm/ExtVMFace.cpp index ad419d2a3..f4614d669 100644 --- a/libevm/ExtVMFace.cpp +++ b/libevm/ExtVMFace.cpp @@ -21,22 +21,20 @@ #include "ExtVMFace.h" -using namespace std; using namespace dev; using namespace dev::eth; -ExtVMFace::ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytes const& _code, h256 const& _codeHash, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, LastHashes const& _lh, unsigned _depth): +ExtVMFace::ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytes _code, h256 const& _codeHash, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, LastHashes const& _lh, unsigned _depth): myAddress(_myAddress), caller(_caller), origin(_origin), value(_value), gasPrice(_gasPrice), data(_data), - code(_code), + code(std::move(_code)), codeHash(_codeHash), lastHashes(_lh), previousBlock(_previousBlock), currentBlock(_currentBlock), depth(_depth) {} - diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index f6cab376a..94c8e2fef 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -161,7 +161,7 @@ public: ExtVMFace() = default; /// Full constructor. - ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytes const& _code, h256 const& _codeHash, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, LastHashes const& _lh, unsigned _depth); + ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytes _code, h256 const& _codeHash, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, LastHashes const& _lh, unsigned _depth); virtual ~ExtVMFace() = default; diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp index 803824558..9a981786d 100644 --- a/libp2p/Session.cpp +++ b/libp2p/Session.cpp @@ -256,9 +256,8 @@ bool Session::checkPacket(bytesConstRef _msg) void Session::send(bytes&& _msg) { - clog(NetLeft) << RLP(bytesConstRef(&_msg).cropped(1)); - bytesConstRef msg(&_msg); + clog(NetLeft) << RLP(msg.cropped(1)); if (!checkPacket(msg)) clog(NetWarn) << "INVALID PACKET CONSTRUCTED!"; @@ -268,7 +267,7 @@ void Session::send(bytes&& _msg) bool doWrite = false; { Guard l(x_writeQueue); - m_writeQueue.push_back(_msg); + m_writeQueue.push_back(std::move(_msg)); doWrite = (m_writeQueue.size() == 1); } @@ -387,7 +386,7 @@ void Session::doRead() drop(BadProtocol); return; } - + /// read padded frame and mac auto tlen = header.length + header.padding + h128::size; ba::async_read(m_socket->ref(), boost::asio::buffer(m_data, tlen), [this, self, header, tlen](boost::system::error_code ec, std::size_t length) diff --git a/libtestutils/StateLoader.cpp b/libtestutils/StateLoader.cpp index 9eff30b29..235f1c573 100644 --- a/libtestutils/StateLoader.cpp +++ b/libtestutils/StateLoader.cpp @@ -1,16 +1,16 @@ /* 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 . */ @@ -36,10 +36,10 @@ StateLoader::StateLoader(Json::Value const& _json, std::string const& _dbPath): Address address = Address(name); bytes code = fromHex(o["code"].asString().substr(2)); - if (code.size()) + if (!code.empty()) { m_state.m_cache[address] = Account(u256(o["balance"].asString()), Account::ContractConception); - m_state.m_cache[address].setCode(code); + m_state.m_cache[address].setCode(std::move(code)); } else m_state.m_cache[address] = Account(u256(o["balance"].asString()), Account::NormalCreation); diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 37bc194fb..c80aecdd8 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -69,7 +69,7 @@ class QSolState: public QObject public: QSolState(QObject* _parent, QVariantMap&& _storage, QVariantList&& _callStack, QVariantMap&& _locals, int _start, int _end, QString _sourceName): - QObject(_parent), m_storage(_storage), m_callStack(_callStack), m_locals(_locals), m_start(_start), m_end(_end), m_sourceName(_sourceName) + QObject(_parent), m_storage(std::move(_storage)), m_callStack(std::move(_callStack)), m_locals(std::move(_locals)), m_start(_start), m_end(_end), m_sourceName(_sourceName) { } private: @@ -92,7 +92,7 @@ class QCode: public QObject Q_PROPERTY(QString documentId MEMBER m_document CONSTANT) public: - QCode(QObject* _owner, QString const& _address, QVariantList&& _instrunctions): QObject(_owner), m_instructions(_instrunctions), m_address(_address) {} + QCode(QObject* _owner, QString const& _address, QVariantList&& _instrunctions): QObject(_owner), m_instructions(std::move(_instrunctions)), m_address(_address) {} void setDocument(QString const& _documentId) { m_document = _documentId; } private: @@ -110,7 +110,7 @@ class QCallData: public QObject Q_PROPERTY(QVariantList items MEMBER m_items CONSTANT) public: - QCallData(QObject* _owner, QVariantList&& _items): QObject(_owner), m_items(_items) {} + QCallData(QObject* _owner, QVariantList&& _items): QObject(_owner), m_items(std::move(_items)) {} private: QVariantList m_items; @@ -126,7 +126,7 @@ class QDebugData: public QObject public: QDebugData() { } - void setStates(QVariantList&& _states) { m_states = _states; } + void setStates(QVariantList&& _states) { m_states = std::move(_states); } private: QVariantList m_states; diff --git a/mix/HttpServer.h b/mix/HttpServer.h index 50a345747..606fa4ff1 100644 --- a/mix/HttpServer.h +++ b/mix/HttpServer.h @@ -46,7 +46,7 @@ class HttpRequest: public QObject private: HttpRequest(QObject* _parent, QUrl&& _url, QString&& _content, QVariantMap&& _headers): - QObject(_parent), m_url(_url), m_content(_content), m_headers(_headers) + QObject(_parent), m_url(std::move(_url)), m_content(std::move(_content)), m_headers(std::move(_headers)) { } diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index b3dee72ec..9a1b16935 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -199,10 +199,10 @@ void ImportTest::importState(json_spirit::mObject& _o, State& _state, stateOptio stateOptions.m_bHasCode = true; } - if (code.size()) + if (!code.empty()) { _state.m_cache[address] = Account(balance, Account::ContractConception); - _state.m_cache[address].setCode(code); + _state.m_cache[address].setCode(std::move(code)); } else _state.m_cache[address] = Account(balance, Account::NormalCreation); From 2bc0fd727f45ade6c5110710de5c1909ed7b2a13 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 6 Jul 2015 10:15:49 +0200 Subject: [PATCH 163/290] build without snapshot library, extdep download v8 3.15.9 --- cmake/Findv8.cmake | 16 ++-------------- extdep/getstuff.bat | 1 + 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/cmake/Findv8.cmake b/cmake/Findv8.cmake index 63e281820..7004d0792 100644 --- a/cmake/Findv8.cmake +++ b/cmake/Findv8.cmake @@ -41,14 +41,8 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") NAMES v8_nosnapshot DOC "v8 nosnapshot library" ) - - find_library( - V8_SNAPSHOT_LIBRARY - NAMES v8_snapshot - DOC "v8 snapshotlibrary" - ) - set(V8_LIBRARIES ${V8_BASE_LIBRARY} ${V8_SNAPSHOT_LIBRARY} ${V8_NO_SNAPSHOT_LIBRARY}) + set(V8_LIBRARIES ${V8_BASE_LIBRARY} ${V8_NO_SNAPSHOT_LIBRARY}) find_library( V8_BASE_LIBRARY_DEBUG @@ -62,13 +56,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") DOC "v8 nosnapshot library" ) - find_library( - V8_SNAPSHOT_LIBRARY_DEBUG - NAMES v8_snapshotd - DOC "v8 snapshotlibrary" - ) - - set(V8_LIBRARIES optimized ${V8_LIBRARIES} debug ${V8_BASE_LIBRARY_DEBUG} ${V8_SNAPSHOT_LIBRARY_DEBUG} ${V8_NO_SNAPSHOT_LIBRARY_DEBUG}) + set(V8_LIBRARIES optimized ${V8_LIBRARIES} debug ${V8_BASE_LIBRARY_DEBUG} ${V8_NO_SNAPSHOT_LIBRARY_DEBUG}) endif() diff --git a/extdep/getstuff.bat b/extdep/getstuff.bat index 3b41f9e96..3c0b42f95 100644 --- a/extdep/getstuff.bat +++ b/extdep/getstuff.bat @@ -14,6 +14,7 @@ call :download leveldb 1.2 call :download microhttpd 0.9.2 call :download qt 5.4.1 call :download miniupnpc 1.9 +call :download v8 3.15.9 goto :EOF From 1db8e5ff71ff384afc10f05a1c455595fb713240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 6 Jul 2015 12:07:33 +0200 Subject: [PATCH 164/290] Increase stack size needed for VM execution in Debug build type. --- libethereum/ExtVM.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libethereum/ExtVM.cpp b/libethereum/ExtVM.cpp index 305462511..f8d12b62c 100644 --- a/libethereum/ExtVM.cpp +++ b/libethereum/ExtVM.cpp @@ -33,7 +33,12 @@ namespace static unsigned const c_depthLimit = 1024; /// Upper bound of stack space needed by single CALL/CREATE execution. Set experimentally. -static size_t const c_singleExecutionStackSize = 12 * 1024; +static size_t const c_singleExecutionStackSize = +#ifdef NDEBUG + 12 * 1024; +#else + 64 * 1024; +#endif /// Standard OSX thread stack limit. Should be reasonable for other platforms too. static size_t const c_defaultStackSize = 512 * 1024; @@ -68,7 +73,7 @@ void go(unsigned _depth, Executive& _e, OnOpFunc const& _onOp) { // If in the offloading point we need to switch to additional separated stack space. // Current stack is too small to handle more CALL/CREATE executions. - // It needs to be done only once as newly allocated stack space it enough to handle + // It needs to be done only once as newly allocated stack space it enough to handle // the rest of the calls up to the depth limit (c_depthLimit). if (_depth == c_offloadPoint) goOnOffloadedStack(_e, _onOp); @@ -104,4 +109,3 @@ h160 ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc io_gas = e.gas(); return e.newAddress(); } - From 35760b7055d56348b8be30e3e4c3d97f4eb86580 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 6 Jul 2015 12:43:16 +0200 Subject: [PATCH 165/290] common fixes for msvc in jsconsole --- cmake/Findv8.cmake | 8 ++++---- libjsengine/JSV8Engine.cpp | 10 +++++++--- libjsengine/JSV8Engine.h | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/cmake/Findv8.cmake b/cmake/Findv8.cmake index 7004d0792..0632afecc 100644 --- a/cmake/Findv8.cmake +++ b/cmake/Findv8.cmake @@ -31,7 +31,7 @@ set(V8_LIBRARIES ${V8_LIBRARY}) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") find_library( - V8_BASE_LIBRARY + V8_LIBRARY NAMES v8_base DOC "v8 base library" ) @@ -42,10 +42,10 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") DOC "v8 nosnapshot library" ) - set(V8_LIBRARIES ${V8_BASE_LIBRARY} ${V8_NO_SNAPSHOT_LIBRARY}) + set(V8_LIBRARIES ${V8_LIBRARY} ${V8_NO_SNAPSHOT_LIBRARY}) find_library( - V8_BASE_LIBRARY_DEBUG + V8_LIBRARY_DEBUG NAMES v8_based DOC "v8 base library" ) @@ -56,7 +56,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") DOC "v8 nosnapshot library" ) - set(V8_LIBRARIES optimized ${V8_LIBRARIES} debug ${V8_BASE_LIBRARY_DEBUG} ${V8_NO_SNAPSHOT_LIBRARY_DEBUG}) + set(V8_LIBRARIES optimized ${V8_LIBRARIES} debug ${V8_LIBRARY_DEBUG} ${V8_NO_SNAPSHOT_LIBRARY_DEBUG}) endif() diff --git a/libjsengine/JSV8Engine.cpp b/libjsengine/JSV8Engine.cpp index ebf0a0e72..4c7fd830a 100644 --- a/libjsengine/JSV8Engine.cpp +++ b/libjsengine/JSV8Engine.cpp @@ -90,6 +90,12 @@ void reportException(v8::TryCatch* _tryCatch) class JSV8Env { public: + static JSV8Env& getInstance() + { + static JSV8Env s_env; + return s_env; + } + ~JSV8Env() { v8::V8::Dispose(); @@ -124,8 +130,6 @@ private: } } -JSV8Env JSV8Engine::s_env = JSV8Env(); - JSString JSV8Value::toString() const { if (m_value.IsEmpty()) @@ -138,7 +142,7 @@ JSString JSV8Value::toString() const return toCString(str); } -JSV8Engine::JSV8Engine(): m_scope(new JSV8Scope()) +JSV8Engine::JSV8Engine(): m_env(JSV8Env::getInstance()), m_scope(new JSV8Scope()) { JSEngineResources resources; string common = resources.loadResourceAsString("common"); diff --git a/libjsengine/JSV8Engine.h b/libjsengine/JSV8Engine.h index 563642d73..3a5974bb7 100644 --- a/libjsengine/JSV8Engine.h +++ b/libjsengine/JSV8Engine.h @@ -56,7 +56,7 @@ public: v8::Handle const& context() const; private: - static JSV8Env s_env; + JSV8Env const& m_env; JSV8Scope* m_scope; }; From 4333752691f33c53dd2a85fad77b3f6f46a4c65b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 6 Jul 2015 13:08:21 +0200 Subject: [PATCH 166/290] fixed jsconsole getline --- libjsconsole/JSConsole.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libjsconsole/JSConsole.h b/libjsconsole/JSConsole.h index 9c7256557..77f316442 100644 --- a/libjsconsole/JSConsole.h +++ b/libjsconsole/JSConsole.h @@ -65,10 +65,11 @@ public: free(buff); } #else - std::cout << promptForIndentionLevel(openBrackets) << std::endl << std::flush; + std::cout << promptForIndentionLevel(openBrackets) << std::flush; std::getline(std::cin, rl); + isEmpty = rl.length() == 0; #endif - if (rl.length() > 0) + if (!isEmpty) { cmd += rl; cmd += " "; From 537fb66645d7e944fdef2e7205b01e3d9812bece Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 3 Jul 2015 17:25:06 +0200 Subject: [PATCH 167/290] Some comments for TrieCommon.h --- libdevcore/TrieCommon.h | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/libdevcore/TrieCommon.h b/libdevcore/TrieCommon.h index 8d6be8ebd..822cc66e4 100644 --- a/libdevcore/TrieCommon.h +++ b/libdevcore/TrieCommon.h @@ -32,26 +32,38 @@ inline byte nibble(bytesConstRef _data, unsigned _i) return (_i & 1) ? (_data[_i / 2] & 15) : (_data[_i / 2] >> 4); } -inline unsigned sharedNibbles(bytesConstRef _a, unsigned _ab, unsigned _ae, bytesConstRef _b, unsigned _bb, unsigned _be) +/// Interprets @a _first and @a _second as vectors of nibbles and returns the length of the longest common +/// prefix of _first[_beginFirst..._endFirst] and _second[_beginSecond..._endSecond]. +inline unsigned sharedNibbles(bytesConstRef _first, unsigned _beginFirst, unsigned _endFirst, bytesConstRef _second, unsigned _beginSecond, unsigned _endSecond) { unsigned ret = 0; - for (unsigned ai = _ab, bi = _bb; ai < _ae && bi < _be && nibble(_a, ai) == nibble(_b, bi); ++ai, ++bi, ++ret) {} + while (_beginFirst < _endFirst && _beginSecond < _endSecond && nibble(_first, _beginFirst) == nibble(_second, _beginSecond)) + { + ++_beginFirst; + ++_beginSecond; + ++ret; + } return ret; } +/** + * Nibble-based view on a bytesConstRef. + */ struct NibbleSlice { bytesConstRef data; unsigned offset; - NibbleSlice(bytesConstRef _d = bytesConstRef(), unsigned _o = 0): data(_d), offset(_o) {} + NibbleSlice(bytesConstRef _data = bytesConstRef(), unsigned _offset = 0): data(_data), offset(_offset) {} byte operator[](unsigned _index) const { return nibble(data, offset + _index); } unsigned size() const { return data.size() * 2 - offset; } bool empty() const { return !size(); } NibbleSlice mid(unsigned _index) const { return NibbleSlice(data, offset + _index); } void clear() { data.reset(); offset = 0; } + /// @returns true iff _k is a prefix of this. bool contains(NibbleSlice _k) const { return shared(_k) == _k.size(); } + /// @returns the number of shared nibbles at the beginning of this and _k. unsigned shared(NibbleSlice _k) const { return sharedNibbles(data, offset, offset + size(), _k.data, _k.offset, _k.offset + _k.size()); } /** * @brief Determine if we, a full key, are situated prior to a particular key-prefix. @@ -60,8 +72,8 @@ struct NibbleSlice */ bool isEarlierThan(NibbleSlice _k) const { - unsigned i; - for (i = 0; i < _k.size() && i < size(); ++i) + unsigned i = 0; + for (; i < _k.size() && i < size(); ++i) if (operator[](i) < _k[i]) // Byte is lower - we're earlier.. return true; else if (operator[](i) > _k[i]) // Byte is higher - we're not earlier. From 5fc72145af2085993702e39916db1cf20fb6a321 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 6 Jul 2015 13:31:52 +0200 Subject: [PATCH 168/290] noexcept only on *nix --- libjsengine/JSEngine.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libjsengine/JSEngine.h b/libjsengine/JSEngine.h index afd7292bd..d44fc7828 100644 --- a/libjsengine/JSEngine.h +++ b/libjsengine/JSEngine.h @@ -29,7 +29,11 @@ namespace eth { class JSException: public std::exception {}; +#if defined(_MSC_VER) class JSPrintException: public JSException { char const* what() const { return "Cannot print expression!"; } }; +#else +class JSPrintException: public JSException { char const* what() const noexcept { return "Cannot print expression!"; } }; +#endif class JSString { From eb2bc3e69fe729a93efb159abc3a616c2d0d4347 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 6 Jul 2015 13:41:19 +0200 Subject: [PATCH 169/290] sync status CLI --- eth/main.cpp | 3 +++ libethereum/BlockChainSync.cpp | 11 +++++++++++ libethereum/BlockChainSync.h | 3 +++ 3 files changed, 17 insertions(+) diff --git a/eth/main.cpp b/eth/main.cpp index 9cd270a16..e4facccee 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -375,6 +376,8 @@ void interactiveMode(eth::Client* c, std::shared_ptr gasP cout << "Current block: " << c->blockChain().details().number << endl; else if (c && cmd == "blockqueue") cout << "Current blockqueue status: " << endl << c->blockQueueStatus() << endl; + else if (c && cmd == "sync") + cout << "Current sync status: " << endl << c->syncStatus() << endl; else if (c && cmd == "hashrate") cout << "Current hash rate: " << toString(c->hashrate()) << " hashes per second." << endl; else if (c && cmd == "findblock") diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index b8c613a54..90dc70574 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -41,6 +41,17 @@ using namespace p2p; unsigned const c_chainReorgSize = 30000; /// Added to estimated hashes to account for potential chain reorganiation unsigned const c_hashSubchainSize = 8192; /// PV61 subchain size +std::ostream& dev::eth::operator<<(std::ostream& _out, SyncStatus const& _sync) +{ + _out << "protocol: " << _sync.protocolVersion << endl; + _out << "state: " << EthereumHost::stateName(_sync.state) << " "; + if (_sync.state == SyncState::Hashes) + _out << _sync.hashesReceived << "/" << (_sync.hashesEstimated ? "~" : "") << _sync.hashesTotal; + if (_sync.state == SyncState::Blocks || _sync.state == SyncState::NewBlocks) + _out << _sync.blocksReceived << "/" << _sync.blocksTotal; + return _out; +} + BlockChainSync::BlockChainSync(EthereumHost& _host): m_host(_host) { diff --git a/libethereum/BlockChainSync.h b/libethereum/BlockChainSync.h index 5501075fd..0c104882b 100644 --- a/libethereum/BlockChainSync.h +++ b/libethereum/BlockChainSync.h @@ -316,5 +316,8 @@ private: unsigned m_syncingBlockNumber = 0; ///< Current subchain marker bool m_hashScanComplete = false; ///< True if leading peer completed hashchain scan and we have a list of subchains ready }; + +std::ostream& operator<<(std::ostream& _out, SyncStatus const& _sync); + } } From 050ee239fdef426ce01ea7bfb6266f97defffc94 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 6 Jul 2015 13:58:33 +0200 Subject: [PATCH 170/290] locking improvements --- libethereum/TransactionQueue.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 28a56cdf8..36d337e7b 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -361,10 +361,12 @@ void TransactionQueue::clear() void TransactionQueue::enqueue(RLP const& _data, h512 const& _nodeId) { - unique_lock l(x_queue); - unsigned itemCount = _data.itemCount(); - for (unsigned i = 0; i < itemCount; ++i) - m_unverified.emplace_back(UnverifiedTransaction(_data[i].data(), _nodeId)); + { + Guard l(x_queue); + unsigned itemCount = _data.itemCount(); + for (unsigned i = 0; i < itemCount; ++i) + m_unverified.emplace_back(UnverifiedTransaction(_data[i].data(), _nodeId)); + } m_queueReady.notify_all(); } @@ -385,7 +387,6 @@ void TransactionQueue::verifierBody() try { - Transaction t(work.transaction, CheckTransaction::Cheap); //Signature will be checked later ImportResult ir = import(t); m_onImport(ir, t.sha3(), work.nodeId); From 871a7c4bc9167f8eaff07c1c345eff59776e257e Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 6 Jul 2015 14:46:01 +0200 Subject: [PATCH 171/290] don't refresh blockchain if not visible --- alethzero/Main.ui | 2 +- alethzero/MainWin.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/alethzero/Main.ui b/alethzero/Main.ui index 2515959ad..67a15d248 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -707,7 +707,7 @@ - + QDockWidget::DockWidgetFeatureMask diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 964553b03..1e4577bf5 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -260,6 +260,8 @@ Main::Main(QWidget *parent) : m_transact->setWindowFlags(Qt::Dialog); m_transact->setWindowModality(Qt::WindowModal); + connect(ui->blockChainDockWidget, &QDockWidget::visibilityChanged, [=]() { refreshBlockChain(); }); + #if !ETH_FATDB removeDockWidget(ui->dockWidget_accounts); #endif @@ -1307,7 +1309,7 @@ void Main::on_turboMining_triggered() void Main::refreshBlockChain() { - if (!ui->blocks->isVisible() && isVisible()) + if (!(ui->blockChainDockWidget->isVisible() || !tabifiedDockWidgets(ui->blockChainDockWidget).isEmpty())) return; DEV_TIMED_FUNCTION_ABOVE(500); From bc9bdf09af335b6c8e50b522fa1ff57900e32c7d Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 6 Jul 2015 15:58:07 +0200 Subject: [PATCH 172/290] Move defaults so that cl_miner is not included in MinerAux.h --- ethminer/MinerAux.h | 1 - libethash-cl/ethash_cl_miner.h | 7 ------- libethcore/Ethash.h | 7 +++++++ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 9c199cecb..eba68a4c3 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -39,7 +39,6 @@ #include #include #include -#include #include #if ETH_JSONRPC || !ETH_TRUE #include diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h index c60ee1881..8f7594be5 100644 --- a/libethash-cl/ethash_cl_miner.h +++ b/libethash-cl/ethash_cl_miner.h @@ -17,13 +17,6 @@ #include #include -/// Default value of the local work size. Also known as workgroup size. -#define CL_DEFAULT_LOCAL_WORK_SIZE 64 -/// Default value of the global work size as a multiplier of the local work size -#define CL_DEFAULT_GLOBAL_WORK_SIZE_MULTIPLIER 512 // * CL_DEFAULT_LOCAL_WORK_SIZE -/// Default value of the milliseconds per global work size (per batch) -#define CL_DEFAULT_MS_PER_BATCH 100 - class ethash_cl_miner { private: diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index e9ddf16ca..8cc392306 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -31,6 +31,13 @@ #include "BlockInfo.h" #include "Miner.h" +/// Default value of the local work size. Also known as workgroup size. +#define CL_DEFAULT_LOCAL_WORK_SIZE 64 +/// Default value of the global work size as a multiplier of the local work size +#define CL_DEFAULT_GLOBAL_WORK_SIZE_MULTIPLIER 512 // * CL_DEFAULT_LOCAL_WORK_SIZE +/// Default value of the milliseconds per global work size (per batch) +#define CL_DEFAULT_MS_PER_BATCH 100 + class ethash_cl_miner; namespace dev From bd133628cb4484dc7d9066bc2468a43090a3e040 Mon Sep 17 00:00:00 2001 From: Dimitry Khokhlov Date: Mon, 6 Jul 2015 18:14:39 +0400 Subject: [PATCH 173/290] stPreCompiledContracts remove as there is no 'out' when calling contracts from transaction --- ...PreCompiledContractsTransactionFiller.json | 854 ------------------ test/libethereum/state.cpp | 5 - 2 files changed, 859 deletions(-) delete mode 100644 test/libethereum/StateTestsFiller/stPreCompiledContractsTransactionFiller.json diff --git a/test/libethereum/StateTestsFiller/stPreCompiledContractsTransactionFiller.json b/test/libethereum/StateTestsFiller/stPreCompiledContractsTransactionFiller.json deleted file mode 100644 index ff1e8c5d1..000000000 --- a/test/libethereum/StateTestsFiller/stPreCompiledContractsTransactionFiller.json +++ /dev/null @@ -1,854 +0,0 @@ -{ - "CallEcrecover0": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "300000", - "to" : "0000000000000000000000000000000000000001", - "value" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549" - } - }, - - "CallEcrecover80": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x0000000000000000000000003f17f1962b36e491b30a40b2405849e597ba5fb5", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "300000", - "to" : "0000000000000000000000000000000000000001", - "value" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "00c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c00b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f00b940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549" - } - }, - - "CallEcrecover0_gas3000": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "3000", - "to" : "0000000000000000000000000000000000000001", - "value" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549" - } - }, - - "CallEcrecover0_0input": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x0000000000000000000000000000000000000000000000000000000000000000", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "300000", - "to" : "0000000000000000000000000000000000000001", - "value" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "" - } - }, - - "CallEcrecover1": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x0000000000000000000000000000000000000000000000000000000000000000", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "300000", - "to" : "0000000000000000000000000000000000000001", - "value" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000000173b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549" - } - }, - - "CallEcrecover2": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x0000000000000000000000000000000000000000000000000000000000000000", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "300000", - "to" : "0000000000000000000000000000000000000001", - "value" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c0073b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549" - } - }, - - "CallEcrecover3": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x000000000000000000000000e4319f4b631c6d0fcfc84045dbcb676865fe5e13", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "300000", - "to" : "0000000000000000000000000000000000000001", - "value" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "2f380a2dea7e778d81affc2443403b8fe4644db442ae4862ff5bb3732829cdb9000000000000000000000000000000000000000000000000000000000000001b6b65ccb0558806e9b097f27a396d08f964e37b8b7af6ceeb516ff86739fbea0a37cbc8d883e129a4b1ef9d5f1df53c4f21a3ef147cf2a50a4ede0eb06ce092d4" - } - }, - - "CallSha256_0": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0xec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "300000", - "to" : "0000000000000000000000000000000000000002", - "value" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "000000000000000000000000000000000000000000000000000000000000001" - } - }, - - "CallSha256_2": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "300000", - "to" : "0000000000000000000000000000000000000002", - "value" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "" - } - }, - - "CallSha256_1_nonzeroValue": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000002", - "value" : "0x13", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "" - } - }, - - "CallSha256_2": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0xcb39b3bde22925b2f931111130c774761d8895e0e08437c9b396c1e97d10f34d", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000002", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "0000000000000000000000000000000000000000000000000000000000000000f34578907f" - } - }, - - "CallSha256_3": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x7392925565d67be8e9620aacbcfaecd8cb6ec58d709d25da9eccf1d08a41ce35", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000002", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "000000000000000000000000000000000000000000000000000000f34578907f0000000000" - } - }, - - "CallSha256_4": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0xaf9613760f72635fbdb44a5a0a63c39f12af30f950a6ee5c971be188e89c4051", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000002", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - } - }, - - "CallSha256_5": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x259911ec9f4b02b7975dfa3f5da78fc58b7066604bdaea66c4485c90f6f55bec", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000002", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - } - }, - - "CallRipemd160_0": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x000000000000000000000000ae387fcfeb723c3f5964509af111cf5a67f30661", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000003", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "000000000000000000000000000000000000000000000000000000000000001" - } - }, - - "CallRipemd160_1": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x0000000000000000000000009c1185a5c5e9fc54612808977ee8f548b2258d31", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000003", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "" - } - }, - - "CallRipemd160_2": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x000000000000000000000000dbc100f916bfbc53535573d98cf0cbb3a5b36124", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000003", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "0000000000000000000000000000000000000000000000000000000000000000f34578907f" - } - }, - - "CallRipemd160_3": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x000000000000000000000000316750573f9be26bc17727b47cacedbd0ab3e6ca", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000003", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "000000000000000000000000000000000000000000000000000000f34578907f0000000000" - } - }, - - "CallRipemd160_4": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x0000000000000000000000001cf4e77f5966e13e109703cd8a0df7ceda7f3dc3", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000003", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - } - }, - - "CallRipemd160_5": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000003", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - } - }, - - "CallIdentitiy_0": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x0000000000000000000000000000000000000000000000000000000000000001", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000004", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "000000000000000000000000000000000000000000000000000000000000001" - } - }, - - "CallIdentitiy_1": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000004", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "" - } - }, - - "CallIdentitiy_1_nonzeroValue": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000004", - "value" : "0x13", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "" - } - }, - - "CallIdentitiy_2": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x0000000000000000000000000000000000000000000000000000000000000000f34578907f", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000004", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "0000000000000000000000000000000000000000000000000000000000000000f34578907f" - } - }, - - "CallIdentitiy_3": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x000000000000000000000000000000000000000000000000000000f34578907f0000000000", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000004", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "000000000000000000000000000000000000000000000000000000f34578907f0000000000" - } - }, - - "CallIdentitiy_4": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000004", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - } - }, - - "CallIdentitiy_4_gas17": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "0x", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "23176", - "to" : "0000000000000000000000000000000000000004", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - } - }, - - "CallIdentitiy_5": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expectOut" : "#35659", - "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "nonce" : "0", - "code" : "", - "storage": {} - } - }, - "transaction" : { - "nonce" : "0", - "gasPrice" : "1", - "gasLimit" : "200000", - "to" : "0000000000000000000000000000000000000004", - "value" : "", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "data" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - } - }, - - "callTxToPrecompiled_1": { - "env": { - "currentCoinbase": "aa69d40e4ab383b25fa6c17560dd77b387480dd8", - "currentDifficulty": "0x0100", - "currentGasLimit": "0x0f4240", - "currentNumber": "0x00", - "currentTimestamp": "0x01", - "previousHash": "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "expectOut": "0x0000000000000000000000000000000000000000000000000000000000000000", - "pre": { - "cd2a3d9f938e13cd947ec05abc7fe734df8dd826": { - "balance": "150000240000000000000000", - "code": "0x", - "nonce": "0x31", - "storage": {} - }, - "aa69d40e4ab383b25fa6c17560dd77b387480dd8": { - "balance": "0x", - "code": "0x", - "nonce": "0x00", - "storage": {} - }, - "0000000000000000000000000000000000000001": { - "balance": "0x1", - "code": "0x", - "nonce": "0x00", - "storage": {} - } - }, - "transaction": { - "data": "", - "gasLimit": "0x09965e", - "gasPrice": "0x09184e72a000", - "nonce": "0x31", - "secretKey": "c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4", - "to": "0000000000000000000000000000000000000001", - "value": "0x0a968163f0a57b400000" - } - } -} diff --git a/test/libethereum/state.cpp b/test/libethereum/state.cpp index a134d024f..45c2fa13e 100644 --- a/test/libethereum/state.cpp +++ b/test/libethereum/state.cpp @@ -129,11 +129,6 @@ BOOST_AUTO_TEST_CASE(stPreCompiledContracts) dev::test::executeTests("stPreCompiledContracts", "/StateTests",dev::test::getFolder(__FILE__) + "/StateTestsFiller", dev::test::doStateTests); } -BOOST_AUTO_TEST_CASE(stPreCompiledContractsTransaction) -{ - dev::test::executeTests("stPreCompiledContractsTransaction", "/StateTests",dev::test::getFolder(__FILE__) + "/StateTestsFiller", dev::test::doStateTests); -} - BOOST_AUTO_TEST_CASE(stLogTests) { dev::test::executeTests("stLogTests", "/StateTests",dev::test::getFolder(__FILE__) + "/StateTestsFiller", dev::test::doStateTests); From 9fa64062400aac4a1544d62f9dbacd0732452bc1 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 6 Jul 2015 15:23:11 +0200 Subject: [PATCH 174/290] Some initial tests for libdevcore/FixedHash --- libdevcore/FixedHash.h | 2 +- test/libdevcore/FixedHash.cpp | 106 ++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 test/libdevcore/FixedHash.cpp diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index c7c551c2b..e9600ed0c 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -102,7 +102,7 @@ public: FixedHash operator&(FixedHash const& _c) const { return FixedHash(*this) &= _c; } FixedHash operator~() const { FixedHash ret; for (unsigned i = 0; i < N; ++i) ret[i] = ~m_data[i]; return ret; } - /// @returns true if all bytes in @a _c are set in this object. + /// @returns true if all one-bits in @a _c are set in this object. bool contains(FixedHash const& _c) const { return (*this & _c) == _c; } /// @returns a particular byte from the hash. diff --git a/test/libdevcore/FixedHash.cpp b/test/libdevcore/FixedHash.cpp new file mode 100644 index 000000000..9a6ebe0e0 --- /dev/null +++ b/test/libdevcore/FixedHash.cpp @@ -0,0 +1,106 @@ +/* + 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 FixedHash.cpp + * @author Lefterus + * @date 2015 + */ + +#include +#include "../TestHelper.h" + +using namespace std; +using namespace dev; + +namespace dev +{ +namespace test +{ + +BOOST_AUTO_TEST_SUITE(FixedHashTests) + +BOOST_AUTO_TEST_CASE(FixedHashComparisons) +{ + FixedHash<4> h1(sha3("abcd")); + FixedHash<4> h2(sha3("abcd")); + FixedHash<4> h3(sha3("aadd")); + FixedHash<4> h4(0xBAADF00D); + FixedHash<4> h5(0xAAAAAAAA); + FixedHash<4> h6(0xBAADF00D); + + BOOST_CHECK(h1 == h2); + BOOST_CHECK(h2 != h3); + + BOOST_CHECK(h4 > h5); + BOOST_CHECK(h5 < h4); + BOOST_CHECK(h6 <= h4); + BOOST_CHECK(h6 >= h4); +} + +BOOST_AUTO_TEST_CASE(FixedHashXOR) +{ + FixedHash<2> h1("0xAAAA"); + FixedHash<2> h2("0xBBBB"); + + BOOST_CHECK((h1 ^ h2) == FixedHash<2>("0x1111")); + h1 ^= h2; + BOOST_CHECK(h1 == FixedHash<2>("0x1111")); +} + +BOOST_AUTO_TEST_CASE(FixedHashOR) +{ + FixedHash<4> h1("0xD3ADB33F"); + FixedHash<4> h2("0xBAADF00D"); + FixedHash<4> res("0xFBADF33F"); + + BOOST_CHECK((h1 | h2) == res); + h1 |= h2; + BOOST_CHECK(h1 == res); +} + +BOOST_AUTO_TEST_CASE(FixedHashAND) +{ + FixedHash<4> h1("0xD3ADB33F"); + FixedHash<4> h2("0xBAADF00D"); + FixedHash<4> h3("0x92aDB00D"); + + BOOST_CHECK((h1 & h2) == h3); + h1 &= h2; + BOOST_CHECK(h1 = h3); +} + +BOOST_AUTO_TEST_CASE(FixedHashInvert) +{ + FixedHash<4> h1("0xD3ADB33F"); + FixedHash<4> h2("0x2C524CC0"); + + BOOST_CHECK(~h1 == h2); +} + +BOOST_AUTO_TEST_CASE(FixedHashContains) +{ + FixedHash<4> h1("0xD3ADB331"); + FixedHash<4> h2("0x0000B331"); + FixedHash<4> h3("0x0000000C"); + + BOOST_CHECK(h1.contains(h2)); + BOOST_CHECK(!h1.contains(h3)); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} From be4cd3a3c37a1025fd45d19b2fe9e9ef385fe4d5 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 6 Jul 2015 17:26:11 +0200 Subject: [PATCH 175/290] Some cosmetic work on TrieDB. --- libdevcore/TrieDB.h | 150 +++++++++++++++++++++++--------------------- 1 file changed, 80 insertions(+), 70 deletions(-) diff --git a/libdevcore/TrieDB.h b/libdevcore/TrieDB.h index f35cf893c..fb50fadb6 100644 --- a/libdevcore/TrieDB.h +++ b/libdevcore/TrieDB.h @@ -66,7 +66,7 @@ class GenericTrieDB public: using DB = _DB; - GenericTrieDB(DB* _db = nullptr): m_db(_db) {} + explicit GenericTrieDB(DB* _db = nullptr): m_db(_db) {} GenericTrieDB(DB* _db, h256 const& _root, Verification _v = Verification::Normal) { open(_db, _root, _v); } ~GenericTrieDB() {} @@ -96,11 +96,72 @@ public: /// True if the trie is initialised but empty (i.e. that the DB contains the root node which is empty). bool isEmpty() const { return m_root == c_shaNull && node(m_root).size(); } - h256 const& root() const { if (!node(m_root).size()) BOOST_THROW_EXCEPTION(BadRoot()); /*std::cout << "Returning root as " << ret << " (really " << m_root << ")" << std::endl;*/ return m_root; } // patch the root in the case of the empty trie. TODO: handle this properly. + h256 const& root() const { if (node(m_root).empty()) BOOST_THROW_EXCEPTION(BadRoot()); /*std::cout << "Returning root as " << ret << " (really " << m_root << ")" << std::endl;*/ return m_root; } // patch the root in the case of the empty trie. TODO: handle this properly. + + std::string at(bytes const& _key) const { return at(&_key); } + std::string at(bytesConstRef _key) const; + void insert(bytes const& _key, bytes const& _value) { insert(&_key, &_value); } + void insert(bytesConstRef _key, bytes const& _value) { insert(_key, &_value); } + void insert(bytes const& _key, bytesConstRef _value) { insert(&_key, _value); } + void insert(bytesConstRef _key, bytesConstRef _value); + void remove(bytes const& _key) { remove(&_key); } + void remove(bytesConstRef _key); + bool contains(bytes const& _key) { return contains(&_key); } + bool contains(bytesConstRef _key) { return !at(_key).empty(); } + + class iterator + { + public: + using value_type = std::pair; + + iterator() {} + explicit iterator(GenericTrieDB const* _db); + iterator(GenericTrieDB const* _db, bytesConstRef _key); + + iterator& operator++() { next(); return *this; } + + value_type operator*() const { return at(); } + value_type operator->() const { return at(); } + + bool operator==(iterator const& _c) const { return _c.m_trail == m_trail; } + bool operator!=(iterator const& _c) const { return _c.m_trail != m_trail; } + + value_type at() const; + + private: + void next(); + void next(NibbleSlice _key); + + struct Node + { + std::string rlp; + std::string key; // as hexPrefixEncoding. + byte child; // 255 -> entering, 16 -> actually at the node, 17 -> exiting, 0-15 -> actual children. + + // 255 -> 16 -> 0 -> 1 -> ... -> 15 -> 17 + + void setChild(unsigned _i) { child = _i; } + void setFirstChild() { child = 16; } + void incrementChild() { child = child == 16 ? 0 : child == 15 ? 17 : (child + 1); } + + bool operator==(Node const& _c) const { return rlp == _c.rlp && key == _c.key && child == _c.child; } + bool operator!=(Node const& _c) const { return !operator==(_c); } + }; + + protected: + std::vector m_trail; + GenericTrieDB const* m_that; + }; + + iterator begin() const { return iterator(this); } + iterator end() const { return iterator(); } + + iterator lower_bound(bytesConstRef _key) const { return iterator(this, _key); } void debugPrint() {} - void descendKey(h256 _k, h256Hash& _keyMask, bool _wasExt, std::ostream* _out, int _indent = 0) const + /// Used for debugging, scans the whole trie. + void descendKey(h256 const& _k, h256Hash& _keyMask, bool _wasExt, std::ostream* _out, int _indent = 0) const { _keyMask.erase(_k); if (_k == m_root && _k == c_shaNull) // root allowed to be empty @@ -108,6 +169,7 @@ public: descendList(RLP(node(_k)), _keyMask, _wasExt, _out, _indent); // if not, it must be a list } + /// Used for debugging, scans the whole trie. void descendEntry(RLP const& _r, h256Hash& _keyMask, bool _wasExt, std::ostream* _out, int _indent) const { if (_r.isData() && _r.size() == 32) @@ -118,6 +180,7 @@ public: BOOST_THROW_EXCEPTION(InvalidTrie()); } + /// Used for debugging, scans the whole trie. void descendList(RLP const& _r, h256Hash& _keyMask, bool _wasExt, std::ostream* _out, int _indent) const { if (_r.isList() && _r.itemCount() == 2 && (!_wasExt || _out)) @@ -139,6 +202,7 @@ public: BOOST_THROW_EXCEPTION(InvalidTrie()); } + /// Used for debugging, scans the whole trie. h256Hash leftOvers(std::ostream* _out = nullptr) const { h256Hash k = m_db->keys(); @@ -146,11 +210,14 @@ public: return k; } + /// Used for debugging, scans the whole trie. void debugStructure(std::ostream& _out) const { leftOvers(&_out); } + /// Used for debugging, scans the whole trie. + /// @param _requireNoLeftOvers if true, requires that all keys are reachable. bool check(bool _requireNoLeftOvers) const { try @@ -164,66 +231,6 @@ public: } } - std::string at(bytes const& _key) const { return at(&_key); } - std::string at(bytesConstRef _key) const; - void insert(bytes const& _key, bytes const& _value) { insert(&_key, &_value); } - void insert(bytesConstRef _key, bytes const& _value) { insert(_key, &_value); } - void insert(bytes const& _key, bytesConstRef _value) { insert(&_key, _value); } - void insert(bytesConstRef _key, bytesConstRef _value); - void remove(bytes const& _key) { remove(&_key); } - void remove(bytesConstRef _key); - bool contains(bytes const& _key) { return contains(&_key); } - bool contains(bytesConstRef _key) { return !at(_key).empty(); } - - class iterator - { - public: - using value_type = std::pair; - - iterator() {} - iterator(GenericTrieDB const* _db); - iterator(GenericTrieDB const* _db, bytesConstRef _key); - - iterator& operator++() { next(); return *this; } - - value_type operator*() const { return at(); } - value_type operator->() const { return at(); } - - bool operator==(iterator const& _c) const { return _c.m_trail == m_trail; } - bool operator!=(iterator const& _c) const { return _c.m_trail != m_trail; } - - value_type at() const; - - private: - void next(); - void next(NibbleSlice _key); - - struct Node - { - std::string rlp; - std::string key; // as hexPrefixEncoding. - byte child; // 255 -> entering, 16 -> actually at the node, 17 -> exiting, 0-15 -> actual children. - - // 255 -> 16 -> 0 -> 1 -> ... -> 15 -> 17 - - void setChild(unsigned _i) { child = _i; } - void setFirstChild() { child = 16; } - void incrementChild() { child = child == 16 ? 0 : child == 15 ? 17 : (child + 1); } - - bool operator==(Node const& _c) const { return rlp == _c.rlp && key == _c.key && child == _c.child; } - bool operator!=(Node const& _c) const { return !operator==(_c); } - }; - - protected: - std::vector m_trail; - GenericTrieDB const* m_that; - }; - - iterator begin() const { return this; } - iterator end() const { return iterator(); } - - iterator lower_bound(bytesConstRef _key) const { return iterator(this, _key); } - protected: DB* db() const { return m_db; } @@ -279,12 +286,12 @@ private: bool isTwoItemNode(RLP const& _n) const; std::string deref(RLP const& _n) const; - std::string node(h256 _h) const { return m_db->lookup(_h); } + std::string node(h256 const& _h) const { return m_db->lookup(_h); } // These are low-level node insertion functions that just go straight through into the DB. h256 forceInsertNode(bytesConstRef _v) { auto h = sha3(_v); forceInsertNode(h, _v); return h; } - void forceInsertNode(h256 _h, bytesConstRef _v) { m_db->insert(_h, _v); } - void forceKillNode(h256 _h) { m_db->kill(_h); } + void forceInsertNode(h256 const& _h, bytesConstRef _v) { m_db->insert(_h, _v); } + void forceKillNode(h256 const& _h) { m_db->kill(_h); } // This are semantically-aware node insertion functions that only kills when the node's // data is < 32 bytes. It can safely be used when pruning the trie but won't work correctly @@ -305,6 +312,9 @@ std::ostream& operator<<(std::ostream& _out, GenericTrieDB const& _db) return _out; } +/** + * Different view on a GenericTrieDB that can use different key types. + */ template class SpecificTrieDB: public Generic { @@ -753,14 +763,14 @@ template void GenericTrieDB::insert(bytesConstRef _key, bytesCons tdebug << "Insert" << toHex(_key.cropped(0, 4)) << "=>" << toHex(_value); #endif - std::string rv = node(m_root); - assert(rv.size()); - bytes b = mergeAt(RLP(rv), m_root, NibbleSlice(_key), _value); + std::string rootValue = node(m_root); + assert(rootValue.size()); + bytes b = mergeAt(RLP(rootValue), m_root, NibbleSlice(_key), _value); // mergeAt won't attempt to delete the node if it's less than 32 bytes // However, we know it's the root node and thus always hashed. // So, if it's less than 32 (and thus should have been deleted but wasn't) then we delete it here. - if (rv.size() < 32) + if (rootValue.size() < 32) forceKillNode(m_root); m_root = forceInsertNode(&b); } From bcc31d5d59347d3ef690bd6d374f3e7681e0a594 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 6 Jul 2015 18:04:26 +0200 Subject: [PATCH 176/290] Updated wallet code. --- test/libsolidity/SolidityWallet.cpp | 248 ++++++++++++++++++---------- 1 file changed, 160 insertions(+), 88 deletions(-) diff --git a/test/libsolidity/SolidityWallet.cpp b/test/libsolidity/SolidityWallet.cpp index ba8f198f8..1c296b9f7 100644 --- a/test/libsolidity/SolidityWallet.cpp +++ b/test/libsolidity/SolidityWallet.cpp @@ -47,12 +47,18 @@ static char const* walletCode = R"DELIMITER( // some number (specified in constructor) of the set of owners (specified in the constructor, modifiable) before the // interior is executed. contract multiowned { + + // TYPES + // struct for the status of a pending operation. struct PendingState { uint yetNeeded; uint ownersDone; uint index; } + + // EVENTS + // this contract only has five types of events: it can accept a confirmation, in which case // we record owner and operation (hash) alongside it. event Confirmation(address owner, bytes32 operation); @@ -63,14 +69,9 @@ contract multiowned { event OwnerRemoved(address oldOwner); // the last one is emitted if the required signatures change event RequirementChanged(uint newRequirement); - // constructor is given number of sigs required to do protected "onlymanyowners" transactions - // as well as the selection of addresses capable of confirming them. - function multiowned() { - m_required = 1; - m_numOwners = 1; - m_owners[m_numOwners] = uint(msg.sender); - m_ownerIndex[uint(msg.sender)] = m_numOwners; - } + + // MODIFIERS + // simple single-sig function modifier. modifier onlyowner { if (isOwner(msg.sender)) @@ -80,9 +81,21 @@ contract multiowned { // that later attempts can be realised as the same underlying operation and // thus count as confirmations. modifier onlymanyowners(bytes32 _operation) { - if (confirmed(_operation)) + if (confirmAndCheck(_operation)) _ } + + // METHODS + + // constructor is given number of sigs required to do protected "onlymanyowners" transactions + // as well as the selection of addresses capable of confirming them. + function multiowned() { + m_required = 1; + m_numOwners = 1; + m_owners[m_numOwners] = uint(msg.sender); + m_ownerIndex[uint(msg.sender)] = m_numOwners; + } + // Revokes a prior confirmation of the given operation function revoke(bytes32 _operation) external { uint ownerIndex = m_ownerIndex[uint(msg.sender)]; @@ -96,7 +109,75 @@ contract multiowned { Revoke(msg.sender, _operation); } } - function confirmed(bytes32 _operation) internal returns (bool) { + + // Replaces an owner `_from` with another `_to`. + function changeOwner(address _from, address _to) onlymanyowners(sha3(msg.data, block.number)) external { + if (isOwner(_to)) return; + uint ownerIndex = m_ownerIndex[uint(_from)]; + if (ownerIndex == 0) return; + + clearPending(); + m_owners[ownerIndex] = uint(_to); + m_ownerIndex[uint(_from)] = 0; + m_ownerIndex[uint(_to)] = ownerIndex; + OwnerChanged(_from, _to); + } + function addOwner(address _owner) onlymanyowners(sha3(msg.data, block.number)) external { + if (isOwner(_owner)) return; + + clearPending(); + if (m_numOwners >= c_maxOwners) + reorganizeOwners(); + if (m_numOwners >= c_maxOwners) + return; + m_numOwners++; + m_owners[m_numOwners] = uint(_owner); + m_ownerIndex[uint(_owner)] = m_numOwners; + OwnerAdded(_owner); + } + + function removeOwner(address _owner) onlymanyowners(sha3(msg.data, block.number)) external { + uint ownerIndex = m_ownerIndex[uint(_owner)]; + if (ownerIndex == 0) return; + if (m_required > m_numOwners - 1) return; + + m_owners[ownerIndex] = 0; + m_ownerIndex[uint(_owner)] = 0; + clearPending(); + reorganizeOwners(); //make sure m_numOwner is equal to the number of owners and always points to the optimal free slot + OwnerRemoved(_owner); + } + + function changeRequirement(uint _newRequired) onlymanyowners(sha3(msg.data, block.number)) external { + if (_newRequired > m_numOwners) return; + m_required = _newRequired; + clearPending(); + RequirementChanged(_newRequired); + } + + function isOwner(address _addr) returns (bool) { + return m_ownerIndex[uint(_addr)] > 0; + } + + function hasConfirmed(bytes32 _operation, address _owner) constant returns (bool) { + var pending = m_pending[_operation]; + uint ownerIndex = m_ownerIndex[uint(_owner)]; + + // make sure they're an owner + if (ownerIndex == 0) return false; + + // determine the bit to set for this owner. + uint ownerIndexBit = 2**ownerIndex; + if (pending.ownersDone & ownerIndexBit == 0) { + return false; + } else { + return true; + } + } + + // INTERNAL METHODS + + function confirmAndCheck(bytes32 _operation) internal returns (bool) { // determine what index the present sender is: uint ownerIndex = m_ownerIndex[uint(msg.sender)]; // make sure they're an owner @@ -132,42 +213,7 @@ contract multiowned { } } } - // Replaces an owner `_from` with another `_to`. - function changeOwner(address _from, address _to) onlymanyowners(sha3(msg.data)) external { - if (isOwner(_to)) return; - uint ownerIndex = m_ownerIndex[uint(_from)]; - if (ownerIndex == 0) return; - clearPending(); - m_owners[ownerIndex] = uint(_to); - m_ownerIndex[uint(_from)] = 0; - m_ownerIndex[uint(_to)] = ownerIndex; - OwnerChanged(_from, _to); - } - function addOwner(address _owner) onlymanyowners(sha3(msg.data)) external { - if (isOwner(_owner)) return; - - clearPending(); - if (m_numOwners >= c_maxOwners) - reorganizeOwners(); - if (m_numOwners >= c_maxOwners) - return; - m_numOwners++; - m_owners[m_numOwners] = uint(_owner); - m_ownerIndex[uint(_owner)] = m_numOwners; - OwnerAdded(_owner); - } - function removeOwner(address _owner) onlymanyowners(sha3(msg.data)) external { - uint ownerIndex = m_ownerIndex[uint(_owner)]; - if (ownerIndex == 0) return; - if (m_required > m_numOwners - 1) return; - - m_owners[ownerIndex] = 0; - m_ownerIndex[uint(_owner)] = 0; - clearPending(); - reorganizeOwners(); //make sure m_numOwner is equal to the number of owners and always points to the optimal free slot - OwnerRemoved(_owner); - } function reorganizeOwners() private returns (bool) { uint free = 1; while (free < m_numOwners) @@ -182,6 +228,7 @@ contract multiowned { } } } + function clearPending() internal { uint length = m_pendingIndex.length; for (uint i = 0; i < length; ++i) @@ -189,46 +236,54 @@ contract multiowned { delete m_pending[m_pendingIndex[i]]; delete m_pendingIndex; } - function changeRequirement(uint _newRequired) onlymanyowners(sha3(msg.data)) external { - if (_newRequired > m_numOwners) return; - m_required = _newRequired; - clearPending(); - RequirementChanged(_newRequired); - } - function isOwner(address _addr) returns (bool) { - return m_ownerIndex[uint(_addr)] > 0; - } + + // FIELDS // the number of owners that must confirm the same operation before it is run. uint public m_required; // pointer used to find a free slot in m_owners uint public m_numOwners; + // list of owners - uint[256] public m_owners; + uint[256] m_owners; uint constant c_maxOwners = 250; // index on the list of owners to allow reverse lookup - mapping(uint => uint) public m_ownerIndex; + mapping(uint => uint) m_ownerIndex; // the ongoing operations. - mapping(bytes32 => PendingState) public m_pending; - bytes32[] public m_pendingIndex; + mapping(bytes32 => PendingState) m_pending; + bytes32[] m_pendingIndex; } // inheritable "property" contract that enables methods to be protected by placing a linear limit (specifiable) // on a particular resource per calendar day. is multiowned to allow the limit to be altered. resource that method // uses is specified in the modifier. contract daylimit is multiowned { + + // MODIFIERS + + // simple modifier for daily limit. + modifier limitedDaily(uint _value) { + if (underLimit(_value)) + _ + } + + // METHODS + // constructor - just records the present day's index. function daylimit() { m_lastDay = today(); } // (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today. - function setDailyLimit(uint _newLimit) onlymanyowners(sha3(msg.data)) external { + function setDailyLimit(uint _newLimit) onlymanyowners(sha3(msg.data, block.number)) external { m_dailyLimit = _newLimit; } // (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today. - function resetSpentToday() onlymanyowners(sha3(msg.data)) external { + function resetSpentToday() onlymanyowners(sha3(msg.data, block.number)) external { m_spentToday = 0; } + + // INTERNAL METHODS + // checks to see if there is at least `_value` left from the daily limit today. if there is, subtracts it and // returns true. otherwise just returns false. function underLimit(uint _value) internal onlyowner returns (bool) { @@ -244,60 +299,76 @@ contract daylimit is multiowned { } return false; } - // simple modifier for daily limit. - modifier limitedDaily(uint _value) { - if (underLimit(_value)) - _ - } // determines today's index. function today() private constant returns (uint) { return now / 1 days; } - uint public m_spentToday; + + // FIELDS + uint public m_dailyLimit; - uint public m_lastDay; + uint m_spentToday; + uint m_lastDay; } + // interface contract for multisig proxy contracts; see below for docs. contract multisig { + + // EVENTS + + // logged events: + // Funds has arrived into the wallet (record how much). event Deposit(address from, uint value); + // Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going). event SingleTransact(address owner, uint value, address to, bytes data); + // Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going). event MultiTransact(address owner, bytes32 operation, uint value, address to, bytes data); + // Confirmation still needed for a transaction. event ConfirmationNeeded(bytes32 operation, address initiator, uint value, address to, bytes data); + + // FUNCTIONS + + // TODO: document function changeOwner(address _from, address _to) external; function execute(address _to, uint _value, bytes _data) external returns (bytes32); function confirm(bytes32 _h) returns (bool); } + // usage: // bytes32 h = Wallet(w).from(oneOwner).transact(to, value, data); // Wallet(w).from(anotherOwner).confirm(h); contract Wallet is multisig, multiowned, daylimit { + + // TYPES + // Transaction structure to remember details of transaction lest it need be saved for a later call. struct Transaction { address to; uint value; bytes data; } - /* - // logged events: - // Funds has arrived into the wallet (record how much). - event Deposit(address from, uint value); - // Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going). - event SingleTransact(address owner, uint value, address to, bytes data); - // Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going). - event MultiTransact(address owner, bytes32 operation, uint value, address to, bytes data);*/ + + // EVENTS + + event Created(bytes32 indexed identifier); + + // METHODS + // constructor - just pass on the owner arra to the multiowned. - event Created(); - function Wallet() { - Created(); + function Wallet(bytes32 identifier) { + Created(identifier); } + // kills the contract sending everything to `_to`. - function kill(address _to) onlymanyowners(sha3(msg.data)) external { + function kill(address _to) onlymanyowners(sha3(msg.data, block.number)) external { suicide(_to); } + // gets called when no other function matches function() { // just being sent some cash? if (msg.value > 0) Deposit(msg.sender, msg.value); } + // Outside-visible transact entry point. Executes transacion immediately if below daily spend limit. // If not, goes into multisig process. We provide a hash on return to allow the sender to provide // shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value @@ -311,7 +382,7 @@ contract Wallet is multisig, multiowned, daylimit { return 0; } // determine our operation hash. - _r = sha3(msg.data); + _r = sha3(msg.data, block.number); if (!confirm(_r) && m_txs[_r].to == 0) { m_txs[_r].to = _to; m_txs[_r].value = _value; @@ -319,6 +390,7 @@ contract Wallet is multisig, multiowned, daylimit { ConfirmationNeeded(_r, msg.sender, _value, _to, _data); } } + // confirm a transaction through just the hash. we use the previous transactions map, m_txs, in order // to determine the body of the transaction from the hash provided. function confirm(bytes32 _h) onlymanyowners(_h) returns (bool) { @@ -329,20 +401,20 @@ contract Wallet is multisig, multiowned, daylimit { return true; } } + + // INTERNAL METHODS + function clearPending() internal { uint length = m_pendingIndex.length; for (uint i = 0; i < length; ++i) delete m_txs[m_pendingIndex[i]]; super.clearPending(); } - // // internally confirm transaction with all of the info. returns true iff confirmed good and executed. - // function confirmVerbose(bytes32 _h, address _to, uint _value, bytes _data) private onlymanyowners(_h) returns (bool) { - // _to.call.value(_value)(_data); - // MultiTransact("out", msg.sender, _h, _value, _to); - // return true; - // } + + // FIELDS + // pending transactions we have at present. - mapping (bytes32 => Transaction) public m_txs; + mapping (bytes32 => Transaction) m_txs; } )DELIMITER"; @@ -443,7 +515,7 @@ BOOST_AUTO_TEST_CASE(multisig_value_transfer) // 4 owners, set required to 3 BOOST_REQUIRE(callContractFunction("changeRequirement(uint256)", u256(3)) == encodeArgs()); // check that balance is and stays zero at destination address - h256 opHash("f916231db11c12e0142dc51f23632bc655de87c63f83fc928c443e90f7aa364a"); + h256 opHash("8f27f478ebcfaf28b0c354f4809ace8087000d668b89c8bc3b1b608bfdbe6654"); BOOST_CHECK_EQUAL(m_state.balance(Address(0x05)), 0); m_sender = Address(0x12); BOOST_REQUIRE(callContractFunction("execute(address,uint256,bytes)", h256(0x05), 100, 0x60, 0x00) == encodeArgs(opHash)); From 09d091b8d08268500d2d42bc840ec088d0d47699 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 6 Jul 2015 20:50:00 +0200 Subject: [PATCH 177/290] Default values of args are now class constants Default values of some mining related arguments are no longer C constant macros but are instead C++ Ethash class constants --- ethminer/MinerAux.h | 12 ++++++------ libethash-cl/ethash_cl_miner.cpp | 8 +++++--- libethcore/Ethash.cpp | 3 +++ libethcore/Ethash.h | 13 ++++++------- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index eba68a4c3..5e2fdc8f1 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -345,9 +345,9 @@ public: << " --list-devices List the detected OpenCL devices and exit." << endl << " --current-block Let the miner know the current block number at configuration time. Will help determine DAG size and required GPU memory." << endl << " --cl-extragpu-mem Set the memory (in MB) you believe your GPU requires for stuff other than mining. Windows rendering e.t.c.." << endl - << " --cl-local-work Set the OpenCL local work size. Default is " << toString(CL_DEFAULT_LOCAL_WORK_SIZE) << endl - << " --cl-global-work Set the OpenCL global work size as a multiple of the local work size. Default is " << toString(CL_DEFAULT_GLOBAL_WORK_SIZE_MULTIPLIER) << " * " << toString(CL_DEFAULT_LOCAL_WORK_SIZE) << endl - << " --cl-ms-per-batch Set the OpenCL target milliseconds per batch (global workgroup size). Default is " << toString(CL_DEFAULT_MS_PER_BATCH) << ". If 0 is given then no autoadjustment of global work size will happen" << endl + << " --cl-local-work Set the OpenCL local work size. Default is " << toString(dev::eth::Ethash::defaultLocalWorkSize) << endl + << " --cl-global-work Set the OpenCL global work size as a multiple of the local work size. Default is " << toString(dev::eth::Ethash::defaultGlobalWorkSizeMultiplier) << " * " << toString(dev::eth::Ethash::defaultLocalWorkSize) << endl + << " --cl-ms-per-batch Set the OpenCL target milliseconds per batch (global workgroup size). Default is " << toString(dev::eth::Ethash::defaultMSPerBatch) << ". If 0 is given then no autoadjustment of global work size will happen" << endl ; } @@ -536,9 +536,9 @@ private: unsigned m_miningThreads = UINT_MAX; bool m_shouldListDevices = false; bool m_clAllowCPU = false; - unsigned m_globalWorkSizeMultiplier = CL_DEFAULT_GLOBAL_WORK_SIZE_MULTIPLIER; - unsigned m_localWorkSize = CL_DEFAULT_LOCAL_WORK_SIZE; - unsigned m_msPerBatch = CL_DEFAULT_MS_PER_BATCH; + unsigned m_globalWorkSizeMultiplier = dev::eth::Ethash::defaultGlobalWorkSizeMultiplier; + unsigned m_localWorkSize = dev::eth::Ethash::defaultLocalWorkSize; + unsigned m_msPerBatch = dev::eth::Ethash::defaultMSPerBatch; boost::optional m_currentBlock; // default value is 350MB of GPU memory for other stuff (windows system rendering, e.t.c.) unsigned m_extraGPUMemory = 350000000; diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 8c22f7f1b..bf4644b98 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "ethash_cl_miner.h" #include "ethash_cl_miner_kernel.h" @@ -49,6 +50,7 @@ #undef max using namespace std; +using namespace dev::eth; // TODO: If at any point we can use libdevcore in here then we should switch to using a LogChannel #define ETHCL_LOG(_contents) cout << "[OPENCL]:" << _contents << endl @@ -181,9 +183,9 @@ bool ethash_cl_miner::configureGPU( bool ethash_cl_miner::s_allowCPU = false; unsigned ethash_cl_miner::s_extraRequiredGPUMem; -unsigned ethash_cl_miner::s_msPerBatch = CL_DEFAULT_MS_PER_BATCH; -unsigned ethash_cl_miner::s_workgroupSize = CL_DEFAULT_LOCAL_WORK_SIZE; -unsigned ethash_cl_miner::s_initialGlobalWorkSize = CL_DEFAULT_GLOBAL_WORK_SIZE_MULTIPLIER * CL_DEFAULT_LOCAL_WORK_SIZE; +unsigned ethash_cl_miner::s_msPerBatch = Ethash::defaultMSPerBatch; +unsigned ethash_cl_miner::s_workgroupSize = Ethash::defaultLocalWorkSize; +unsigned ethash_cl_miner::s_initialGlobalWorkSize = Ethash::defaultGlobalWorkSizeMultiplier * Ethash::defaultLocalWorkSize; bool ethash_cl_miner::searchForAllDevices(function _callback) { diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index fc0e07f12..3baac3292 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -54,6 +54,9 @@ namespace dev namespace eth { +const unsigned Ethash::defaultLocalWorkSize = 64; +const unsigned Ethash::defaultGlobalWorkSizeMultiplier = 512; // * CL_DEFAULT_LOCAL_WORK_SIZE +const unsigned Ethash::defaultMSPerBatch = 100; const Ethash::WorkPackage Ethash::NullWorkPackage = Ethash::WorkPackage(); std::string Ethash::name() diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 8cc392306..804c92984 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -31,13 +31,6 @@ #include "BlockInfo.h" #include "Miner.h" -/// Default value of the local work size. Also known as workgroup size. -#define CL_DEFAULT_LOCAL_WORK_SIZE 64 -/// Default value of the global work size as a multiplier of the local work size -#define CL_DEFAULT_GLOBAL_WORK_SIZE_MULTIPLIER 512 // * CL_DEFAULT_LOCAL_WORK_SIZE -/// Default value of the milliseconds per global work size (per batch) -#define CL_DEFAULT_MS_PER_BATCH 100 - class ethash_cl_miner; namespace dev @@ -157,6 +150,12 @@ public: #else using GPUMiner = CPUMiner; #endif + /// Default value of the local work size. Also known as workgroup size. + static const unsigned defaultLocalWorkSize; + /// Default value of the global work size as a multiplier of the local work size + static const unsigned defaultGlobalWorkSizeMultiplier; + /// Default value of the milliseconds per global work size (per batch) + static const unsigned defaultMSPerBatch; }; } From 08756f6c06706e55c656d730387b7457274a6802 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 6 Jul 2015 22:57:58 +0200 Subject: [PATCH 178/290] removed nested faulty handle scopes in libjsengine --- libjsengine/JSV8Engine.cpp | 1 - libjsengine/JSV8Printer.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/libjsengine/JSV8Engine.cpp b/libjsengine/JSV8Engine.cpp index 4c7fd830a..46664b4b2 100644 --- a/libjsengine/JSV8Engine.cpp +++ b/libjsengine/JSV8Engine.cpp @@ -161,7 +161,6 @@ JSV8Engine::~JSV8Engine() JSV8Value JSV8Engine::eval(char const* _cstr) const { - v8::HandleScope handleScope; v8::TryCatch tryCatch; v8::Local source = v8::String::New(_cstr); v8::Local name(v8::String::New("(shell)")); diff --git a/libjsengine/JSV8Printer.cpp b/libjsengine/JSV8Printer.cpp index 93c235859..53a9c94a8 100644 --- a/libjsengine/JSV8Printer.cpp +++ b/libjsengine/JSV8Printer.cpp @@ -37,7 +37,6 @@ JSV8Printer::JSV8Printer(JSV8Engine const& _engine): m_engine(_engine) JSString JSV8Printer::prettyPrint(JSV8Value const& _value) const { - v8::HandleScope handleScope; v8::Local pp = v8::String::New("prettyPrint"); v8::Handle func = v8::Handle::Cast(m_engine.context()->Global()->Get(pp)); v8::Local values[1] = {v8::Local::New(_value.value())}; From e288b27195c7d405f49e2e9d11efb40cd8dc990f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 6 Jul 2015 23:06:45 +0200 Subject: [PATCH 179/290] winmm added to v8_libraries --- cmake/Findv8.cmake | 2 +- libjsconsole/CMakeLists.txt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cmake/Findv8.cmake b/cmake/Findv8.cmake index 0632afecc..e46ae7e39 100644 --- a/cmake/Findv8.cmake +++ b/cmake/Findv8.cmake @@ -56,7 +56,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") DOC "v8 nosnapshot library" ) - set(V8_LIBRARIES optimized ${V8_LIBRARIES} debug ${V8_LIBRARY_DEBUG} ${V8_NO_SNAPSHOT_LIBRARY_DEBUG}) + set(V8_LIBRARIES "ws2_32" "winmm" optimized ${V8_LIBRARIES} debug ${V8_LIBRARY_DEBUG} ${V8_NO_SNAPSHOT_LIBRARY_DEBUG}) endif() diff --git a/libjsconsole/CMakeLists.txt b/libjsconsole/CMakeLists.txt index ab94a62dd..b5362b31a 100644 --- a/libjsconsole/CMakeLists.txt +++ b/libjsconsole/CMakeLists.txt @@ -33,7 +33,6 @@ target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${CURL_LIBRARIES}) if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) - target_link_libraries(${EXECUTABLE} "ws2_32" "winmm") eth_copy_dlls(${EXECUTABLE} CURL_DLLS) endif() From ec461cafce40bfef3fd584c1ec70f5734310fbff Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 6 Jul 2015 23:50:37 +0200 Subject: [PATCH 180/290] no color output on windows jsconsole --- libjsengine/CMakeLists.txt | 2 ++ libjsengine/JSV8Engine.cpp | 5 +++++ libjsengine/PrettyPrint.js | 26 ++++++++++++++++++-------- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/libjsengine/CMakeLists.txt b/libjsengine/CMakeLists.txt index 0023494c6..df3421a37 100644 --- a/libjsengine/CMakeLists.txt +++ b/libjsengine/CMakeLists.txt @@ -22,6 +22,8 @@ eth_add_resources("${CMAKE_CURRENT_SOURCE_DIR}/JSResources.cmake" "JSRES") message(STATUS "HERE!!! ${JSRES}") add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS} ${JSRES}) +add_dependencies(${EXECUTABLE} BuildInfo.h) + # macos brew version of v8 needs to be compiled with libstdc++ # it also needs to be dynamic library # xcode needs libstdc++ to be explicitly set as it's attribute diff --git a/libjsengine/JSV8Engine.cpp b/libjsengine/JSV8Engine.cpp index 46664b4b2..c60d99e7b 100644 --- a/libjsengine/JSV8Engine.cpp +++ b/libjsengine/JSV8Engine.cpp @@ -23,6 +23,10 @@ #include #include "JSV8Engine.h" #include "libjsengine/JSEngineResources.hpp" +#include "BuildInfo.h" + +#define TO_STRING_HELPER(s) #s +#define TO_STRING(s) TO_STRING_HELPER(s) using namespace std; using namespace dev; @@ -145,6 +149,7 @@ JSString JSV8Value::toString() const JSV8Engine::JSV8Engine(): m_env(JSV8Env::getInstance()), m_scope(new JSV8Scope()) { JSEngineResources resources; + eval("env = typeof(env) === 'undefined' ? {} : env; env.os = '" TO_STRING(ETH_BUILD_PLATFORM) "'"); string common = resources.loadResourceAsString("common"); string web3 = resources.loadResourceAsString("web3"); string admin = resources.loadResourceAsString("admin"); diff --git a/libjsengine/PrettyPrint.js b/libjsengine/PrettyPrint.js index f617cf29c..080c1a485 100644 --- a/libjsengine/PrettyPrint.js +++ b/libjsengine/PrettyPrint.js @@ -1,4 +1,14 @@ var prettyPrint = (function () { + var onlyDecentPlatform = function (x) { + return env.os.indexOf('Windows') === -1 ? x : ''; + }; + + var color_red = onlyDecentPlatform('\033[31m'); + var color_green = onlyDecentPlatform('\033[32m'); + var color_pink = onlyDecentPlatform('\033[35m'); + var color_white = onlyDecentPlatform('\033[0m'); + var color_blue = onlyDecentPlatform('\033[30m'); + function pp(object, indent) { try { JSON.stringify(object) @@ -16,13 +26,13 @@ var prettyPrint = (function () { } str += " ]"; } else if (object instanceof Error) { - str += "\033[31m" + "Error:\033[0m " + object.message; + str += color_red + "Error: " + color_white + object.message; } else if (object === null) { - str += "\033[1m\033[30m" + "null"; + str += color_blue + "null"; } else if(typeof(object) === "undefined") { - str += "\033[1m\033[30m" + object; + str += color_blue + object; } else if (isBigNumber(object)) { - str += "\033[32m'" + object.toString(10) + "'"; + str += color_green + object.toString(10) + "'"; } else if(typeof(object) === "object") { str += "{\n"; indent += " "; @@ -41,15 +51,15 @@ var prettyPrint = (function () { }); str += indent.substr(2, indent.length) + "}"; } else if(typeof(object) === "string") { - str += "\033[32m'" + object + "'"; + str += color_green + object + "'"; } else if(typeof(object) === "number") { - str += "\033[31m" + object; + str += color_red + object; } else if(typeof(object) === "function") { - str += "\033[35m[Function]"; + str += color_pink + "[Function]"; } else { str += object; } - str += "\033[0m"; + str += color_white; return str; } var redundantFields = [ From 0ec0e5c4ea8dccdd7e66bee0cd4f39be64065628 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 6 Jul 2015 15:04:00 -0700 Subject: [PATCH 181/290] Fix ready for gas used/refunded. --- libethereum/Executive.cpp | 8 +++++++- libethereum/Executive.h | 4 ++++ libethereum/ExtVM.cpp | 2 ++ libethereum/State.cpp | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 02e263ab1..efb97d3b1 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -153,6 +153,11 @@ u256 Executive::gasUsed() const return m_t.gas() - m_gas; } +u256 Executive::gasUsedNoRefunds() const +{ + return m_t.gas() - m_gas + m_refunded; +} + void Executive::accrueSubState(SubState& _parentContext) { if (m_ext) @@ -391,8 +396,9 @@ void Executive::finalize() // SSTORE refunds... // must be done before the miner gets the fees. + m_refunded = min((m_t.gas() - m_gas) / 2, m_ext->sub.refunds); if (m_ext) - m_gas += min((m_t.gas() - m_gas) / 2, m_ext->sub.refunds); + m_gas += m_refunded; // cnote << "Refunding" << formatBalance(m_endGas * m_ext->gasPrice) << "to origin (=" << m_endGas << "*" << formatBalance(m_ext->gasPrice) << ")"; m_s.addBalance(m_t.sender(), m_gas * m_t.gasPrice()); diff --git a/libethereum/Executive.h b/libethereum/Executive.h index 89fa00214..78a7a8bb5 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -110,6 +110,9 @@ public: /// @returns total gas used in the transaction/operation. /// @warning Only valid after finalise(). u256 gasUsed() const; + /// @returns total gas used in the transaction/operation, excluding anything refunded. + /// @warning Only valid after finalise(). + u256 gasUsedNoRefunds() const; /// Set up the executive for evaluating a bare CREATE (contract-creation) operation. /// @returns false iff go() must be called (and thus a VM execution in required). @@ -154,6 +157,7 @@ private: bool m_isCreation = false; ///< True if the transaction creates a contract, or if create() is called. TransactionException m_excepted = TransactionException::None; ///< Details if the VM's execution resulted in an exception. u256 m_gas = 0; ///< The gas for EVM code execution. Initial amount before go() execution, final amount after go() execution. + u256 m_refunded = 0; ///< The amount of gas refunded. Transaction m_t; ///< The original transaction. Set by setup(). LogEntries m_logs; ///< The log entries created by this transaction. Set by finalize(). diff --git a/libethereum/ExtVM.cpp b/libethereum/ExtVM.cpp index 305462511..f64decf51 100644 --- a/libethereum/ExtVM.cpp +++ b/libethereum/ExtVM.cpp @@ -70,9 +70,11 @@ void go(unsigned _depth, Executive& _e, OnOpFunc const& _onOp) // Current stack is too small to handle more CALL/CREATE executions. // It needs to be done only once as newly allocated stack space it enough to handle // the rest of the calls up to the depth limit (c_depthLimit). +#if __GNUC__ if (_depth == c_offloadPoint) goOnOffloadedStack(_e, _onOp); else +#endif _e.go(_onOp); } } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index d1afd0403..22a172bcb 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -1269,6 +1269,7 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per // Add to the user-originated transactions that we've executed. m_transactions.push_back(e.t()); +// m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + e.gasUsedNoRefunds(), e.logs())); // TODO: Switch in to be compliant with YP. m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + e.gasUsed(), e.logs())); m_transactionSet.insert(e.t().sha3()); } From 944dd16825834618300857ef6c88975acb0fcf64 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 7 Jul 2015 00:12:11 +0200 Subject: [PATCH 182/290] removed unnecessary JSV8Env && V8::Dispose in libjsengine --- libjsengine/JSV8Engine.cpp | 17 +---------------- libjsengine/JSV8Engine.h | 1 - 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/libjsengine/JSV8Engine.cpp b/libjsengine/JSV8Engine.cpp index c60d99e7b..a97120a67 100644 --- a/libjsengine/JSV8Engine.cpp +++ b/libjsengine/JSV8Engine.cpp @@ -91,21 +91,6 @@ void reportException(v8::TryCatch* _tryCatch) } } -class JSV8Env -{ -public: - static JSV8Env& getInstance() - { - static JSV8Env s_env; - return s_env; - } - - ~JSV8Env() - { - v8::V8::Dispose(); - } -}; - class JSV8Scope { public: @@ -146,7 +131,7 @@ JSString JSV8Value::toString() const return toCString(str); } -JSV8Engine::JSV8Engine(): m_env(JSV8Env::getInstance()), m_scope(new JSV8Scope()) +JSV8Engine::JSV8Engine(): m_scope(new JSV8Scope()) { JSEngineResources resources; eval("env = typeof(env) === 'undefined' ? {} : env; env.os = '" TO_STRING(ETH_BUILD_PLATFORM) "'"); diff --git a/libjsengine/JSV8Engine.h b/libjsengine/JSV8Engine.h index 3a5974bb7..db75cafbc 100644 --- a/libjsengine/JSV8Engine.h +++ b/libjsengine/JSV8Engine.h @@ -56,7 +56,6 @@ public: v8::Handle const& context() const; private: - JSV8Env const& m_env; JSV8Scope* m_scope; }; From e83201f563102303dd53badded7c53f6c45d200b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 6 Jul 2015 15:39:28 -0700 Subject: [PATCH 183/290] Crash fix. --- libethereum/Executive.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index efb97d3b1..866c9c8f9 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -396,9 +396,8 @@ void Executive::finalize() // SSTORE refunds... // must be done before the miner gets the fees. - m_refunded = min((m_t.gas() - m_gas) / 2, m_ext->sub.refunds); - if (m_ext) - m_gas += m_refunded; + m_refunded = m_ext ? min((m_t.gas() - m_gas) / 2, m_ext->sub.refunds) : 0; + m_gas += m_refunded; // cnote << "Refunding" << formatBalance(m_endGas * m_ext->gasPrice) << "to origin (=" << m_endGas << "*" << formatBalance(m_ext->gasPrice) << ")"; m_s.addBalance(m_t.sender(), m_gas * m_t.gasPrice()); From 9fe95754fe3884f5f33d060613455dda18ac7fa9 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Tue, 7 Jul 2015 00:53:48 +0200 Subject: [PATCH 184/290] FixedHash::operator++() introduced --- libdevcore/FixedHash.h | 1 + test/libdevcore/FixedHash.cpp | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index a5b65458c..449848654 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -105,6 +105,7 @@ public: FixedHash& operator&=(FixedHash const& _c) { for (unsigned i = 0; i < N; ++i) m_data[i] &= _c.m_data[i]; return *this; } FixedHash operator&(FixedHash const& _c) const { return FixedHash(*this) &= _c; } FixedHash operator~() const { FixedHash ret; for (unsigned i = 0; i < N; ++i) ret[i] = ~m_data[i]; return ret; } + FixedHash& operator++() { for (unsigned i = size; i > 0 && !++m_data[--i]; ) {}; return *this; } /// @returns true if all one-bits in @a _c are set in this object. bool contains(FixedHash const& _c) const { return (*this & _c) == _c; } diff --git a/test/libdevcore/FixedHash.cpp b/test/libdevcore/FixedHash.cpp index 9a6ebe0e0..e990a3bd0 100644 --- a/test/libdevcore/FixedHash.cpp +++ b/test/libdevcore/FixedHash.cpp @@ -100,6 +100,42 @@ BOOST_AUTO_TEST_CASE(FixedHashContains) BOOST_CHECK(!h1.contains(h3)); } +void incrementSingleIteration(unsigned seed) +{ + unsigned next = seed + 1; + + FixedHash<4> h1(seed); + FixedHash<4> h2 = h1; + FixedHash<4> h3(next); + + FixedHash<32> hh1(seed); + FixedHash<32> hh2 = hh1; + FixedHash<32> hh3(next); + + BOOST_CHECK_EQUAL(++h2, h3); + BOOST_CHECK_EQUAL(++hh2, hh3); + + BOOST_CHECK(h2 > h1); + BOOST_CHECK(hh2 > hh1); + + unsigned reverse1 = ((FixedHash<4>::Arith)h2).convert_to(); + unsigned reverse2 = ((FixedHash<32>::Arith)hh2).convert_to(); + + BOOST_CHECK_EQUAL(next, reverse1); + BOOST_CHECK_EQUAL(next, reverse2); +} + +BOOST_AUTO_TEST_CASE(FixedHashIncrement) +{ + incrementSingleIteration(0); + incrementSingleIteration(1); + incrementSingleIteration(0xBAD); + incrementSingleIteration(0xBEEF); + incrementSingleIteration(0xFFFF); + incrementSingleIteration(0xFEDCBA); + incrementSingleIteration(0x7FFFFFFF); +} + BOOST_AUTO_TEST_SUITE_END() } From 6690cc489caf0fd60a2c00ceb07b663301ee8436 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 6 Jul 2015 15:55:58 -0700 Subject: [PATCH 185/290] BUNDLE=cli --- CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 036b67234..b66871338 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -234,6 +234,15 @@ elseif (BUNDLE STREQUAL "full") set(TOOLS ON) set(TESTS ON) set(FATDB ON) +elseif (BUNDLE STREQUAL "cli") + set(SERPENT ${DECENT_PLATFORM}) + set(SOLIDITY ON) + set(USENPM ON) + set(GUI OFF) +# set(NCURSES ${DECENT_PLATFORM}) + set(TOOLS ON) + set(TESTS ON) + set(FATDB ON) elseif (BUNDLE STREQUAL "core") set(SERPENT OFF) set(SOLIDITY ON) From 134b67f0084ca8f041ef3ff06178c8b9bfe832ea Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 6 Jul 2015 15:57:49 -0700 Subject: [PATCH 186/290] Cleanup cmake. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b66871338..2c2307301 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -321,6 +321,7 @@ message("-- Hardware identification support ${CPUID_FO message("-- HTTP Request support ${CURL_FOUND}") message("-- VMTRACE VM execution tracing ${VMTRACE}") message("-- PROFILING Profiling support ${PROFILING}") +message("-- NOBOOST No BOOST macros in test functions ${NOBOOST}") message("-- FATDB Full database exploring ${FATDB}") message("-- JSONRPC JSON-RPC support ${JSONRPC}") message("-- USENPM Javascript source building ${USENPM}") @@ -334,7 +335,6 @@ message("-- SERPENT Build Serpent language components ${SERPENT} message("-- GUI Build GUI components ${GUI}") message("-- NCURSES Build NCurses components ${NCURSES}") message("-- TESTS Build tests ${TESTS}") -message("-- NOBOOST No BOOST macros in test functions ${NOBOOST}") message("-- ETHASHCL Build OpenCL components (experimental!) ${ETHASHCL}") message("-- JSCONSOLE Build with javascript console ${JSCONSOLE}") message("-- EVMJIT Build LLVM-based JIT EVM (experimental!) ${EVMJIT}") From cc06339f0ebe8848d129857c93f9e885b183c033 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 6 Jul 2015 15:59:52 -0700 Subject: [PATCH 187/290] Minor cmake cleanpus. --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c2307301..0d76e2e8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -203,7 +203,9 @@ eth_format_option(ROCKSDB) eth_format_option(GUI) eth_format_option(TESTS) eth_format_option(NOBOOST) +eth_format_option(ROCKSDB) eth_format_option(TOOLS) +eth_format_option(ETHKEY) eth_format_option(ETHASHCL) eth_format_option(JSCONSOLE) eth_format_option_on_decent_platform(SERPENT) From 2eab0eee4c20493152c64f417e080e606cf9c934 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 6 Jul 2015 16:02:36 -0700 Subject: [PATCH 188/290] More cleanups to cmake. --- CMakeLists.txt | 2 -- libjsengine/CMakeLists.txt | 1 - 2 files changed, 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d76e2e8c..6cd9e338f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -373,8 +373,6 @@ else () set(GENERAL 0) endif () -message("GENERAL ${GENERAL}") - add_subdirectory(libdevcore) if (GENERAL) add_subdirectory(libevmcore) diff --git a/libjsengine/CMakeLists.txt b/libjsengine/CMakeLists.txt index 0023494c6..746e8751e 100644 --- a/libjsengine/CMakeLists.txt +++ b/libjsengine/CMakeLists.txt @@ -19,7 +19,6 @@ file(GLOB HEADERS "*.h") include(EthUtils) eth_add_resources("${CMAKE_CURRENT_SOURCE_DIR}/JSResources.cmake" "JSRES") -message(STATUS "HERE!!! ${JSRES}") add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS} ${JSRES}) # macos brew version of v8 needs to be compiled with libstdc++ From beee2c0bf91974c0dfe8359f5fab704395caeeca Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Tue, 7 Jul 2015 01:10:51 +0200 Subject: [PATCH 189/290] add blockGasLimitTests --- .../bcBlockGasLimitTestFiller.json | 277 ++++++++++++++++++ test/libethereum/blockchain.cpp | 7 +- 2 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 test/libethereum/BlockchainTestsFiller/bcBlockGasLimitTestFiller.json diff --git a/test/libethereum/BlockchainTestsFiller/bcBlockGasLimitTestFiller.json b/test/libethereum/BlockchainTestsFiller/bcBlockGasLimitTestFiller.json new file mode 100644 index 000000000..ef3b208b5 --- /dev/null +++ b/test/libethereum/BlockchainTestsFiller/bcBlockGasLimitTestFiller.json @@ -0,0 +1,277 @@ +{ + "SuicideTransaction" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "131072", + "extraData" : "0x42", + "gasLimit" : "125000", + "gasUsed" : "0", + "mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0x0102030405060708", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "expect" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "90000000000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "aaaf5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0bff", + "storage": {} + } + }, + "blocks" : [ + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "100000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "aaaf5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + } + ] + }, + + "GasUsedHigherThanBlockGasLimitButNotWithRefundsSuicideLast" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "131072", + "extraData" : "0x42", + "gasLimit" : "147000", + "gasUsed" : "0", + "mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0x0102030405060708", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "expect" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "90000000000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "aaaf5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0bff", + "storage": {} + } + }, + "blocks" : [ + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "10", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "10", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "10", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "10", + "nonce" : "4", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "10", + "nonce" : "5", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "22000", + "gasPrice" : "10", + "nonce" : "6", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "aaaf5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + } + ] + }, + + "GasUsedHigherThanBlockGasLimitButNotWithRefundsSuicideFirst" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "131072", + "extraData" : "0x42", + "gasLimit" : "147000", + "gasUsed" : "0", + "mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0x0102030405060708", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "expect" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "90000000000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "aaaf5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0bff", + "storage": {} + } + }, + "blocks" : [ + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "10", + "nonce" : "6", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "10", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "10", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "10", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "10", + "nonce" : "4", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "10", + "nonce" : "5", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "22000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "aaaf5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + } + ] + } +} diff --git a/test/libethereum/blockchain.cpp b/test/libethereum/blockchain.cpp index 6dea609e2..2e78dbe40 100644 --- a/test/libethereum/blockchain.cpp +++ b/test/libethereum/blockchain.cpp @@ -837,10 +837,15 @@ BOOST_AUTO_TEST_CASE(bcBruncleTest) dev::test::executeTests("bcBruncleTest", "/BlockchainTests",dev::test::getFolder(__FILE__) + "/BlockchainTestsFiller", dev::test::doBlockchainTests); } +BOOST_AUTO_TEST_CASE(bcBlockGasLimitTest) +{ + dev::test::executeTests("bcBlockGasLimitTest", "/BlockchainTests",dev::test::getFolder(__FILE__) + "/BlockchainTestsFiller", dev::test::doBlockchainTests); +} + BOOST_AUTO_TEST_CASE(bcWalletTest) { if (test::Options::get().wallet) - dev::test::executeTests("bcWalletTest", "/BlockchainTests",dev::test::getFolder(__FILE__) + "/BlockchainTestsFiller", dev::test::doBlockchainTests); + dev::test::executeTests("bcBlockGasLimitTest", "/BlockchainTests",dev::test::getFolder(__FILE__) + "/BlockchainTestsFiller", dev::test::doBlockchainTests); } BOOST_AUTO_TEST_CASE(userDefinedFile) From 2a0aaf9d1a8d7452528468cfbf10d80909f4e0fe Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Tue, 7 Jul 2015 01:11:53 +0200 Subject: [PATCH 190/290] fix wallet test name --- test/libethereum/blockchain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libethereum/blockchain.cpp b/test/libethereum/blockchain.cpp index 2e78dbe40..20f60618f 100644 --- a/test/libethereum/blockchain.cpp +++ b/test/libethereum/blockchain.cpp @@ -845,7 +845,7 @@ BOOST_AUTO_TEST_CASE(bcBlockGasLimitTest) BOOST_AUTO_TEST_CASE(bcWalletTest) { if (test::Options::get().wallet) - dev::test::executeTests("bcBlockGasLimitTest", "/BlockchainTests",dev::test::getFolder(__FILE__) + "/BlockchainTestsFiller", dev::test::doBlockchainTests); + dev::test::executeTests("bcWalletTest", "/BlockchainTests",dev::test::getFolder(__FILE__) + "/BlockchainTestsFiller", dev::test::doBlockchainTests); } BOOST_AUTO_TEST_CASE(userDefinedFile) From 694ab29b8deba473b61a287c3af61b0105c13892 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Tue, 7 Jul 2015 01:46:23 +0200 Subject: [PATCH 191/290] style update --- libdevcore/FixedHash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 449848654..bf0444774 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -105,7 +105,7 @@ public: FixedHash& operator&=(FixedHash const& _c) { for (unsigned i = 0; i < N; ++i) m_data[i] &= _c.m_data[i]; return *this; } FixedHash operator&(FixedHash const& _c) const { return FixedHash(*this) &= _c; } FixedHash operator~() const { FixedHash ret; for (unsigned i = 0; i < N; ++i) ret[i] = ~m_data[i]; return ret; } - FixedHash& operator++() { for (unsigned i = size; i > 0 && !++m_data[--i]; ) {}; return *this; } + FixedHash& operator++() { for (unsigned i = size; i > 0 && !++m_data[--i]; ) {} return *this; } /// @returns true if all one-bits in @a _c are set in this object. bool contains(FixedHash const& _c) const { return (*this & _c) == _c; } From 9be175ddd7b494fea1c8f340f0723cdd3380e45b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 6 Jul 2015 19:52:11 -0700 Subject: [PATCH 192/290] Cleaned up interface to send/submit Transaction. We take notice of manually-set nonce. --- alethzero/OurWebThreeStubServer.cpp | 2 +- libethcore/Common.h | 1 + libethcore/Transaction.cpp | 14 ++++++++ libethcore/Transaction.h | 4 ++- libethereum/Client.h | 2 +- libethereum/ClientBase.cpp | 43 +++++------------------ libethereum/ClientBase.h | 9 ++--- libethereum/Interface.cpp | 29 +++++++++++++-- libethereum/Interface.h | 12 +++---- libethereum/Transaction.h | 7 ++-- libweb3jsonrpc/AccountHolder.cpp | 4 +-- libweb3jsonrpc/JsonHelper.cpp | 3 ++ libweb3jsonrpc/WebThreeStubServerBase.cpp | 2 +- mix/MixClient.cpp | 28 +++------------ mix/MixClient.h | 6 ++-- 15 files changed, 81 insertions(+), 85 deletions(-) diff --git a/alethzero/OurWebThreeStubServer.cpp b/alethzero/OurWebThreeStubServer.cpp index aaeffa16b..a13f2b8f7 100644 --- a/alethzero/OurWebThreeStubServer.cpp +++ b/alethzero/OurWebThreeStubServer.cpp @@ -130,7 +130,7 @@ void OurAccountHolder::doValidations() else // sign and submit. if (Secret s = m_main->retrieveSecret(t.from)) - m_main->ethereum()->submitTransaction(s, t); + m_main->ethereum()->submitTransaction(t, s); } } diff --git a/libethcore/Common.h b/libethcore/Common.h index 190774126..fe9692ed3 100644 --- a/libethcore/Common.h +++ b/libethcore/Common.h @@ -185,6 +185,7 @@ struct TransactionSkeleton bytes data; u256 gas = UndefinedU256; u256 gasPrice = UndefinedU256; + u256 nonce = UndefinedU256; }; void badBlock(bytesConstRef _header, std::string const& _err); diff --git a/libethcore/Transaction.cpp b/libethcore/Transaction.cpp index 5e08acd4d..302579aa2 100644 --- a/libethcore/Transaction.cpp +++ b/libethcore/Transaction.cpp @@ -29,6 +29,20 @@ using namespace std; using namespace dev; using namespace dev::eth; +TransactionBase::TransactionBase(TransactionSkeleton const& _ts, Secret const& _s): + m_type(_ts.creation ? ContractCreation : MessageCall), + m_nonce(_ts.nonce), + m_value(_ts.value), + m_receiveAddress(_ts.to), + m_gasPrice(_ts.gasPrice), + m_gas(_ts.gas), + m_data(_ts.data), + m_sender(_ts.from) +{ + if (_s) + sign(_s); +} + TransactionBase::TransactionBase(bytesConstRef _rlpData, CheckTransaction _checkSig) { int field = 0; diff --git a/libethcore/Transaction.h b/libethcore/Transaction.h index e5eeb74b4..de611fa5a 100644 --- a/libethcore/Transaction.h +++ b/libethcore/Transaction.h @@ -51,6 +51,9 @@ public: /// Constructs a null transaction. TransactionBase() {} + /// Constructs a transaction from a transaction skeleton & optional secret. + TransactionBase(TransactionSkeleton const& _ts, Secret const& _s = Secret()); + /// Constructs a signed message-call transaction. TransactionBase(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data, u256 const& _nonce, Secret const& _secret): m_type(MessageCall), m_nonce(_nonce), m_value(_value), m_receiveAddress(_dest), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) { sign(_secret); } @@ -69,7 +72,6 @@ public: /// Constructs a transaction from the given RLP. explicit TransactionBase(bytes const& _rlp, CheckTransaction _checkSig): TransactionBase(&_rlp, _checkSig) {} - /// Checks equality of transactions. bool operator==(TransactionBase const& _c) const { return m_type == _c.m_type && (m_type == ContractCreation || m_receiveAddress == _c.m_receiveAddress) && m_value == _c.m_value && m_data == _c.m_data; } /// Checks inequality of transactions. diff --git a/libethereum/Client.h b/libethereum/Client.h index 7f9a65875..829ec77c1 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -313,7 +313,7 @@ private: Handler<> m_tqReady; Handler<> m_bqReady; - bool m_wouldMine = false; ///< True if we /should/ be mining. + bool m_wouldMine = false; ///< True if we /should/ be mining. bool m_turboMining = false; ///< Don't squander all of our time mining actually just sleeping. bool m_forceMining = false; ///< Mine even when there are no transactions pending? bool m_mineOnBadChain = false; ///< Mine even when the canary says it's a bad chain. diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index d6d259380..9a221f351 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -45,48 +45,21 @@ State ClientBase::asOf(BlockNumber _h) const return asOf(bc().numberHash(_h)); } -void ClientBase::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, u256 _nonce) -{ - prepareForTransaction(); - - Transaction t(_value, _gasPrice, _gas, _dest, _data, _nonce, _secret); - m_tq.import(t.rlp()); - - StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged()); - cnote << "New transaction " << t; -} - -Address ClientBase::submitTransaction(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, u256 _nonce) -{ - prepareForTransaction(); - - Transaction t(_value, _gasPrice, _gas, _data, _nonce, _secret); - m_tq.import(t.rlp()); - - StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged()); - cnote << "New transaction " << t; - - return right160(sha3(rlpList(t.sender(), t.nonce()))); -} - -void ClientBase::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) -{ - auto a = toAddress(_secret); - submitTransaction(_secret, _value, _dest, _data, _gas, _gasPrice, max(postMine().transactionsFrom(a), m_tq.maxNonce(a))); -} - -Address ClientBase::submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) +Address ClientBase::submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) { prepareForTransaction(); - u256 n = postMine().transactionsFrom(toAddress(_secret)); - Transaction t(_endowment, _gasPrice, _gas, _init, n, _secret); - m_tq.import(t.rlp()); + TransactionSkeleton ts(_t); + ts.from = toAddress(_secret); + if (_t.nonce == UndefinedU256) + ts.nonce = max(postMine().transactionsFrom(ts.from), m_tq.maxNonce(ts.from)); + Transaction t(ts, _secret); + m_tq.import(t.rlp()); StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged()); cnote << "New transaction " << t; - return right160(sha3(rlpList(t.sender(), t.nonce()))); + return _t.creation ? right160(sha3(rlpList(ts.from, ts.nonce))) : Address(); } // TODO: remove try/catch, allow exceptions diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index d2d22a08f..609bde580 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -75,14 +75,9 @@ public: ClientBase() {} virtual ~ClientBase() {} - /// Submits the given message-call transaction. - virtual void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, u256 _nonce); - virtual void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override; - - /// Submits a new contract-creation transaction. + /// Submits the given transaction. /// @returns the new contract's address (assuming it all goes through). - virtual Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice, u256 _nonce); - virtual Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override; + virtual Address submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) override; using Interface::submitTransaction; /// Makes the given call. Nothing is recorded into the state. diff --git a/libethereum/Interface.cpp b/libethereum/Interface.cpp index 545604d90..f7d2d2468 100644 --- a/libethereum/Interface.cpp +++ b/libethereum/Interface.cpp @@ -20,6 +20,31 @@ */ #include "Interface.h" +using namespace std; +using namespace dev; +using namespace eth; -#pragma GCC diagnostic ignored "-Wunused-variable" -namespace { char dummy; } +void Interface::submitTransaction(Secret const& _secret, u256 const& _value, Address const& _dest, bytes const& _data, u256 const& _gas, u256 const& _gasPrice, u256 const& _nonce) +{ + TransactionSkeleton ts; + ts.creation = false; + ts.value = _value; + ts.to = _dest; + ts.data = _data; + ts.gas = _gas; + ts.gasPrice = _gasPrice; + ts.nonce = _nonce; + submitTransaction(ts, _secret); +} + +Address Interface::submitTransaction(Secret const& _secret, u256 const& _endowment, bytes const& _init, u256 const& _gas, u256 const& _gasPrice, u256 const& _nonce) +{ + TransactionSkeleton ts; + ts.creation = true; + ts.value = _endowment; + ts.data = _init; + ts.gas = _gas; + ts.gasPrice = _gasPrice; + ts.nonce = _nonce; + return submitTransaction(ts, _secret); +} diff --git a/libethereum/Interface.h b/libethereum/Interface.h index f24f1b5c3..3e68a1e70 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -65,16 +65,16 @@ public: // [TRANSACTION API] - /// Submits the given message-call transaction. - virtual void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) = 0; + /// Submits a new transaction. + /// @returns the new contract's address (assuming it all goes through and it's contract creation). + virtual Address submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) = 0; - /// Submits a new contract-creation transaction. - /// @returns the new contract's address (assuming it all goes through). - virtual Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo) = 0; + /// Submits the given message-call transaction. + void submitTransaction(Secret const& _secret, u256 const& _value, Address const& _dest, bytes const& _data = bytes(), u256 const& _gas = 10000, u256 const& _gasPrice = 10 * szabo, u256 const& _nonce = UndefinedU256); /// Submits a new contract-creation transaction. /// @returns the new contract's address (assuming it all goes through). - Address submitTransaction(Secret const& _secret, TransactionSkeleton const& _t) { if (_t.creation) return submitTransaction(_secret, _t.value, _t.data, _t.gas, _t.gasPrice); submitTransaction(_secret, _t.value, _t.to, _t.data, _t.gas, _t.gasPrice); return Address(); } + Address submitTransaction(Secret const& _secret, u256 const& _endowment, bytes const& _init, u256 const& _gas = 10000, u256 const& _gasPrice = 10 * szabo, u256 const& _nonce = UndefinedU256); /// Blocks until all pending transactions have been processed. virtual void flushTransactions() = 0; diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h index 77ba1824d..8ed0043c9 100644 --- a/libethereum/Transaction.h +++ b/libethereum/Transaction.h @@ -85,6 +85,9 @@ public: /// Constructs a null transaction. Transaction() {} + /// Constructs from a transaction skeleton & optional secret. + Transaction(TransactionSkeleton const& _ts, Secret const& _s = Secret()): TransactionBase(_ts, _s) {} + /// Constructs a signed message-call transaction. Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data, u256 const& _nonce, Secret const& _secret): TransactionBase(_value, _gasPrice, _gas, _dest, _data, _nonce, _secret) @@ -96,12 +99,12 @@ public: {} /// Constructs an unsigned message-call transaction. - Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data, u256 const& _nonce = 0): + Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data, u256 const& _nonce = UndefinedU256): TransactionBase(_value, _gasPrice, _gas, _dest, _data, _nonce) {} /// Constructs an unsigned contract-creation transaction. - Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data, u256 const& _nonce = 0): + Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data, u256 const& _nonce = UndefinedU256): TransactionBase(_value, _gasPrice, _gas, _data, _nonce) {} diff --git a/libweb3jsonrpc/AccountHolder.cpp b/libweb3jsonrpc/AccountHolder.cpp index 3250eae6b..6f6c288e2 100644 --- a/libweb3jsonrpc/AccountHolder.cpp +++ b/libweb3jsonrpc/AccountHolder.cpp @@ -109,7 +109,7 @@ AddressHash SimpleAccountHolder::realAccounts() const void SimpleAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t) { if (isRealAccount(_t.from)) - m_client()->submitTransaction(m_keyManager.secret(_t.from, [&](){ return m_getPassword(_t.from); }), _t); + m_client()->submitTransaction(_t, m_keyManager.secret(_t.from, [&](){ return m_getPassword(_t.from); })); else if (isProxyAccount(_t.from)) queueTransaction(_t); } @@ -117,7 +117,7 @@ void SimpleAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t) void FixedAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t) { if (isRealAccount(_t.from)) - m_client()->submitTransaction(m_accounts[_t.from], _t); + m_client()->submitTransaction(_t, m_accounts[_t.from]); else if (isProxyAccount(_t.from)) queueTransaction(_t); } diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp index 0b6cd4a1d..39a856446 100644 --- a/libweb3jsonrpc/JsonHelper.cpp +++ b/libweb3jsonrpc/JsonHelper.cpp @@ -269,6 +269,9 @@ TransactionSkeleton toTransactionSkeleton(Json::Value const& _json) if (!_json["code"].empty()) ret.data = jsToBytes(_json["code"].asString()); + + if (!_json["nonce"].empty()) + ret.nonce = jsToU256(_json["nonce"].asString()); return ret; } diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index 3683c01ca..6a8ab8bd6 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -248,7 +248,7 @@ string WebThreeStubServerBase::eth_sendTransaction(Json::Value const& _json) if (!t.from) t.from = m_ethAccounts->defaultTransactAccount(); if (t.creation) - ret = toJS(right160(sha3(rlpList(t.from, client()->countAt(t.from)))));; + ret = toJS(right160(sha3(rlpList(t.from, client()->countAt(t.from))))); if (t.gasPrice == UndefinedU256) t.gasPrice = 10 * dev::eth::szabo; // TODO: should be determined by user somehow. if (t.gas == UndefinedU256) diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 0b1c7c44f..8c52e5923 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -303,22 +303,14 @@ State MixClient::asOf(h256 const& _block) const return ret; } -void MixClient::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, bool _gasAuto) +Address MixClient::submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto) { WriteGuard l(x_state); - u256 n = m_state.transactionsFrom(toAddress(_secret)); - Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); + TransactionSkeleton ts = _ts; + ts.nonce = m_state.transactionsFrom(toAddress(_secret)); + eth::Transaction t(ts, _secret); executeTransaction(t, m_state, false, _gasAuto, _secret); -} - -Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice, bool _gasAuto) -{ - WriteGuard l(x_state); - u256 n = m_state.transactionsFrom(toAddress(_secret)); - eth::Transaction t(_endowment, _gasPrice, _gas, _init, n, _secret); - executeTransaction(t, m_state, false, _gasAuto, _secret); - Address address = right160(sha3(rlpList(t.sender(), t.nonce()))); - return address; + return _ts.creation ? right160(sha3(rlpList(ts.to, ts.nonce))) : Address(); } dev::eth::ExecutionResult MixClient::call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto, FudgeFactor _ff) @@ -335,16 +327,6 @@ dev::eth::ExecutionResult MixClient::call(Address const& _from, u256 _value, Add return lastExecution().result; } -void MixClient::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) -{ - submitTransaction(_secret, _value, _dest, _data, _gas, _gasPrice, false); -} - -Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) -{ - return submitTransaction(_secret, _endowment, _init, _gas, _gasPrice, false); -} - dev::eth::ExecutionResult MixClient::call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, eth::FudgeFactor _ff) { return call(_from, _value, _dest, _data, _gas, _gasPrice, _blockNumber, false, _ff); diff --git a/mix/MixClient.h b/mix/MixClient.h index 1172bffbd..1ac32df0f 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -54,14 +54,12 @@ public: ExecutionResult lastExecution() const; ExecutionResult execution(unsigned _index) const; - void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) override; - Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) override; dev::eth::ExecutionResult call(Address const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override; dev::eth::ExecutionResult create(Address const& _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * eth::szabo, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override; using ClientBase::submitTransaction; - void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, bool _gasAuto); - Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice, bool _gasAuto); + virtual Address submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret) override { return submitTransaction(_ts, _secret, false); } + Address submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto); dev::eth::ExecutionResult call(Address const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber, bool _gasAuto, eth::FudgeFactor _ff = eth::FudgeFactor::Strict); void setAddress(Address _us) override; From e1edbcf581c8ea3991961b55e78d545af19b7b1f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 6 Jul 2015 22:04:39 -0700 Subject: [PATCH 193/290] Avoid spurious error messages. --- libethereum/State.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 22a172bcb..e1bdd19b6 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -536,7 +536,7 @@ pair State::sync(BlockChain const& _bc, TransactionQu if (req > got) { // too old - for (Transaction const& mt: m_transactions) +/* for (Transaction const& mt: m_transactions) { if (mt.from() == t.from()) { @@ -545,7 +545,7 @@ pair State::sync(BlockChain const& _bc, TransactionQu else if (mt.nonce() == t.nonce() && mt.gasPrice() <= t.gasPrice()) cnote << t.sha3() << "Dropping old transaction (gas price lower)"; } - } + }*/ _tq.drop(t.sha3()); } else if (got > req + _tq.waiting(t.sender())) From 455a1aed741a326cb81d995219170d770e735680 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 7 Jul 2015 10:17:50 +0200 Subject: [PATCH 194/290] rpc eth_sendTransaction returns always transaction hash --- alethzero/OurWebThreeStubServer.cpp | 3 ++- alethzero/OurWebThreeStubServer.h | 2 +- libdevcrypto/Common.cpp | 6 ++++++ libdevcrypto/Common.h | 3 +++ libethereum/ClientBase.cpp | 4 ++-- libethereum/ClientBase.h | 2 +- libethereum/Interface.cpp | 3 ++- libethereum/Interface.h | 2 +- libweb3jsonrpc/AccountHolder.cpp | 10 ++++++---- libweb3jsonrpc/AccountHolder.h | 6 +++--- libweb3jsonrpc/WebThreeStubServerBase.cpp | 10 +--------- mix/MixClient.cpp | 4 ++-- mix/MixClient.h | 4 ++-- 13 files changed, 32 insertions(+), 27 deletions(-) diff --git a/alethzero/OurWebThreeStubServer.cpp b/alethzero/OurWebThreeStubServer.cpp index a13f2b8f7..056b0460d 100644 --- a/alethzero/OurWebThreeStubServer.cpp +++ b/alethzero/OurWebThreeStubServer.cpp @@ -99,10 +99,11 @@ bool OurAccountHolder::showUnknownCallNotice(TransactionSkeleton const& _t, bool "REJECT UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!"); } -void OurAccountHolder::authenticate(TransactionSkeleton const& _t) +h256 OurAccountHolder::authenticate(TransactionSkeleton const& _t) { Guard l(x_queued); m_queued.push(_t); + return h256(); } void OurAccountHolder::doValidations() diff --git a/alethzero/OurWebThreeStubServer.h b/alethzero/OurWebThreeStubServer.h index cc950027e..26053ae36 100644 --- a/alethzero/OurWebThreeStubServer.h +++ b/alethzero/OurWebThreeStubServer.h @@ -43,7 +43,7 @@ protected: // easiest to return keyManager.addresses(); virtual dev::AddressHash realAccounts() const override; // use web3 to submit a signed transaction to accept - virtual void authenticate(dev::eth::TransactionSkeleton const& _t) override; + virtual dev::h256 authenticate(dev::eth::TransactionSkeleton const& _t) override; private: bool showAuthenticationPopup(std::string const& _title, std::string const& _text); diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index 219b28f3a..8bf95d02f 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #if ETH_HAVE_SECP256K1 #include #endif @@ -90,6 +91,11 @@ Address dev::toAddress(Secret const& _secret) return toAddress(p); } +Address dev::toAddress(Address const& _from, u256 const& _nonce) +{ + return right160(sha3(rlpList(_from, _nonce))); +} + void dev::encrypt(Public const& _k, bytesConstRef _plain, bytes& o_cipher) { bytes io = _plain.toBytes(); diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h index b3d2649b8..c45e060b2 100644 --- a/libdevcrypto/Common.h +++ b/libdevcrypto/Common.h @@ -85,6 +85,9 @@ Address toAddress(Public const& _public); /// @returns 0 if it's not a valid secret key. Address toAddress(Secret const& _secret); +// Convert transaction from and nonce to address. +Address toAddress(Address const& _from, u256 const& _nonce); + /// Encrypts plain text using Public key. void encrypt(Public const& _k, bytesConstRef _plain, bytes& o_cipher); diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 9a221f351..73404f83d 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -45,7 +45,7 @@ State ClientBase::asOf(BlockNumber _h) const return asOf(bc().numberHash(_h)); } -Address ClientBase::submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) +h256 ClientBase::submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) { prepareForTransaction(); @@ -59,7 +59,7 @@ Address ClientBase::submitTransaction(TransactionSkeleton const& _t, Secret cons StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged()); cnote << "New transaction " << t; - return _t.creation ? right160(sha3(rlpList(ts.from, ts.nonce))) : Address(); + return t.sha3(); } // TODO: remove try/catch, allow exceptions diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index 609bde580..e08429c96 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -77,7 +77,7 @@ public: /// Submits the given transaction. /// @returns the new contract's address (assuming it all goes through). - virtual Address submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) override; + virtual h256 submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) override; using Interface::submitTransaction; /// Makes the given call. Nothing is recorded into the state. diff --git a/libethereum/Interface.cpp b/libethereum/Interface.cpp index f7d2d2468..efa304bd5 100644 --- a/libethereum/Interface.cpp +++ b/libethereum/Interface.cpp @@ -46,5 +46,6 @@ Address Interface::submitTransaction(Secret const& _secret, u256 const& _endowme ts.gas = _gas; ts.gasPrice = _gasPrice; ts.nonce = _nonce; - return submitTransaction(ts, _secret); + submitTransaction(ts, _secret); + return toAddress(toAddress(_secret), _nonce); } diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 3e68a1e70..564589eb6 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -67,7 +67,7 @@ public: /// Submits a new transaction. /// @returns the new contract's address (assuming it all goes through and it's contract creation). - virtual Address submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) = 0; + virtual h256 submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) = 0; /// Submits the given message-call transaction. void submitTransaction(Secret const& _secret, u256 const& _value, Address const& _dest, bytes const& _data = bytes(), u256 const& _gas = 10000, u256 const& _gasPrice = 10 * szabo, u256 const& _nonce = UndefinedU256); diff --git a/libweb3jsonrpc/AccountHolder.cpp b/libweb3jsonrpc/AccountHolder.cpp index 6f6c288e2..f4b3a9f9f 100644 --- a/libweb3jsonrpc/AccountHolder.cpp +++ b/libweb3jsonrpc/AccountHolder.cpp @@ -106,20 +106,22 @@ AddressHash SimpleAccountHolder::realAccounts() const return m_keyManager.accountsHash(); } -void SimpleAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t) +h256 SimpleAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t) { if (isRealAccount(_t.from)) - m_client()->submitTransaction(_t, m_keyManager.secret(_t.from, [&](){ return m_getPassword(_t.from); })); + return m_client()->submitTransaction(_t, m_keyManager.secret(_t.from, [&](){ return m_getPassword(_t.from); })); else if (isProxyAccount(_t.from)) queueTransaction(_t); + return h256(); } -void FixedAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t) +h256 FixedAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t) { if (isRealAccount(_t.from)) - m_client()->submitTransaction(_t, m_accounts[_t.from]); + return m_client()->submitTransaction(_t, m_accounts[_t.from]); else if (isProxyAccount(_t.from)) queueTransaction(_t); + return h256(); } diff --git a/libweb3jsonrpc/AccountHolder.h b/libweb3jsonrpc/AccountHolder.h index 559f8509a..4a30826ae 100644 --- a/libweb3jsonrpc/AccountHolder.h +++ b/libweb3jsonrpc/AccountHolder.h @@ -51,7 +51,7 @@ public: virtual AddressHash realAccounts() const = 0; // use m_web3's submitTransaction // or use AccountHolder::queueTransaction(_t) to accept - virtual void authenticate(dev::eth::TransactionSkeleton const& _t) = 0; + virtual h256 authenticate(dev::eth::TransactionSkeleton const& _t) = 0; Addresses allAccounts() const; bool isRealAccount(Address const& _account) const { return realAccounts().count(_account) > 0; } @@ -85,7 +85,7 @@ public: {} AddressHash realAccounts() const override; - void authenticate(dev::eth::TransactionSkeleton const& _t) override; + h256 authenticate(dev::eth::TransactionSkeleton const& _t) override; private: std::function m_getPassword; @@ -117,7 +117,7 @@ public: // use m_web3's submitTransaction // or use AccountHolder::queueTransaction(_t) to accept - void authenticate(dev::eth::TransactionSkeleton const& _t) override; + h256 authenticate(dev::eth::TransactionSkeleton const& _t) override; private: std::unordered_map m_accounts; diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index 6a8ab8bd6..fd0b4c514 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -242,21 +242,16 @@ string WebThreeStubServerBase::eth_sendTransaction(Json::Value const& _json) { try { - string ret; TransactionSkeleton t = toTransactionSkeleton(_json); if (!t.from) t.from = m_ethAccounts->defaultTransactAccount(); - if (t.creation) - ret = toJS(right160(sha3(rlpList(t.from, client()->countAt(t.from))))); if (t.gasPrice == UndefinedU256) t.gasPrice = 10 * dev::eth::szabo; // TODO: should be determined by user somehow. if (t.gas == UndefinedU256) t.gas = min(client()->gasLimitRemaining() / 5, client()->balanceAt(t.from) / t.gasPrice); - m_ethAccounts->authenticate(t); - - return ret; + return toJS(m_ethAccounts->authenticate(t)); } catch (...) { @@ -268,13 +263,10 @@ string WebThreeStubServerBase::eth_signTransaction(Json::Value const& _json) { try { - string ret; TransactionSkeleton t = toTransactionSkeleton(_json); if (!t.from) t.from = m_ethAccounts->defaultTransactAccount(); - if (t.creation) - ret = toJS(right160(sha3(rlpList(t.from, client()->countAt(t.from)))));; if (t.gasPrice == UndefinedU256) t.gasPrice = 10 * dev::eth::szabo; // TODO: should be determined by user somehow. if (t.gas == UndefinedU256) diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 8c52e5923..7978ff1ac 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -303,14 +303,14 @@ State MixClient::asOf(h256 const& _block) const return ret; } -Address MixClient::submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto) +h256 MixClient::submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto) { WriteGuard l(x_state); TransactionSkeleton ts = _ts; ts.nonce = m_state.transactionsFrom(toAddress(_secret)); eth::Transaction t(ts, _secret); executeTransaction(t, m_state, false, _gasAuto, _secret); - return _ts.creation ? right160(sha3(rlpList(ts.to, ts.nonce))) : Address(); + return t.sha3(); } dev::eth::ExecutionResult MixClient::call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto, FudgeFactor _ff) diff --git a/mix/MixClient.h b/mix/MixClient.h index 1ac32df0f..e4ad9c133 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -58,8 +58,8 @@ public: dev::eth::ExecutionResult create(Address const& _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * eth::szabo, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override; using ClientBase::submitTransaction; - virtual Address submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret) override { return submitTransaction(_ts, _secret, false); } - Address submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto); + virtual h256 submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret) override { return submitTransaction(_ts, _secret, false); } + h256 submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto); dev::eth::ExecutionResult call(Address const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber, bool _gasAuto, eth::FudgeFactor _ff = eth::FudgeFactor::Strict); void setAddress(Address _us) override; From c89f56309db167ab7f39ba5c8e3eb3107f574dd2 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 7 Jul 2015 10:20:26 +0200 Subject: [PATCH 195/290] updated Interface and ClientBase method "sendTransaction" description --- libethereum/ClientBase.h | 2 +- libethereum/Interface.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index e08429c96..f0e830d1d 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -76,7 +76,7 @@ public: virtual ~ClientBase() {} /// Submits the given transaction. - /// @returns the new contract's address (assuming it all goes through). + /// @returns the new transaction's hash. virtual h256 submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) override; using Interface::submitTransaction; diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 564589eb6..0d40937b8 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -66,7 +66,7 @@ public: // [TRANSACTION API] /// Submits a new transaction. - /// @returns the new contract's address (assuming it all goes through and it's contract creation). + /// @returns the transaction's hash. virtual h256 submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) = 0; /// Submits the given message-call transaction. From ef3ccfcdaaf8e330556d9e41eb921fd7a59998c3 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 7 Jul 2015 10:53:58 +0200 Subject: [PATCH 196/290] Use rlpList to construct some RLPs. --- eth/main.cpp | 10 ++-------- libdevcore/TrieDB.h | 12 ++++-------- libethereum/BlockChainSync.cpp | 1 - libethereum/BlockDetails.h | 4 ++-- neth/main.cpp | 6 +----- 5 files changed, 9 insertions(+), 24 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index e4facccee..6a66df6a2 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -1026,9 +1026,7 @@ void interactiveMode(eth::Client* c, std::shared_ptr gasP { string path; iss >> path; - RLPStream config(2); - config << signingKey << beneficiary; - writeFile(path, config.out()); + writeFile(path, rlpList(signingKey, beneficiary)); } else cwarn << "Require parameter: exportConfig PATH"; @@ -1477,11 +1475,7 @@ int main(int argc, char** argv) for (auto const& s: passwordsToNote) keyManager.notePassword(s); - { - RLPStream config(2); - config << signingKey << beneficiary; - writeFile(configFile, config.out()); - } + writeFile(configFile, rlpList(signingKey, beneficiary)); if (sessionKey) signingKey = sessionKey; diff --git a/libdevcore/TrieDB.h b/libdevcore/TrieDB.h index f35cf893c..5d3784909 100644 --- a/libdevcore/TrieDB.h +++ b/libdevcore/TrieDB.h @@ -1066,11 +1066,11 @@ template bytes GenericTrieDB::place(RLP const& _orig, NibbleSlice killNode(_orig); if (_orig.isEmpty()) - return (RLPStream(2) << hexPrefixEncode(_k, true) << _s).out(); + return rlpList(hexPrefixEncode(_k, true), _s); assert(_orig.isList() && (_orig.itemCount() == 2 || _orig.itemCount() == 17)); if (_orig.itemCount() == 2) - return (RLPStream(2) << _orig[0] << _s).out(); + return rlpList(_orig[0], _s); auto s = RLPStream(17); for (unsigned i = 0; i < 16; ++i) @@ -1152,7 +1152,7 @@ template bytes GenericTrieDB::graft(RLP const& _orig) } assert(n.itemCount() == 2); - return (RLPStream(2) << hexPrefixEncode(keyOf(_orig), keyOf(n), isLeaf(n)) << n[1]).out(); + return rlpList(hexPrefixEncode(keyOf(_orig), keyOf(n), isLeaf(n)), n[1]); // auto ret = // std::cout << keyOf(_orig) << " ++ " << keyOf(n) << " == " << keyOf(RLP(ret)) << std::endl; // return ret; @@ -1201,11 +1201,7 @@ template bytes GenericTrieDB::branch(RLP const& _orig) for (unsigned i = 0; i < 16; ++i) if (i == b) if (isLeaf(_orig) || k.size() > 1) - { - RLPStream bottom(2); - bottom << hexPrefixEncode(k.mid(1), isLeaf(_orig)) << _orig[1]; - streamNode(r, bottom.out()); - } + streamNode(r, rlpList(hexPrefixEncode(k.mid(1), isLeaf(_orig)), _orig[1])); else r << _orig[1]; else diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 90dc70574..e22f10880 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -397,7 +397,6 @@ void PV60Sync::transition(std::shared_ptr _peer, SyncState _s, boo if (m_state == SyncState::Idle && _s != SyncState::Idle) _peer->m_requireTransactions = true; - RLPStream s; if (_s == SyncState::Hashes) { if (m_state == SyncState::Idle || m_state == SyncState::Hashes) diff --git a/libethereum/BlockDetails.h b/libethereum/BlockDetails.h index f1526b5fd..73026834e 100644 --- a/libethereum/BlockDetails.h +++ b/libethereum/BlockDetails.h @@ -59,7 +59,7 @@ struct BlockLogBlooms { BlockLogBlooms() {} BlockLogBlooms(RLP const& _r) { blooms = _r.toVector(); size = _r.data().size(); } - bytes rlp() const { RLPStream s; s << blooms; size = s.out().size(); return s.out(); } + bytes rlp() const { bytes r = dev::rlp(blooms); size = r.size(); return r; } LogBlooms blooms; mutable unsigned size; @@ -69,7 +69,7 @@ struct BlocksBlooms { BlocksBlooms() {} BlocksBlooms(RLP const& _r) { blooms = _r.toArray(); size = _r.data().size(); } - bytes rlp() const { RLPStream s; s << blooms; size = s.out().size(); return s.out(); } + bytes rlp() const { bytes r = dev::rlp(blooms); size = r.size(); return r; } std::array blooms; mutable unsigned size; diff --git a/neth/main.cpp b/neth/main.cpp index 65f46735f..d5cb4bb4b 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -363,11 +363,7 @@ int main(int argc, char** argv) coinbase = config[1].toHash
(); } else - { - RLPStream config(2); - config << us.secret() << coinbase; - writeFile(configFile, config.out()); - } + writeFile(configFile, rlpList(us.secret(), coinbase)); for (int i = 1; i < argc; ++i) { From d2a20ef120931e5a3ca1dd563266e30bb55daadc Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Tue, 7 Jul 2015 11:16:41 +0200 Subject: [PATCH 197/290] test updated --- test/libdevcore/FixedHash.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/libdevcore/FixedHash.cpp b/test/libdevcore/FixedHash.cpp index e990a3bd0..dc5ced2c1 100644 --- a/test/libdevcore/FixedHash.cpp +++ b/test/libdevcore/FixedHash.cpp @@ -134,6 +134,10 @@ BOOST_AUTO_TEST_CASE(FixedHashIncrement) incrementSingleIteration(0xFFFF); incrementSingleIteration(0xFEDCBA); incrementSingleIteration(0x7FFFFFFF); + + FixedHash<4> h(0xFFFFFFFF); + FixedHash<4> zero; + BOOST_CHECK_EQUAL(++h, zero); } BOOST_AUTO_TEST_SUITE_END() From 1a6620ef671e21fb3d4131c537f0a5b1d2338339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 7 Jul 2015 12:02:14 +0200 Subject: [PATCH 198/290] Adjust stack offloading params. Enable only for clang compiler. --- libethereum/ExtVM.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libethereum/ExtVM.cpp b/libethereum/ExtVM.cpp index e54fc7cad..875fad684 100644 --- a/libethereum/ExtVM.cpp +++ b/libethereum/ExtVM.cpp @@ -37,14 +37,17 @@ static size_t const c_singleExecutionStackSize = #ifdef NDEBUG 12 * 1024; #else - 64 * 1024; + 33 * 1024; #endif /// Standard OSX thread stack limit. Should be reasonable for other platforms too. static size_t const c_defaultStackSize = 512 * 1024; +/// Stack overhead prior to allocation. +static size_t const c_entryOverhead = 128 * 1024; + /// On what depth execution should be offloaded to additional separated stack space. -static unsigned const c_offloadPoint = c_defaultStackSize / c_singleExecutionStackSize; +static unsigned const c_offloadPoint = (c_defaultStackSize - c_entryOverhead) / c_singleExecutionStackSize; void goOnOffloadedStack(Executive& _e, OnOpFunc const& _onOp) { @@ -75,7 +78,7 @@ void go(unsigned _depth, Executive& _e, OnOpFunc const& _onOp) // Current stack is too small to handle more CALL/CREATE executions. // It needs to be done only once as newly allocated stack space it enough to handle // the rest of the calls up to the depth limit (c_depthLimit). -#if __GNUC__ +#if __clang__ // Enabled for clang only as the problem affects OSX if (_depth == c_offloadPoint) goOnOffloadedStack(_e, _onOp); else From 560b09777e54082860b06953f2ae50046f384518 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 7 Jul 2015 12:25:38 +0200 Subject: [PATCH 199/290] Throw on FixedHash failure of String construction I have had this bite me a few times when testing FixedHash with the string constructor. A capital "X" in the 0x prefix, wrong number of hex characters compared to the number of bytes the FixedHash has e.t.c. and there was no warning. The hash had a 0 value while I was assuming it worked fine. Having it throw in case of error will guarantee that this won't happen again. --- libdevcore/FixedHash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index a5b65458c..88b42f16c 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -81,7 +81,7 @@ public: explicit FixedHash(byte const* _bs, ConstructFromPointerType) { memcpy(m_data.data(), _bs, N); } /// Explicitly construct, copying from a string. - explicit FixedHash(std::string const& _s, ConstructFromStringType _t = FromHex, ConstructFromHashType _ht = FailIfDifferent): FixedHash(_t == FromHex ? fromHex(_s) : dev::asBytes(_s), _ht) {} + explicit FixedHash(std::string const& _s, ConstructFromStringType _t = FromHex, ConstructFromHashType _ht = FailIfDifferent): FixedHash(_t == FromHex ? fromHex(_s, WhenError::Throw) : dev::asBytes(_s), _ht) {} /// Convert to arithmetic type. operator Arith() const { return fromBigEndian(m_data); } From 0c382f37f1ceab623a6ec2203e1a12ad14d72a43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 7 Jul 2015 12:46:48 +0200 Subject: [PATCH 200/290] Avoid warnings about unused function arguments. --- libethereum/ExtVM.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libethereum/ExtVM.cpp b/libethereum/ExtVM.cpp index 875fad684..903bf627c 100644 --- a/libethereum/ExtVM.cpp +++ b/libethereum/ExtVM.cpp @@ -78,11 +78,10 @@ void go(unsigned _depth, Executive& _e, OnOpFunc const& _onOp) // Current stack is too small to handle more CALL/CREATE executions. // It needs to be done only once as newly allocated stack space it enough to handle // the rest of the calls up to the depth limit (c_depthLimit). -#if __clang__ // Enabled for clang only as the problem affects OSX + if (_depth == c_offloadPoint) goOnOffloadedStack(_e, _onOp); else -#endif _e.go(_onOp); } } @@ -92,7 +91,11 @@ bool ExtVM::call(CallParameters& _p) Executive e(m_s, lastHashes, depth + 1); if (!e.call(_p, gasPrice, origin)) { + #if __clang__ // Enabled for clang only as the problem affects OSX go(depth, e, _p.onOp); + #else + e.go(_p.onOp); + #endif e.accrueSubState(sub); } _p.gas = e.gas(); From cea26e8dab99665e170a1c40d6762523ad32c073 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 7 Jul 2015 13:22:33 +0200 Subject: [PATCH 201/290] Fixed clang warnings --- alethzero/CMakeLists.txt | 5 +++++ libethereum/TransactionQueue.h | 2 +- mix/CMakeLists.txt | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 93609e54c..25bd3de59 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -7,6 +7,11 @@ if (${CMAKE_MAJOR_VERSION} GREATER 2) cmake_policy(SET CMP0043 OLD) endif() +if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + # Supress warnings for qt headers for clang+ccache + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override") +endif () + set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index 407250530..ad8bd4a87 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -89,7 +89,7 @@ private: struct UnverifiedTransaction { UnverifiedTransaction() {} - UnverifiedTransaction(bytesConstRef const& _t, h512 const& _nodeId): transaction(std::move(_t.toBytes())), nodeId(_nodeId) {} + UnverifiedTransaction(bytesConstRef const& _t, h512 const& _nodeId): transaction(_t.toBytes()), nodeId(_nodeId) {} UnverifiedTransaction(UnverifiedTransaction&& _t): transaction(std::move(_t.transaction)) {} UnverifiedTransaction& operator=(UnverifiedTransaction&& _other) { transaction = std::move(_other.transaction); nodeId = std::move(_other.nodeId); return *this; } diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index 6a434534f..01102ee53 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -15,6 +15,11 @@ include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS}) include_directories(BEFORE ..) +if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + # Supress warnings for qt headers for clang+ccache + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override") +endif () + find_package (Qt5WebEngine QUIET) qt5_add_resources(UI_RESOURCES res.qrc qml.qrc) From 9d0ef73c8eb8560e7b3bcd696363d2a7841acfb9 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 7 Jul 2015 14:05:25 +0200 Subject: [PATCH 202/290] eth_getTransactionReceipt --- libethereum/BlockChain.h | 3 +++ libethereum/ClientBase.cpp | 5 ++++ libethereum/ClientBase.h | 1 + libethereum/Interface.h | 1 + libweb3jsonrpc/JsonHelper.cpp | 27 +++++++++++++++++++++ libweb3jsonrpc/JsonHelper.h | 3 +++ libweb3jsonrpc/WebThreeStubServerBase.cpp | 17 +++++++++++++ libweb3jsonrpc/WebThreeStubServerBase.h | 1 + libweb3jsonrpc/abstractwebthreestubserver.h | 6 +++++ libweb3jsonrpc/spec.json | 1 + test/libweb3jsonrpc/webthreestubclient.h | 10 ++++++++ 11 files changed, 75 insertions(+) diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index 5b3a43d68..4cffca2df 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -142,6 +142,9 @@ public: BlockReceipts receipts(h256 const& _hash) const { return queryExtras(_hash, m_receipts, x_receipts, NullBlockReceipts); } BlockReceipts receipts() const { return receipts(currentHash()); } + /// Get the transaction receipt by transaction hash. Thread-safe. + TransactionReceipt transactionReceipt(h256 const& _transactionHash) const {TransactionAddress ta = queryExtras(_transactionHash, m_transactionAddresses, x_transactionAddresses, NullTransactionAddress); if (!ta) return bytesConstRef(); return receipts(ta.blockHash).receipts[ta.index]; } + /// Get a list of transaction hashes for a given block. Thread-safe. TransactionHashes transactionHashes(h256 const& _hash) const { auto b = block(_hash); RLP rlp(b); h256s ret; for (auto t: rlp[1]) ret.push_back(sha3(t.data())); return ret; } TransactionHashes transactionHashes() const { return transactionHashes(currentHash()); } diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 73404f83d..2cef62680 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -327,6 +327,11 @@ Transaction ClientBase::transaction(h256 _blockHash, unsigned _i) const return Transaction(); } +TransactionReceipt ClientBase::transactionReceipt(h256 const& _transactionHash) const +{ + return bc().transactionReceipt(_transactionHash); +} + pair ClientBase::transactionLocation(h256 const& _transactionHash) const { return bc().transactionLocation(_transactionHash); diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index f0e830d1d..05766b3a1 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -119,6 +119,7 @@ public: virtual BlockDetails blockDetails(h256 _hash) const override; virtual Transaction transaction(h256 _transactionHash) const override; virtual Transaction transaction(h256 _blockHash, unsigned _i) const override; + virtual TransactionReceipt transactionReceipt(h256 const& _transactionHash) const override; virtual std::pair transactionLocation(h256 const& _transactionHash) const override; virtual Transactions transactions(h256 _blockHash) const override; virtual TransactionHashes transactionHashes(h256 _blockHash) const override; diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 0d40937b8..c65670a30 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -135,6 +135,7 @@ public: virtual bool isKnownTransaction(h256 const& _transactionHash) const = 0; virtual Transaction transaction(h256 _transactionHash) const = 0; + virtual TransactionReceipt transactionReceipt(h256 const& _transactionHash) const = 0; virtual std::pair transactionLocation(h256 const& _transactionHash) const = 0; virtual h256 hashFromNumber(BlockNumber _number) const = 0; virtual BlockNumber numberFromHash(h256 _blockHash) const = 0; diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp index 39a856446..96312f625 100644 --- a/libweb3jsonrpc/JsonHelper.cpp +++ b/libweb3jsonrpc/JsonHelper.cpp @@ -182,6 +182,33 @@ Json::Value toJson(dev::eth::TransactionReceipt const& _t) return res; } +Json::Value toJson(dev::eth::TransactionReceipt const& _tr, std::pair _location, BlockNumber _blockNumber, Transaction const& _t) +{ + Json::Value res; + h256 h = _t.sha3(); + res["transactionHash"] = toJS(h); + res["transactionIndex"] = _location.second; + res["blockHash"] = toJS(_location.first); + res["blockNumber"] = _blockNumber; + res["cumulativeGasUsed"] = toJS(_tr.gasUsed()); // TODO: check if this is fine + res["gasUsed"] = toJS(_tr.gasUsed()); + res["contractAddress"] = toJS(toAddress(_t.from(), _t.nonce())); + res["logs"] = Json::Value(Json::arrayValue); + for (unsigned i = 0; i < _tr.log().size(); i++) + { + LogEntry e = _tr.log()[i]; + Json::Value l = toJson(e); + l["type"] = "mined"; + l["blockNumber"] = _blockNumber; + l["blockHash"] = toJS(_location.first); + l["logIndex"] = i; + l["transactionHash"] = toJS(h); + l["transactionIndex"] = _location.second; + res["logs"].append(l); + } + return res; +} + Json::Value toJson(dev::eth::Transaction const& _t) { Json::Value res; diff --git a/libweb3jsonrpc/JsonHelper.h b/libweb3jsonrpc/JsonHelper.h index dd868f8de..421d11b78 100644 --- a/libweb3jsonrpc/JsonHelper.h +++ b/libweb3jsonrpc/JsonHelper.h @@ -50,12 +50,15 @@ using UncleHashes = h256s; using TransactionHashes = h256s; Json::Value toJson(BlockInfo const& _bi); +//TODO: wrap these params into one structure eg. "LocalisedTransaction" Json::Value toJson(Transaction const& _t, std::pair _location, BlockNumber _blockNumber); Json::Value toJson(BlockInfo const& _bi, BlockDetails const& _bd, UncleHashes const& _us, Transactions const& _ts); Json::Value toJson(BlockInfo const& _bi, BlockDetails const& _bd, UncleHashes const& _us, TransactionHashes const& _ts); Json::Value toJson(TransactionSkeleton const& _t); Json::Value toJson(Transaction const& _t); Json::Value toJson(TransactionReceipt const& _t); +//TODO: wrap these params into one structure eg. "LocalisedTransactionReceipt" +Json::Value toJson(TransactionReceipt const& _tr, std::pair _location, BlockNumber _blockNumber, Transaction const& _t); Json::Value toJson(LocalisedLogEntry const& _e); Json::Value toJson(LogEntry const& _e); TransactionSkeleton toTransactionSkeleton(Json::Value const& _json); diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index fd0b4c514..166fbb1bb 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -419,6 +419,23 @@ Json::Value WebThreeStubServerBase::eth_getTransactionByBlockNumberAndIndex(stri } } +Json::Value WebThreeStubServerBase::eth_getTransactionReceipt(string const& _transactionHash) +{ + try + { + h256 h = jsToFixed<32>(_transactionHash); + if (!client()->isKnownTransaction(h)) + return Json::Value(Json::nullValue); + + auto l = client()->transactionLocation(h); + return toJson(client()->transactionReceipt(h), l, client()->numberFromHash(l.first), client()->transaction(h)); + } + catch (...) + { + BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS)); + } +} + Json::Value WebThreeStubServerBase::eth_getUncleByBlockHashAndIndex(string const& _blockHash, string const& _uncleIndex) { try diff --git a/libweb3jsonrpc/WebThreeStubServerBase.h b/libweb3jsonrpc/WebThreeStubServerBase.h index 94fbd1acb..d90015aec 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.h +++ b/libweb3jsonrpc/WebThreeStubServerBase.h @@ -119,6 +119,7 @@ public: virtual Json::Value eth_getTransactionByHash(std::string const& _transactionHash); virtual Json::Value eth_getTransactionByBlockHashAndIndex(std::string const& _blockHash, std::string const& _transactionIndex); virtual Json::Value eth_getTransactionByBlockNumberAndIndex(std::string const& _blockNumber, std::string const& _transactionIndex); + virtual Json::Value eth_getTransactionReceipt(std::string const& _transactionHash); virtual Json::Value eth_getUncleByBlockHashAndIndex(std::string const& _blockHash, std::string const& _uncleIndex); virtual Json::Value eth_getUncleByBlockNumberAndIndex(std::string const& _blockNumber, std::string const& _uncleIndex); virtual Json::Value eth_getCompilers(); diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index 6d0db7394..988271c95 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -40,6 +40,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(jsonrpc::Procedure("eth_getTransactionByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getTransactionByHashI); this->bindAndAddMethod(jsonrpc::Procedure("eth_getTransactionByBlockHashAndIndex", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getTransactionByBlockHashAndIndexI); this->bindAndAddMethod(jsonrpc::Procedure("eth_getTransactionByBlockNumberAndIndex", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getTransactionByBlockNumberAndIndexI); + this->bindAndAddMethod(jsonrpc::Procedure("eth_getTransactionReceipt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getTransactionReceiptI); this->bindAndAddMethod(jsonrpc::Procedure("eth_getUncleByBlockHashAndIndex", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getUncleByBlockHashAndIndexI); this->bindAndAddMethod(jsonrpc::Procedure("eth_getUncleByBlockNumberAndIndex", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getUncleByBlockNumberAndIndexI); this->bindAndAddMethod(jsonrpc::Procedure("eth_getCompilers", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_getCompilersI); @@ -224,6 +225,10 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServereth_getTransactionByBlockNumberAndIndex(request[0u].asString(), request[1u].asString()); } + inline virtual void eth_getTransactionReceiptI(const Json::Value &request, Json::Value &response) + { + response = this->eth_getTransactionReceipt(request[0u].asString()); + } inline virtual void eth_getUncleByBlockHashAndIndexI(const Json::Value &request, Json::Value &response) { response = this->eth_getUncleByBlockHashAndIndex(request[0u].asString(), request[1u].asString()); @@ -489,6 +494,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerCallMethod("eth_getTransactionReceipt",p); + if (result.isObject()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + } Json::Value eth_getUncleByBlockHashAndIndex(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) { Json::Value p; From ce935070406754ae1f351dd3beccba32c43e4f41 Mon Sep 17 00:00:00 2001 From: Dimitry Khokhlov Date: Thu, 2 Jul 2015 22:37:53 +0400 Subject: [PATCH 203/290] Issues: BlockChain::rebuild + byteRef test --- libethereum/BlockChain.cpp | 2 +- test/libdevcore/core.cpp | 41 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 test/libdevcore/core.cpp diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index d8dbd266f..be3449a60 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -273,7 +273,7 @@ void BlockChain::rebuild(std::string const& _path, std::function. +*/ +/** @file core.cpp + * @author Dimitry Khokhlov + * @date 2014 + * CORE test functions. + */ + +#include +#include +#include + +BOOST_AUTO_TEST_SUITE(CoreLibTests) + +BOOST_AUTO_TEST_CASE(byteRef) +{ + cnote << "bytesRef copyTo and toString..."; + dev::bytes originalSequence = dev::fromHex("0102030405060708091011121314151617181920212223242526272829303132"); + dev::bytesRef _out(&originalSequence.at(0), 32); + dev::h256 ret("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"); + ret.ref().copyTo(_out); + + BOOST_CHECK_MESSAGE(_out.size() == 32, "Error wrong result size when h256::ref().copyTo(dev::bytesRef out)"); + BOOST_CHECK_MESSAGE(_out.toBytes() == originalSequence, "Error when h256::ref().copyTo(dev::bytesRef out)"); +} + +BOOST_AUTO_TEST_SUITE_END() From 5a84977bf43c48f3f103010354966e80f8aa63a3 Mon Sep 17 00:00:00 2001 From: Dimitry Khokhlov Date: Tue, 7 Jul 2015 16:16:17 +0400 Subject: [PATCH 204/290] fix: style --- test/libdevcore/core.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/libdevcore/core.cpp b/test/libdevcore/core.cpp index 696983cf5..e7c7c86a1 100644 --- a/test/libdevcore/core.cpp +++ b/test/libdevcore/core.cpp @@ -30,12 +30,12 @@ BOOST_AUTO_TEST_CASE(byteRef) { cnote << "bytesRef copyTo and toString..."; dev::bytes originalSequence = dev::fromHex("0102030405060708091011121314151617181920212223242526272829303132"); - dev::bytesRef _out(&originalSequence.at(0), 32); - dev::h256 ret("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"); - ret.ref().copyTo(_out); + dev::bytesRef out(&originalSequence.at(0), 32); + dev::h256 hash32("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"); + hash32.ref().copyTo(out); - BOOST_CHECK_MESSAGE(_out.size() == 32, "Error wrong result size when h256::ref().copyTo(dev::bytesRef out)"); - BOOST_CHECK_MESSAGE(_out.toBytes() == originalSequence, "Error when h256::ref().copyTo(dev::bytesRef out)"); + BOOST_CHECK_MESSAGE(out.size() == 32, "Error wrong result size when h256::ref().copyTo(dev::bytesRef out)"); + BOOST_CHECK_MESSAGE(out.toBytes() == originalSequence, "Error when h256::ref().copyTo(dev::bytesRef out)"); } BOOST_AUTO_TEST_SUITE_END() From 12f0d02beb843dc7d1bed36ae3cdeb271d115e78 Mon Sep 17 00:00:00 2001 From: Dimitry Khokhlov Date: Mon, 6 Jul 2015 21:01:56 +0400 Subject: [PATCH 205/290] smartcode: fix --- test/fuzzTesting/fuzzHelper.cpp | 156 +++++++++++--------------------- 1 file changed, 53 insertions(+), 103 deletions(-) diff --git a/test/fuzzTesting/fuzzHelper.cpp b/test/fuzzTesting/fuzzHelper.cpp index de7f56dc9..02404a9f2 100644 --- a/test/fuzzTesting/fuzzHelper.cpp +++ b/test/fuzzTesting/fuzzHelper.cpp @@ -74,7 +74,7 @@ std::string RandomCode::generate(int _maxOpNumber, RandomCodeOptions _options) uint8_t opcode = weightsDefined ? randOpCodeWeight() : randOpCodeGen(); dev::eth::InstructionInfo info = dev::eth::instructionInfo((dev::eth::Instruction) opcode); - if (info.name.find_first_of("INVALID_INSTRUCTION") > 0) + if (info.name.find("INVALID_INSTRUCTION") != std::string::npos) { //Byte code is yet not implemented if (_options.useUndefinedOpCodes == false) @@ -85,12 +85,12 @@ std::string RandomCode::generate(int _maxOpNumber, RandomCodeOptions _options) } else { - if (info.name.find_first_of("PUSH") > 0) + if (info.name.find("PUSH") != std::string::npos) code += toCompactHex(opcode); code += fillArguments((dev::eth::Instruction) opcode, _options); } - if (info.name.find_first_of("PUSH") <= 0) + if (info.name.find("PUSH") == std::string::npos) { std::string byte = toCompactHex(opcode); code += (byte == "") ? "00" : byte; @@ -145,117 +145,67 @@ std::string RandomCode::fillArguments(dev::eth::Instruction _opcode, RandomCodeO unsigned num = info.args; int rand = randUniIntGen() % 100; if (rand < _options.smartCodeProbability) - smart = true; + smart = true; if (smart) { - switch (_opcode) + //PUSH1 ... PUSH32 + if (int(dev::eth::Instruction::PUSH1) <= int(_opcode) && int(_opcode) <= int(dev::eth::Instruction::PUSH32)) + { + code += rndByteSequence(int(_opcode) - int(dev::eth::Instruction::PUSH1) + 1); + return code; + } + + //SWAP1 ... SWAP16 || DUP1 ... DUP16 + if ((int(dev::eth::Instruction::SWAP1) <= int(_opcode) && int(_opcode) <= int(dev::eth::Instruction::SWAP16)) + || (int(dev::eth::Instruction::DUP1) <= int(_opcode) && int(_opcode) <= int(dev::eth::Instruction::DUP16))) { - case dev::eth::Instruction::PUSH1: code += rndByteSequence(1); break; - case dev::eth::Instruction::PUSH2: code += rndByteSequence(2); break; - case dev::eth::Instruction::PUSH3: code += rndByteSequence(3); break; - case dev::eth::Instruction::PUSH4: code += rndByteSequence(4); break; - case dev::eth::Instruction::PUSH5: code += rndByteSequence(5); break; - case dev::eth::Instruction::PUSH6: code += rndByteSequence(6); break; - case dev::eth::Instruction::PUSH7: code += rndByteSequence(7); break; - case dev::eth::Instruction::PUSH8: code += rndByteSequence(8); break; - case dev::eth::Instruction::PUSH9: code += rndByteSequence(9); break; - case dev::eth::Instruction::PUSH10: code += rndByteSequence(10); break; - case dev::eth::Instruction::PUSH11: code += rndByteSequence(11); break; - case dev::eth::Instruction::PUSH12: code += rndByteSequence(12); break; - case dev::eth::Instruction::PUSH13: code += rndByteSequence(13); break; - case dev::eth::Instruction::PUSH14: code += rndByteSequence(14); break; - case dev::eth::Instruction::PUSH15: code += rndByteSequence(15); break; - case dev::eth::Instruction::PUSH16: code += rndByteSequence(16); break; - case dev::eth::Instruction::PUSH17: code += rndByteSequence(17); break; - case dev::eth::Instruction::PUSH18: code += rndByteSequence(18); break; - case dev::eth::Instruction::PUSH19: code += rndByteSequence(19); break; - case dev::eth::Instruction::PUSH20: code += rndByteSequence(20); break; - case dev::eth::Instruction::PUSH21: code += rndByteSequence(21); break; - case dev::eth::Instruction::PUSH22: code += rndByteSequence(22); break; - case dev::eth::Instruction::PUSH23: code += rndByteSequence(23); break; - case dev::eth::Instruction::PUSH24: code += rndByteSequence(24); break; - case dev::eth::Instruction::PUSH25: code += rndByteSequence(25); break; - case dev::eth::Instruction::PUSH26: code += rndByteSequence(26); break; - case dev::eth::Instruction::PUSH27: code += rndByteSequence(27); break; - case dev::eth::Instruction::PUSH28: code += rndByteSequence(28); break; - case dev::eth::Instruction::PUSH29: code += rndByteSequence(29); break; - case dev::eth::Instruction::PUSH30: code += rndByteSequence(30); break; - case dev::eth::Instruction::PUSH31: code += rndByteSequence(31); break; - case dev::eth::Instruction::PUSH32: code += rndByteSequence(32); break; - case dev::eth::Instruction::SWAP1: - case dev::eth::Instruction::SWAP2: - case dev::eth::Instruction::SWAP3: - case dev::eth::Instruction::SWAP4: - case dev::eth::Instruction::SWAP5: - case dev::eth::Instruction::SWAP6: - case dev::eth::Instruction::SWAP7: - case dev::eth::Instruction::SWAP8: - case dev::eth::Instruction::SWAP9: - case dev::eth::Instruction::SWAP10: - case dev::eth::Instruction::SWAP11: - case dev::eth::Instruction::SWAP12: - case dev::eth::Instruction::SWAP13: - case dev::eth::Instruction::SWAP14: - case dev::eth::Instruction::SWAP15: - case dev::eth::Instruction::SWAP16: - case dev::eth::Instruction::DUP1: - case dev::eth::Instruction::DUP2: - case dev::eth::Instruction::DUP3: - case dev::eth::Instruction::DUP4: - case dev::eth::Instruction::DUP5: - case dev::eth::Instruction::DUP6: - case dev::eth::Instruction::DUP7: - case dev::eth::Instruction::DUP8: - case dev::eth::Instruction::DUP9: - case dev::eth::Instruction::DUP10: - case dev::eth::Instruction::DUP11: - case dev::eth::Instruction::DUP12: - case dev::eth::Instruction::DUP13: - case dev::eth::Instruction::DUP14: - case dev::eth::Instruction::DUP15: - case dev::eth::Instruction::DUP16: int times; switch (_opcode) { - case dev::eth::Instruction::DUP1: times = 1; break; - case dev::eth::Instruction::SWAP1: - case dev::eth::Instruction::DUP2: times = 2; break; - case dev::eth::Instruction::SWAP2: - case dev::eth::Instruction::DUP3: times = 3; break; - case dev::eth::Instruction::SWAP3: - case dev::eth::Instruction::DUP4: times = 4; break; - case dev::eth::Instruction::SWAP4: - case dev::eth::Instruction::DUP5: times = 5; break; - case dev::eth::Instruction::SWAP5: - case dev::eth::Instruction::DUP6: times = 6; break; - case dev::eth::Instruction::SWAP6: - case dev::eth::Instruction::DUP7: times = 7; break; - case dev::eth::Instruction::SWAP7: - case dev::eth::Instruction::DUP8: times = 8; break; - case dev::eth::Instruction::SWAP8: - case dev::eth::Instruction::DUP9: times = 9; break; - case dev::eth::Instruction::SWAP9: - case dev::eth::Instruction::DUP10: times = 10; break; - case dev::eth::Instruction::SWAP10: - case dev::eth::Instruction::DUP11: times = 11; break; - case dev::eth::Instruction::SWAP11: - case dev::eth::Instruction::DUP12: times = 12; break; - case dev::eth::Instruction::SWAP12: - case dev::eth::Instruction::DUP13: times = 13; break; - case dev::eth::Instruction::SWAP13: - case dev::eth::Instruction::DUP14: times = 14; break; - case dev::eth::Instruction::SWAP14: - case dev::eth::Instruction::DUP15: times = 15; break; - case dev::eth::Instruction::SWAP15: - case dev::eth::Instruction::DUP16: times = 16; break; - case dev::eth::Instruction::SWAP16: times = 17; break; - default: times = 1; + case dev::eth::Instruction::DUP1: times = 1; break; + case dev::eth::Instruction::SWAP1: + case dev::eth::Instruction::DUP2: times = 2; break; + case dev::eth::Instruction::SWAP2: + case dev::eth::Instruction::DUP3: times = 3; break; + case dev::eth::Instruction::SWAP3: + case dev::eth::Instruction::DUP4: times = 4; break; + case dev::eth::Instruction::SWAP4: + case dev::eth::Instruction::DUP5: times = 5; break; + case dev::eth::Instruction::SWAP5: + case dev::eth::Instruction::DUP6: times = 6; break; + case dev::eth::Instruction::SWAP6: + case dev::eth::Instruction::DUP7: times = 7; break; + case dev::eth::Instruction::SWAP7: + case dev::eth::Instruction::DUP8: times = 8; break; + case dev::eth::Instruction::SWAP8: + case dev::eth::Instruction::DUP9: times = 9; break; + case dev::eth::Instruction::SWAP9: + case dev::eth::Instruction::DUP10: times = 10; break; + case dev::eth::Instruction::SWAP10: + case dev::eth::Instruction::DUP11: times = 11; break; + case dev::eth::Instruction::SWAP11: + case dev::eth::Instruction::DUP12: times = 12; break; + case dev::eth::Instruction::SWAP12: + case dev::eth::Instruction::DUP13: times = 13; break; + case dev::eth::Instruction::SWAP13: + case dev::eth::Instruction::DUP14: times = 14; break; + case dev::eth::Instruction::SWAP14: + case dev::eth::Instruction::DUP15: times = 15; break; + case dev::eth::Instruction::SWAP15: + case dev::eth::Instruction::DUP16: times = 16; break; + case dev::eth::Instruction::SWAP16: times = 17; break; + default: times = 1; } + for (int i = 0; i < times; i ++) code += getPushCode(randUniIntGen() % 32); - break; + return code; + } + + switch (_opcode) + { case dev::eth::Instruction::CREATE: //(CREATE value mem1 mem2) code += getPushCode(randUniIntGen() % 128); //memlen1 From 73020754e3b89fdbe09ec3fc909312fdaac07c57 Mon Sep 17 00:00:00 2001 From: Dimitry Khokhlov Date: Tue, 7 Jul 2015 17:25:09 +0400 Subject: [PATCH 206/290] smartcode: style --- test/fuzzTesting/fuzzHelper.cpp | 51 +++++++-------------------------- 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/test/fuzzTesting/fuzzHelper.cpp b/test/fuzzTesting/fuzzHelper.cpp index 02404a9f2..50504a195 100644 --- a/test/fuzzTesting/fuzzHelper.cpp +++ b/test/fuzzTesting/fuzzHelper.cpp @@ -145,58 +145,29 @@ std::string RandomCode::fillArguments(dev::eth::Instruction _opcode, RandomCodeO unsigned num = info.args; int rand = randUniIntGen() % 100; if (rand < _options.smartCodeProbability) - smart = true; + smart = true; if (smart) { //PUSH1 ... PUSH32 - if (int(dev::eth::Instruction::PUSH1) <= int(_opcode) && int(_opcode) <= int(dev::eth::Instruction::PUSH32)) + if (dev::eth::Instruction::PUSH1 <= _opcode && _opcode <= dev::eth::Instruction::PUSH32) { code += rndByteSequence(int(_opcode) - int(dev::eth::Instruction::PUSH1) + 1); return code; } //SWAP1 ... SWAP16 || DUP1 ... DUP16 - if ((int(dev::eth::Instruction::SWAP1) <= int(_opcode) && int(_opcode) <= int(dev::eth::Instruction::SWAP16)) - || (int(dev::eth::Instruction::DUP1) <= int(_opcode) && int(_opcode) <= int(dev::eth::Instruction::DUP16))) + bool isSWAP = (dev::eth::Instruction::SWAP1 <= _opcode && _opcode <= dev::eth::Instruction::SWAP16); + bool isDUP = (dev::eth::Instruction::DUP1 <= _opcode && _opcode <= dev::eth::Instruction::DUP16); + + if (isSWAP || isDUP) { int times; - switch (_opcode) - { - case dev::eth::Instruction::DUP1: times = 1; break; - case dev::eth::Instruction::SWAP1: - case dev::eth::Instruction::DUP2: times = 2; break; - case dev::eth::Instruction::SWAP2: - case dev::eth::Instruction::DUP3: times = 3; break; - case dev::eth::Instruction::SWAP3: - case dev::eth::Instruction::DUP4: times = 4; break; - case dev::eth::Instruction::SWAP4: - case dev::eth::Instruction::DUP5: times = 5; break; - case dev::eth::Instruction::SWAP5: - case dev::eth::Instruction::DUP6: times = 6; break; - case dev::eth::Instruction::SWAP6: - case dev::eth::Instruction::DUP7: times = 7; break; - case dev::eth::Instruction::SWAP7: - case dev::eth::Instruction::DUP8: times = 8; break; - case dev::eth::Instruction::SWAP8: - case dev::eth::Instruction::DUP9: times = 9; break; - case dev::eth::Instruction::SWAP9: - case dev::eth::Instruction::DUP10: times = 10; break; - case dev::eth::Instruction::SWAP10: - case dev::eth::Instruction::DUP11: times = 11; break; - case dev::eth::Instruction::SWAP11: - case dev::eth::Instruction::DUP12: times = 12; break; - case dev::eth::Instruction::SWAP12: - case dev::eth::Instruction::DUP13: times = 13; break; - case dev::eth::Instruction::SWAP13: - case dev::eth::Instruction::DUP14: times = 14; break; - case dev::eth::Instruction::SWAP14: - case dev::eth::Instruction::DUP15: times = 15; break; - case dev::eth::Instruction::SWAP15: - case dev::eth::Instruction::DUP16: times = 16; break; - case dev::eth::Instruction::SWAP16: times = 17; break; - default: times = 1; - } + if (isSWAP) + times = int(_opcode) - int(dev::eth::Instruction::SWAP1) + 2; + else + if (isDUP) + times = int(_opcode) - int(dev::eth::Instruction::DUP1) + 1; for (int i = 0; i < times; i ++) code += getPushCode(randUniIntGen() % 32); From f8a4ca2a5c5adcdb42ad50ea8c5f0dc800208dbb Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 7 Jul 2015 16:32:02 +0200 Subject: [PATCH 207/290] Disable auto adjust of batch size by default After reports from many miners the whole auto adjusting idea may or may not work depending the user's hardware. A much safer default value is 0 (to disable auto adjustment) --- libethcore/Ethash.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 3baac3292..9ec6dd71f 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -56,7 +56,7 @@ namespace eth const unsigned Ethash::defaultLocalWorkSize = 64; const unsigned Ethash::defaultGlobalWorkSizeMultiplier = 512; // * CL_DEFAULT_LOCAL_WORK_SIZE -const unsigned Ethash::defaultMSPerBatch = 100; +const unsigned Ethash::defaultMSPerBatch = 0; const Ethash::WorkPackage Ethash::NullWorkPackage = Ethash::WorkPackage(); std::string Ethash::name() From 6f2731d3f30b53ba28380dcf3ff3c19292e523ad Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 7 Jul 2015 16:36:49 +0200 Subject: [PATCH 208/290] Style. --- libdevcore/Base64.cpp | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/libdevcore/Base64.cpp b/libdevcore/Base64.cpp index f97c82156..8ee2b29f7 100644 --- a/libdevcore/Base64.cpp +++ b/libdevcore/Base64.cpp @@ -27,6 +27,8 @@ /// Originally by René Nyffenegger, modified by some other guy and then devified by Gav Wood. #include "Base64.h" + +using namespace std; using namespace dev; static inline bool is_base64(byte c) @@ -44,14 +46,14 @@ static inline byte find_base64_char_index(byte c) else return 1 + find_base64_char_index('/'); } -std::string dev::toBase64(bytesConstRef _in) +string dev::toBase64(bytesConstRef _in) { static const char base64_chars[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; - std::string ret; + string ret; int i = 0; int j = 0; byte char_array_3[3]; @@ -60,15 +62,17 @@ std::string dev::toBase64(bytesConstRef _in) auto buf = _in.data(); auto bufLen = _in.size(); - while (bufLen--) { + while (bufLen--) + { char_array_3[i++] = *(buf++); - if (i == 3) { + if (i == 3) + { char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; - for(i = 0; (i <4) ; i++) + for (i = 0; i < 4; i++) ret += base64_chars[char_array_4[i]]; i = 0; } @@ -76,7 +80,7 @@ std::string dev::toBase64(bytesConstRef _in) if (i) { - for(j = i; j < 3; j++) + for (j = i; j < 3; j++) char_array_3[j] = '\0'; char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; @@ -84,28 +88,31 @@ std::string dev::toBase64(bytesConstRef _in) char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; - for (j = 0; (j < i + 1); j++) + for (j = 0; j < i + 1; j++) ret += base64_chars[char_array_4[j]]; - while((i++ < 3)) + while (i++ < 3) ret += '='; } return ret; } -bytes dev::fromBase64(std::string const& encoded_string) +bytes dev::fromBase64(string const& encoded_string) { auto in_len = encoded_string.size(); int i = 0; int j = 0; int in_ = 0; - byte char_array_4[4], char_array_3[3]; + byte char_array_3[3]; + byte char_array_4[4]; bytes ret; - while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { + while (in_len-- && encoded_string[in_] != '=' && is_base64(encoded_string[in_])) + { char_array_4[i++] = encoded_string[in_]; in_++; - if (i == 4) { + if (i == 4) + { for (i = 0; i < 4; i++) char_array_4[i] = find_base64_char_index(char_array_4[i]); @@ -119,7 +126,8 @@ bytes dev::fromBase64(std::string const& encoded_string) } } - if (i) { + if (i) + { for (j = i; j < 4; j++) char_array_4[j] = 0; @@ -130,7 +138,8 @@ bytes dev::fromBase64(std::string const& encoded_string) char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - for (j = 0; (j < i - 1); j++) ret.push_back(char_array_3[j]); + for (j = 0; j < i - 1; j++) + ret.push_back(char_array_3[j]); } return ret; From f29cb461c93d4c90d89a3193813668b9e3a378be Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 08:11:35 -0700 Subject: [PATCH 209/290] Tidy up gaurds. Shorted extraData to max size. --- libethereum/BlockChain.cpp | 38 ++++++++++---------------------------- libethereum/State.cpp | 31 ++++++++++++------------------- 2 files changed, 22 insertions(+), 47 deletions(-) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index d8dbd266f..207582ba9 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -871,33 +871,21 @@ template static unsigned getHashSize(unordered_map const& _ma void BlockChain::updateStats() const { - { - ReadGuard l(x_blocks); - m_lastStats.memBlocks = 0; + m_lastStats.memBlocks = 0; + DEV_READ_GUARDED(x_blocks) for (auto const& i: m_blocks) m_lastStats.memBlocks += i.second.size() + 64; - } - { - ReadGuard l(x_details); + DEV_READ_GUARDED(x_details) m_lastStats.memDetails = getHashSize(m_details); - } - { - ReadGuard l1(x_logBlooms); - ReadGuard l2(x_blocksBlooms); - m_lastStats.memLogBlooms = getHashSize(m_logBlooms) + getHashSize(m_blocksBlooms); - } - { - ReadGuard l(x_receipts); + DEV_READ_GUARDED(x_logBlooms) + DEV_READ_GUARDED(x_blocksBlooms) + m_lastStats.memLogBlooms = getHashSize(m_logBlooms) + getHashSize(m_blocksBlooms); + DEV_READ_GUARDED(x_receipts) m_lastStats.memReceipts = getHashSize(m_receipts); - } - { - ReadGuard l(x_blockHashes); + DEV_READ_GUARDED(x_blockHashes) m_lastStats.memBlockHashes = getHashSize(m_blockHashes); - } - { - ReadGuard l(x_transactionAddresses); + DEV_READ_GUARDED(x_transactionAddresses) m_lastStats.memTransactionAddresses = getHashSize(m_transactionAddresses); - } } void BlockChain::garbageCollect(bool _force) @@ -954,10 +942,8 @@ void BlockChain::garbageCollect(bool _force) void BlockChain::checkConsistency() { - { - WriteGuard l(x_details); + DEV_WRITE_GUARDED(x_details) m_details.clear(); - } ldb::Iterator* it = m_blocksDB->NewIterator(m_readOptions); for (it->SeekToFirst(); it->Valid(); it->Next()) if (it->key().size() == 32) @@ -969,13 +955,9 @@ void BlockChain::checkConsistency() { auto dp = details(p); if (asserts(contains(dp.children, h))) - { cnote << "Apparently the database is corrupt. Not much we can do at this stage..."; - } if (assertsEqual(dp.number, dh.number - 1)) - { cnote << "Apparently the database is corrupt. Not much we can do at this stage..."; - } } } delete it; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index e1bdd19b6..4326d5cf3 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -445,7 +445,8 @@ u256 State::enactOn(VerifiedBlockRef const& _block, BlockChain const& _bc, Impor #if ETH_TIMED_ENACTMENTS enactment = t.elapsed(); - cnote << "popVer/popGrand/syncReset/enactment = " << populateVerify << "/" << populateGrand << "/" << syncReset << "/" << enactment; + if (populateVerify + populateGrand + syncReset + enactment > 0.5) + clog(StateChat) << "popVer/popGrand/syncReset/enactment = " << populateVerify << "/" << populateGrand << "/" << syncReset << "/" << enactment; #endif return ret; } @@ -513,18 +514,17 @@ pair State::sync(BlockChain const& _bc, TransactionQu { if (t.gasPrice() >= _gp.ask(*this)) { - // Timer t; +// Timer t; if (lh.empty()) lh = _bc.lastHashes(); execute(lh, t); ret.first.push_back(m_receipts.back()); ++goodTxs; - // cnote << "TX took:" << t.elapsed() * 1000; +// cnote << "TX took:" << t.elapsed() * 1000; } else if (t.gasPrice() < _gp.ask(*this) * 9 / 10) { - // less than 90% of our ask price for gas. drop. - cnote << t.sha3() << "Dropping El Cheapo transaction (<90% of ask price)"; + clog(StateTrace) << t.sha3() << "Dropping El Cheapo transaction (<90% of ask price)"; _tq.drop(t.sha3()); } } @@ -536,22 +536,13 @@ pair State::sync(BlockChain const& _bc, TransactionQu if (req > got) { // too old -/* for (Transaction const& mt: m_transactions) - { - if (mt.from() == t.from()) - { - if (mt.nonce() < t.nonce()) - cnote << t.sha3() << "Dropping old transaction (nonce too low)"; - else if (mt.nonce() == t.nonce() && mt.gasPrice() <= t.gasPrice()) - cnote << t.sha3() << "Dropping old transaction (gas price lower)"; - } - }*/ + clog(StateTrace) << t.sha3() << "Dropping old transaction (nonce too low)"; _tq.drop(t.sha3()); } else if (got > req + _tq.waiting(t.sender())) { // too new - cnote << t.sha3() << "Dropping new transaction (too many nonces ahead)"; + clog(StateTrace) << t.sha3() << "Dropping new transaction (too many nonces ahead)"; _tq.drop(t.sha3()); } else @@ -562,7 +553,7 @@ pair State::sync(BlockChain const& _bc, TransactionQu bigint const& got = *boost::get_error_info(e); if (got > m_currentBlock.gasLimit) { - cnote << t.sha3() << "Dropping over-gassy transaction (gas > block's gas limit)"; + clog(StateTrace) << t.sha3() << "Dropping over-gassy transaction (gas > block's gas limit)"; _tq.drop(t.sha3()); } else @@ -576,14 +567,14 @@ pair State::sync(BlockChain const& _bc, TransactionQu catch (Exception const& _e) { // Something else went wrong - drop it. - cnote << t.sha3() << "Dropping invalid transaction:" << diagnostic_information(_e); + clog(StateTrace) << t.sha3() << "Dropping invalid transaction:" << diagnostic_information(_e); _tq.drop(t.sha3()); } catch (std::exception const&) { // Something else went wrong - drop it. _tq.drop(t.sha3()); - cnote << t.sha3() << "Transaction caused low-level exception :("; + cwarn << t.sha3() << "Transaction caused low-level exception :("; } } if (chrono::steady_clock::now() > deadline) @@ -965,6 +956,8 @@ void State::commitToMine(BlockChain const& _bc, bytes const& _extraData) m_currentBlock.stateRoot = m_state.root(); m_currentBlock.parentHash = m_previousBlock.hash(); m_currentBlock.extraData = _extraData; + if (m_currentBlock.extraData.size() > 32) + m_currentBlock.extraData.resize(32); m_committedToMine = true; } From 5124ff752b7ef663d3583e6af413421346871d69 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 08:15:29 -0700 Subject: [PATCH 210/290] Switch to YP compliant gas accounting at block 830k --- libethereum/State.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 4326d5cf3..8ba3b438a 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -1262,8 +1262,7 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per // Add to the user-originated transactions that we've executed. m_transactions.push_back(e.t()); -// m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + e.gasUsedNoRefunds(), e.logs())); // TODO: Switch in to be compliant with YP. - m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + e.gasUsed(), e.logs())); + m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + (m_currentBlock.number >= 830000 ? e.gasUsedNoRefunds() : e.gasUsed()), e.logs())); m_transactionSet.insert(e.t().sha3()); } From e5cd66898c6bc07cdc84b06e1a91a2561f9b4734 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 10:02:31 -0700 Subject: [PATCH 211/290] Version bump. --- libdevcore/Common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 5591e94bf..6ba933556 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -28,7 +28,7 @@ using namespace dev; namespace dev { -char const* Version = "0.9.28"; +char const* Version = "0.9.29"; const u256 UndefinedU256 = ~(u256)0; From 9ade9777a68e9c9f17ea730f78887b30963dab88 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 10:11:35 -0700 Subject: [PATCH 212/290] Olympic & Frontier specs --- alethzero/Main.ui | 4 ++-- alethzero/MainWin.cpp | 6 ++++++ eth/main.cpp | 9 +++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/alethzero/Main.ui b/alethzero/Main.ui index 67a15d248..b2e3a9a29 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -11,7 +11,7 @@ - AlethZero Ethereum Client + AlethZero ++Ethereum true @@ -132,7 +132,7 @@ 0 0 1617 - 25 + 24 diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 1e4577bf5..bc569c5cf 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -136,6 +136,12 @@ Main::Main(QWidget *parent) : QtWebEngine::initialize(); setWindowFlags(Qt::Window); ui->setupUi(this); + + if (c_network == eth::Network::Olympic) + setWindowTitle("AlethZero Olympic"); + else if (c_network == eth::Network::Frontier) + setWindowTitle("AlethZero Frontier"); + g_logPost = [=](string const& s, char const* c) { simpleDebugOut(s, c); diff --git a/eth/main.cpp b/eth/main.cpp index e4facccee..4b92cafbb 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -1471,6 +1471,15 @@ int main(int argc, char** argv) } } + if (g_logVerbosity > 0) + { + cout << EthGrayBold "(++)Ethereum" EthReset << endl; + if (c_network == eth::Network::Olympic) + cout << "Welcome to Olympic!" << endl; + else if (c_network == eth::Network::Frontier) + cout << "Welcome to the " EthMaroonBold "Frontier" EthReset "!" << endl; + } + m.execute(); KeyManager keyManager; From 091e5d13dd950c67a675683fc0c382ea0ff77583 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 10:32:16 -0700 Subject: [PATCH 213/290] Reorganise logs. --- libethereum/EthereumHost.cpp | 26 +++++++++++++++++--------- libethereum/EthereumHost.h | 2 ++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 186eb6fa8..f00ec7dc7 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -45,6 +45,12 @@ static unsigned const c_maxSendTransactions = 256; char const* const EthereumHost::s_stateNames[static_cast(SyncState::Size)] = {"Idle", "Waiting", "Hashes", "Blocks", "NewBlocks" }; +#ifdef _WIN32 +const char* EthereumHostTrace::name() { return EthPurple "^" EthGray " "; } +#else +const char* EthereumHostTrace::name() { return EthPurple "⧫" EthGray " "; } +#endif + EthereumHost::EthereumHost(BlockChain const& _ch, TransactionQueue& _tq, BlockQueue& _bq, u256 _networkId): HostCapability(), Worker ("ethsync"), @@ -67,7 +73,7 @@ bool EthereumHost::ensureInitialised() { // First time - just initialise. m_latestBlockSent = m_chain.currentHash(); - clog(NetNote) << "Initialising: latest=" << m_latestBlockSent; + clog(EthereumHostTrace) << "Initialising: latest=" << m_latestBlockSent; Guard l(x_transactions); m_transactionsSent = m_tq.knownTransactions(); @@ -150,7 +156,7 @@ void EthereumHost::maintainTransactions() RLPStream ts; _p->prep(ts, TransactionsPacket, n).appendRaw(b, n); _p->sealAndSend(ts); - cnote << "Sent" << n << "transactions to " << _p->session()->info().clientVersion; + clog(EthereumHostTrace) << "Sent" << n << "transactions to " << _p->session()->info().clientVersion; } _p->m_requireTransactions = false; return true; @@ -206,11 +212,15 @@ void EthereumHost::maintainBlocks(h256 const& _currentHash) if (diff(detailsFrom.number, detailsTo.number) < 20) { // don't be sending more than 20 "new" blocks. if there are any more we were probably waaaay behind. - clog(NetMessageSummary) << "Sending a new block (current is" << _currentHash << ", was" << m_latestBlockSent << ")"; + clog(EthereumHostTrace) << "Sending a new block (current is" << _currentHash << ", was" << m_latestBlockSent << ")"; h256s blocks = get<0>(m_chain.treeRoute(m_latestBlockSent, _currentHash, false, false, true)); - auto s = randomSelection(25, [&](EthereumPeer* p){ DEV_GUARDED(p->x_knownBlocks) return !p->m_knownBlocks.count(_currentHash); return false; }); + auto s = randomSelection(25, [&](EthereumPeer* p){ + DEV_GUARDED(p->x_knownBlocks) + return !p->m_knownBlocks.count(_currentHash); + return false; + }); for (shared_ptr const& p: get<0>(s)) for (auto const& b: blocks) { @@ -292,11 +302,11 @@ void EthereumHost::onPeerTransactions(std::shared_ptr _peer, RLP c { if (_peer->isCriticalSyncing()) { - clog(NetAllDetail) << "Ignoring transaction from peer we are syncing with"; + clog(EthereumHostTrace) << "Ignoring transaction from peer we are syncing with"; return; } unsigned itemCount = _r.itemCount(); - clog(NetAllDetail) << "Transactions (" << dec << itemCount << "entries)"; + clog(EthereumHostTrace) << "Transactions (" << dec << itemCount << "entries)"; m_tq.enqueue(_r, _peer->session()->id()); } @@ -351,10 +361,8 @@ void EthereumHost::onTransactionImported(ImportResult _ir, h256 const& _h, h512 break; case ImportResult::AlreadyKnown: // if we already had the transaction, then don't bother sending it on. - { - Guard l(x_transactions); + DEV_GUARDED(x_transactions) m_transactionsSent.insert(_h); - } peer->addRating(0); break; case ImportResult::Success: diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index b65ddb5d0..6cb82ebb4 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -49,6 +49,8 @@ class TransactionQueue; class BlockQueue; class BlockChainSync; +struct EthereumHostTrace: public LogChannel { static const char* name(); static const int verbosity = 6; }; + /** * @brief The EthereumHost class * @warning None of this is thread-safe. You have been warned. From b2640e151a0e8f80ef25157e4485aa8b41811590 Mon Sep 17 00:00:00 2001 From: Dimitry Khokhlov Date: Tue, 7 Jul 2015 22:56:09 +0400 Subject: [PATCH 214/290] fuzz: undefined variable build fix --- test/fuzzTesting/fuzzHelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fuzzTesting/fuzzHelper.cpp b/test/fuzzTesting/fuzzHelper.cpp index 50504a195..b6a3bd700 100644 --- a/test/fuzzTesting/fuzzHelper.cpp +++ b/test/fuzzTesting/fuzzHelper.cpp @@ -162,7 +162,7 @@ std::string RandomCode::fillArguments(dev::eth::Instruction _opcode, RandomCodeO if (isSWAP || isDUP) { - int times; + int times = 0; if (isSWAP) times = int(_opcode) - int(dev::eth::Instruction::SWAP1) + 2; else From 136a077625ee0b22efbcc24d35256c8bd58be053 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 13:04:30 -0700 Subject: [PATCH 215/290] Undo hard fork. --- libethereum/State.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 8ba3b438a..f50545d08 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -1212,7 +1212,6 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per uncommitToMine(); // OK - transaction looks valid - execute. - u256 startGasUsed = gasUsed(); #if ETH_PARANOIA ctrace << "Executing" << e.t() << "on" << h; ctrace << toHex(e.t().rlp()); @@ -1262,7 +1261,7 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per // Add to the user-originated transactions that we've executed. m_transactions.push_back(e.t()); - m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + (m_currentBlock.number >= 830000 ? e.gasUsedNoRefunds() : e.gasUsed()), e.logs())); + m_receipts.push_back(TransactionReceipt(rootHash(), e.gasUsed(), e.logs())); m_transactionSet.insert(e.t().sha3()); } From f014438195be4a13c3e9601c5f337e69a6bdd376 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 13:09:25 -0700 Subject: [PATCH 216/290] Don't use PRNG for key generation! --- libdevcrypto/Common.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index 8bf95d02f..e45d1cfb6 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -262,16 +262,9 @@ bytes dev::scrypt(std::string const& _pass, bytes const& _salt, uint64_t _n, uin KeyPair KeyPair::create() { - static boost::thread_specific_ptr s_eng; - static unsigned s_id = 0; - if (!s_eng.get()) - s_eng.reset(new mt19937_64(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count() + ++s_id)); - - uniform_int_distribution d(0, 255); - for (int i = 0; i < 100; ++i) { - KeyPair ret(FixedHash<32>::random(*s_eng.get())); + KeyPair ret(FixedHash<32>::random()); if (ret.address()) return ret; } From e9cff7f0212c92a1894bd929efe44e22f42d0b79 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 13:11:16 -0700 Subject: [PATCH 217/290] Better casting. --- libdevcore/FixedHash.h | 2 +- libdevcrypto/Common.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 09bc3393b..139c0d943 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -151,7 +151,7 @@ public: { FixedHash ret; for (auto& i: ret.m_data) - i = std::uniform_int_distribution(0, 255)(_eng); + i = std::uniform_int_distribution(0, 255)(_eng); return ret; } diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index e45d1cfb6..e75623799 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -344,9 +344,9 @@ void Nonce::initialiseIfNeeded() { // todo: replace w/entropy from user and system std::mt19937_64 s_eng(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count()); - std::uniform_int_distribution d(0, 255); + std::uniform_int_distribution d(0, 255); for (unsigned i = 0; i < 32; ++i) - m_value[i] = byte(d(s_eng)); + m_value[i] = d(s_eng); } if (!m_value) BOOST_THROW_EXCEPTION(InvalidState()); From 98ad4c2454482a9198861d0de1e54d843442223b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 14:42:35 -0700 Subject: [PATCH 218/290] windows build fix. --- libdevcore/FixedHash.h | 1 + libdevcrypto/Common.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 139c0d943..5257ed333 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -24,6 +24,7 @@ #pragma once #include +#include #include #include #include "CommonData.h" diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index e75623799..6ff29988a 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -22,6 +22,7 @@ #include "Common.h" #include +#include #include #include #include From 9a01bb2b45fe7f7ee4ba23a41998e6bc89c9adfd Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 15:39:50 -0700 Subject: [PATCH 219/290] Enable the network in the case of explicitly disabled discovery. --- eth/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eth/main.cpp b/eth/main.cpp index 2a05311e7..f32eabbf0 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -1706,7 +1706,7 @@ int main(int argc, char** argv) cout << "Transaction Signer: " << signingKey << endl; cout << "Mining Benefactor: " << beneficiary << endl; - if (bootstrap || !remoteHost.empty()) + if (bootstrap || !remoteHost.empty() || disableDiscovery) { web3.startNetwork(); cout << "Node ID: " << web3.enode() << endl; From 54d2906a3b7bc9af1fe90bfce1ecb0c724938b73 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 10:32:16 -0700 Subject: [PATCH 220/290] Reorganise logs. --- libethereum/EthereumHost.cpp | 26 +++++++++++++++++--------- libethereum/EthereumHost.h | 2 ++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 186eb6fa8..f00ec7dc7 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -45,6 +45,12 @@ static unsigned const c_maxSendTransactions = 256; char const* const EthereumHost::s_stateNames[static_cast(SyncState::Size)] = {"Idle", "Waiting", "Hashes", "Blocks", "NewBlocks" }; +#ifdef _WIN32 +const char* EthereumHostTrace::name() { return EthPurple "^" EthGray " "; } +#else +const char* EthereumHostTrace::name() { return EthPurple "⧫" EthGray " "; } +#endif + EthereumHost::EthereumHost(BlockChain const& _ch, TransactionQueue& _tq, BlockQueue& _bq, u256 _networkId): HostCapability(), Worker ("ethsync"), @@ -67,7 +73,7 @@ bool EthereumHost::ensureInitialised() { // First time - just initialise. m_latestBlockSent = m_chain.currentHash(); - clog(NetNote) << "Initialising: latest=" << m_latestBlockSent; + clog(EthereumHostTrace) << "Initialising: latest=" << m_latestBlockSent; Guard l(x_transactions); m_transactionsSent = m_tq.knownTransactions(); @@ -150,7 +156,7 @@ void EthereumHost::maintainTransactions() RLPStream ts; _p->prep(ts, TransactionsPacket, n).appendRaw(b, n); _p->sealAndSend(ts); - cnote << "Sent" << n << "transactions to " << _p->session()->info().clientVersion; + clog(EthereumHostTrace) << "Sent" << n << "transactions to " << _p->session()->info().clientVersion; } _p->m_requireTransactions = false; return true; @@ -206,11 +212,15 @@ void EthereumHost::maintainBlocks(h256 const& _currentHash) if (diff(detailsFrom.number, detailsTo.number) < 20) { // don't be sending more than 20 "new" blocks. if there are any more we were probably waaaay behind. - clog(NetMessageSummary) << "Sending a new block (current is" << _currentHash << ", was" << m_latestBlockSent << ")"; + clog(EthereumHostTrace) << "Sending a new block (current is" << _currentHash << ", was" << m_latestBlockSent << ")"; h256s blocks = get<0>(m_chain.treeRoute(m_latestBlockSent, _currentHash, false, false, true)); - auto s = randomSelection(25, [&](EthereumPeer* p){ DEV_GUARDED(p->x_knownBlocks) return !p->m_knownBlocks.count(_currentHash); return false; }); + auto s = randomSelection(25, [&](EthereumPeer* p){ + DEV_GUARDED(p->x_knownBlocks) + return !p->m_knownBlocks.count(_currentHash); + return false; + }); for (shared_ptr const& p: get<0>(s)) for (auto const& b: blocks) { @@ -292,11 +302,11 @@ void EthereumHost::onPeerTransactions(std::shared_ptr _peer, RLP c { if (_peer->isCriticalSyncing()) { - clog(NetAllDetail) << "Ignoring transaction from peer we are syncing with"; + clog(EthereumHostTrace) << "Ignoring transaction from peer we are syncing with"; return; } unsigned itemCount = _r.itemCount(); - clog(NetAllDetail) << "Transactions (" << dec << itemCount << "entries)"; + clog(EthereumHostTrace) << "Transactions (" << dec << itemCount << "entries)"; m_tq.enqueue(_r, _peer->session()->id()); } @@ -351,10 +361,8 @@ void EthereumHost::onTransactionImported(ImportResult _ir, h256 const& _h, h512 break; case ImportResult::AlreadyKnown: // if we already had the transaction, then don't bother sending it on. - { - Guard l(x_transactions); + DEV_GUARDED(x_transactions) m_transactionsSent.insert(_h); - } peer->addRating(0); break; case ImportResult::Success: diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index b65ddb5d0..6cb82ebb4 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -49,6 +49,8 @@ class TransactionQueue; class BlockQueue; class BlockChainSync; +struct EthereumHostTrace: public LogChannel { static const char* name(); static const int verbosity = 6; }; + /** * @brief The EthereumHost class * @warning None of this is thread-safe. You have been warned. From f35358caa07cea05eb22444f17c27f7cc2dc03fc Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 13:04:30 -0700 Subject: [PATCH 221/290] Undo hard fork. --- libethereum/State.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 8ba3b438a..f50545d08 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -1212,7 +1212,6 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per uncommitToMine(); // OK - transaction looks valid - execute. - u256 startGasUsed = gasUsed(); #if ETH_PARANOIA ctrace << "Executing" << e.t() << "on" << h; ctrace << toHex(e.t().rlp()); @@ -1262,7 +1261,7 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per // Add to the user-originated transactions that we've executed. m_transactions.push_back(e.t()); - m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + (m_currentBlock.number >= 830000 ? e.gasUsedNoRefunds() : e.gasUsed()), e.logs())); + m_receipts.push_back(TransactionReceipt(rootHash(), e.gasUsed(), e.logs())); m_transactionSet.insert(e.t().sha3()); } From d7bd7594e57fe86c8d3509942de63c27f2da2714 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 13:09:25 -0700 Subject: [PATCH 222/290] Don't use PRNG for key generation! --- libdevcrypto/Common.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index 8bf95d02f..e45d1cfb6 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -262,16 +262,9 @@ bytes dev::scrypt(std::string const& _pass, bytes const& _salt, uint64_t _n, uin KeyPair KeyPair::create() { - static boost::thread_specific_ptr s_eng; - static unsigned s_id = 0; - if (!s_eng.get()) - s_eng.reset(new mt19937_64(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count() + ++s_id)); - - uniform_int_distribution d(0, 255); - for (int i = 0; i < 100; ++i) { - KeyPair ret(FixedHash<32>::random(*s_eng.get())); + KeyPair ret(FixedHash<32>::random()); if (ret.address()) return ret; } From 8d95fbe59c1e6575f22ed3a470ad83cb15787bc2 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 13:11:16 -0700 Subject: [PATCH 223/290] Better casting. --- libdevcore/FixedHash.h | 2 +- libdevcrypto/Common.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 09bc3393b..139c0d943 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -151,7 +151,7 @@ public: { FixedHash ret; for (auto& i: ret.m_data) - i = std::uniform_int_distribution(0, 255)(_eng); + i = std::uniform_int_distribution(0, 255)(_eng); return ret; } diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index e45d1cfb6..e75623799 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -344,9 +344,9 @@ void Nonce::initialiseIfNeeded() { // todo: replace w/entropy from user and system std::mt19937_64 s_eng(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count()); - std::uniform_int_distribution d(0, 255); + std::uniform_int_distribution d(0, 255); for (unsigned i = 0; i < 32; ++i) - m_value[i] = byte(d(s_eng)); + m_value[i] = d(s_eng); } if (!m_value) BOOST_THROW_EXCEPTION(InvalidState()); From 3024040ee8e5760dfb0a57097e62b84cd42a24f4 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 14:42:35 -0700 Subject: [PATCH 224/290] windows build fix. --- libdevcore/FixedHash.h | 1 + libdevcrypto/Common.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 139c0d943..5257ed333 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -24,6 +24,7 @@ #pragma once #include +#include #include #include #include "CommonData.h" diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index e75623799..6ff29988a 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -22,6 +22,7 @@ #include "Common.h" #include +#include #include #include #include From dbf49bbc494cc87be6721731a85516c9e526fcd0 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 15:37:58 -0700 Subject: [PATCH 225/290] Better visualisation of sync. --- alethzero/DownloadView.cpp | 82 ++++++++++++++++++++++++++++++---- alethzero/DownloadView.h | 12 ++--- alethzero/Main.ui | 4 +- alethzero/MainWin.cpp | 4 +- exp/main.cpp | 2 +- libdevcore/RangeMask.h | 14 ++++++ libethereum/BlockChainSync.cpp | 2 +- libethereum/DownloadMan.cpp | 10 +++++ libethereum/DownloadMan.h | 33 ++++++++------ 9 files changed, 130 insertions(+), 33 deletions(-) diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp index 210649edb..5112f961c 100644 --- a/alethzero/DownloadView.cpp +++ b/alethzero/DownloadView.cpp @@ -30,29 +30,95 @@ using namespace std; using namespace dev; using namespace dev::eth; -DownloadView::DownloadView(QWidget* _p): QWidget(_p) +SyncView::SyncView(QWidget* _p): QWidget(_p) { } -void DownloadView::paintEvent(QPaintEvent*) +void SyncView::paintEvent(QPaintEvent*) { QPainter p(this); - p.fillRect(rect(), Qt::white); - if (!m_man || m_man->chainEmpty() || !m_man->subCount()) + + if (!m_client) + return; + + DownloadMan const* man = m_client->downloadMan(); + BlockQueueStatus bqs = m_client->blockQueueStatus(); + SyncStatus sync = m_client->syncStatus(); + + unsigned syncFrom = m_client->numberFromHash(PendingBlockHash); + unsigned syncImported = syncFrom; + unsigned syncImporting = syncImported + bqs.importing; + unsigned syncVerified = syncImporting + bqs.verified; + unsigned syncVerifying = syncVerified + bqs.verifying; + unsigned syncUnverified = syncVerifying + bqs.unverified; + unsigned syncUnknown = syncUnverified + bqs.unknown; + + // best effort guess. assumes there's no forks. + unsigned downloadFrom = m_client->numberFromHash(m_client->isKnown(man->firstBlock()) ? man->firstBlock() : PendingBlockHash); + unsigned downloadCount = sync.blocksTotal; + DownloadMan::Overview overview = man->overview(); + unsigned downloadDone = downloadFrom + overview.total; + unsigned downloadFlank = downloadFrom + overview.firstIncomplete; + unsigned downloadPoint = downloadFrom + overview.lastComplete; + + unsigned hashFrom = sync.state == SyncState::Hashes ? m_client->numberFromHash(PendingBlockHash) : downloadFrom; + unsigned hashCount = sync.state == SyncState::Hashes ? sync.hashesTotal : downloadCount; + unsigned hashDone = hashFrom + (sync.state == SyncState::Hashes ? sync.hashesReceived : hashCount); + + m_lastFrom = min(syncFrom, m_lastFrom); + unsigned from = min(min(hashFrom, downloadFrom), min(syncFrom, m_lastFrom)); + unsigned count = max(hashFrom + hashCount, downloadFrom + downloadCount) - from; + m_lastFrom = (m_lastFrom * 95 + syncFrom) / 100; + + if (!count) + { + m_lastFrom = (unsigned)-1; return; + } + + cnote << "Range " << from << "-" << (from + count); + auto r = [&](unsigned u) { + return toString((u - from) * 100 / count) + "%"; + }; + + if (count) + { + cnote << "Hashes:" << r(hashDone) << " Blocks:" << r(downloadFlank) << r(downloadDone) << r(downloadPoint); + cnote << "Importing:" << r(syncFrom) << r(syncImported) << r(syncImporting) << r(syncVerified) << r(syncVerifying) << r(syncUnverified) << r(syncUnknown); + } + + if (!man || man->chainEmpty() || !man->subCount()) + return; + + float s = min(rect().width(), rect().height()); + QPen pen; + pen.setCapStyle(Qt::FlatCap); + pen.setWidthF(s / 10); + p.setPen(pen); + auto middle = [&](float x) { + return QRectF(s / 2 - s / 2 * x, 0 + s / 2 - s / 2 * x, s * x, s * x); + }; + + auto toArc = [&](unsigned x) { + return (x - from) * -5760.f / count; + }; + const float arcFrom = 90 * 16.f; + p.drawArc(middle(0.5f), arcFrom, toArc(downloadDone)); + p.drawPie(middle(0.2f), arcFrom, toArc(hashDone)); + return; double ratio = (double)rect().width() / rect().height(); if (ratio < 1) ratio = 1 / ratio; - double n = min(16.0, min(rect().width(), rect().height()) / ceil(sqrt(m_man->chainSize() / ratio))); + double n = min(16.0, min(rect().width(), rect().height()) / ceil(sqrt(man->chainSize() / ratio))); // QSizeF area(rect().width() / floor(rect().width() / n), rect().height() / floor(rect().height() / n)); QSizeF area(n, n); QPointF pos(0, 0); - auto bg = m_man->blocksGot(); - unsigned subCount = m_man->subCount(); + auto bg = man->blocksGot(); + unsigned subCount = man->subCount(); if (subCount == 0) return; unsigned dh = 360 / subCount; @@ -64,7 +130,7 @@ void DownloadView::paintEvent(QPaintEvent*) else { unsigned h = 0; - m_man->foreachSub([&](DownloadSub const& sub) + man->foreachSub([&](DownloadSub const& sub) { if (sub.askedContains(i)) s = h; diff --git a/alethzero/DownloadView.h b/alethzero/DownloadView.h index d0fc445f8..9ee2428b2 100644 --- a/alethzero/DownloadView.h +++ b/alethzero/DownloadView.h @@ -32,21 +32,23 @@ #endif namespace dev { namespace eth { -class DownloadMan; +class Client; }} -class DownloadView: public QWidget +class SyncView: public QWidget { Q_OBJECT public: - DownloadView(QWidget* _p = nullptr); + SyncView(QWidget* _p = nullptr); - void setDownloadMan(dev::eth::DownloadMan const* _man) { m_man = _man; } + void setEthereum(dev::eth::Client const* _c) { m_client = _c; } protected: virtual void paintEvent(QPaintEvent*); private: - dev::eth::DownloadMan const* m_man = nullptr; + dev::eth::Client const* m_client = nullptr; + + unsigned m_lastFrom = (unsigned)-1; }; diff --git a/alethzero/Main.ui b/alethzero/Main.ui index b2e3a9a29..37ff7f66c 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -1149,7 +1149,7 @@ font-size: 14pt 0 - + @@ -1814,7 +1814,7 @@ font-size: 14pt 1 - DownloadView + SyncView QWidget
DownloadView.h
1 diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index bc569c5cf..ba4bec863 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1993,12 +1993,12 @@ void Main::on_net_triggered() web3()->setNetworkPreferences(netPrefs(), ui->dropPeers->isChecked()); ethereum()->setNetworkId(m_privateChain.size() ? sha3(m_privateChain.toStdString()) : h256()); web3()->startNetwork(); - ui->downloadView->setDownloadMan(ethereum()->downloadMan()); + ui->downloadView->setEthereum(ethereum()); ui->enode->setText(QString::fromStdString(web3()->enode())); } else { - ui->downloadView->setDownloadMan(nullptr); + ui->downloadView->setEthereum(nullptr); writeSettings(); web3()->stopNetwork(); } diff --git a/exp/main.cpp b/exp/main.cpp index 1db9b4267..88608f8cf 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -135,7 +135,7 @@ int main() DownloadSub s0(man); DownloadSub s1(man); DownloadSub s2(man); - man.resetToChain(h256s({u256(0), u256(1), u256(2), u256(3), u256(4), u256(5), u256(6), u256(7), u256(8)})); + man.resetToChain(h256s({u256(0), u256(1), u256(2), u256(3), u256(4), u256(5), u256(6), u256(7), u256(8)}), 0); assert((s0.nextFetch(2) == h256Set{(u256)7, (u256)8})); assert((s1.nextFetch(2) == h256Set{(u256)5, (u256)6})); assert((s2.nextFetch(2) == h256Set{(u256)3, (u256)4})); diff --git a/libdevcore/RangeMask.h b/libdevcore/RangeMask.h index eccc8305d..6c32517f5 100644 --- a/libdevcore/RangeMask.h +++ b/libdevcore/RangeMask.h @@ -200,6 +200,20 @@ public: return c; } + size_t firstOut() const + { + if (m_ranges.empty() || !m_ranges.count(m_all.first)) + return m_all.first; + return m_ranges.at(m_all.first); + } + + size_t lastIn() const + { + if (m_ranges.empty()) + return m_all.first; + return m_ranges.rbegin()->second - 1; + } + private: /// The ground range. UnsignedRange m_all; diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index e22f10880..5dd1a97cb 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -80,7 +80,7 @@ DownloadMan& BlockChainSync::downloadMan() void BlockChainSync::abortSync() { - downloadMan().resetToChain(h256s()); + downloadMan().reset(); } void BlockChainSync::onPeerStatus(std::shared_ptr _peer) diff --git a/libethereum/DownloadMan.cpp b/libethereum/DownloadMan.cpp index 5e68e3c49..a9d353292 100644 --- a/libethereum/DownloadMan.cpp +++ b/libethereum/DownloadMan.cpp @@ -24,6 +24,16 @@ using namespace std; using namespace dev; using namespace dev::eth; +DownloadMan::Overview DownloadMan::overview() const +{ + ReadGuard l(m_lock); + Overview ret; + ret.firstIncomplete = m_blocksGot.firstOut(); + ret.lastComplete = ret.lastStarted = m_blocksGot.lastIn();// TODO: lastStarted properly + ret.total = m_blocksGot.size(); + return ret; +} + DownloadSub::DownloadSub(DownloadMan& _man): m_man(&_man) { WriteGuard l(m_man->x_subs); diff --git a/libethereum/DownloadMan.h b/libethereum/DownloadMan.h index ac99e1d36..b697d87ae 100644 --- a/libethereum/DownloadMan.h +++ b/libethereum/DownloadMan.h @@ -82,6 +82,14 @@ class DownloadMan friend class DownloadSub; public: + struct Overview + { + size_t total; + size_t firstIncomplete; + size_t lastComplete; + size_t lastStarted; + }; + ~DownloadMan() { for (auto i: m_subs) @@ -97,11 +105,9 @@ public: void resetToChain(h256s const& _chain) { - { - ReadGuard l(x_subs); + DEV_READ_GUARDED(x_subs) for (auto i: m_subs) i->resetFetch(); - } WriteGuard l(m_lock); m_chain.clear(); m_chain.reserve(_chain.size()); @@ -112,11 +118,9 @@ public: void reset() { - { - ReadGuard l(x_subs); + DEV_READ_GUARDED(x_subs) for (auto i: m_subs) i->resetFetch(); - } WriteGuard l(m_lock); m_chain.clear(); m_blocksGot.reset(); @@ -127,11 +131,9 @@ public: ReadGuard l(m_lock); auto ret = m_blocksGot; if (!_desperate) - { - ReadGuard l(x_subs); - for (auto i: m_subs) - ret += i->m_asked; - } + DEV_READ_GUARDED(x_subs) + for (auto i: m_subs) + ret += i->m_asked; return ret; } @@ -144,12 +146,15 @@ public: h256s remaining() const { h256s ret; - ReadGuard l(m_lock); - for (auto i: m_blocksGot.inverted()) - ret.push_back(m_chain[i]); + DEV_READ_GUARDED(m_lock) + for (auto i: m_blocksGot.inverted()) + ret.push_back(m_chain[i]); return ret; } + h256 firstBlock() const { return m_chain.empty() ? h256() : m_chain[0]; } + Overview overview() const; + size_t chainSize() const { ReadGuard l(m_lock); return m_chain.size(); } size_t chainEmpty() const { ReadGuard l(m_lock); return m_chain.empty(); } void foreachSub(std::function const& _f) const { ReadGuard l(x_subs); for(auto i: m_subs) _f(*i); } From 1927b021ab8713b42cfdb2e3011bb1c577a6ee66 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Wed, 8 Jul 2015 03:31:53 +0200 Subject: [PATCH 226/290] update canary address --- libethereum/Client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index fba8d51fa..2295904cc 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -67,7 +67,7 @@ static const Addresses c_canaries = Address("4bb7e8ae99b645c2b7860b8f3a2328aae28bd80a"), // gav Address("1baf27b88c48dd02b744999cf3522766929d2b2a"), // vitalik Address("a8edb1ac2c86d3d9d78f96cd18001f60df29e52c"), // jeff - Address("60d11b58744784dc97f878f7e3749c0f1381a004") // christoph + Address("ace7813896a84d3f5f80223916a5353ab16e46e6") // christoph }; VersionChecker::VersionChecker(string const& _dbPath) From f2fdd8fb32276b1c58ab8fe90b8597269cb15e90 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 18:41:07 -0700 Subject: [PATCH 227/290] Nicer import graph. --- alethzero/DownloadView.cpp | 59 ++++++++++++++++++++++++++------------ alethzero/DownloadView.h | 1 + alethzero/Main.ui | 6 ++++ alethzero/MainWin.cpp | 11 +++++++ alethzero/MainWin.h | 1 + libethereum/BlockChain.cpp | 22 +++++++++++++- libethereum/BlockChain.h | 3 ++ libethereum/BlockQueue.cpp | 4 ++- libethereum/Client.h | 2 ++ libethereum/State.cpp | 3 +- 10 files changed, 91 insertions(+), 21 deletions(-) diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp index 5112f961c..046b8973a 100644 --- a/alethzero/DownloadView.cpp +++ b/alethzero/DownloadView.cpp @@ -52,7 +52,7 @@ void SyncView::paintEvent(QPaintEvent*) unsigned syncVerified = syncImporting + bqs.verified; unsigned syncVerifying = syncVerified + bqs.verifying; unsigned syncUnverified = syncVerifying + bqs.unverified; - unsigned syncUnknown = syncUnverified + bqs.unknown; + unsigned syncCount = syncUnverified + bqs.unknown - syncFrom; // best effort guess. assumes there's no forks. unsigned downloadFrom = m_client->numberFromHash(m_client->isKnown(man->firstBlock()) ? man->firstBlock() : PendingBlockHash); @@ -67,17 +67,19 @@ void SyncView::paintEvent(QPaintEvent*) unsigned hashDone = hashFrom + (sync.state == SyncState::Hashes ? sync.hashesReceived : hashCount); m_lastFrom = min(syncFrom, m_lastFrom); + m_lastTo = max(max(syncFrom + syncCount, hashFrom + hashCount), m_lastTo); unsigned from = min(min(hashFrom, downloadFrom), min(syncFrom, m_lastFrom)); - unsigned count = max(hashFrom + hashCount, downloadFrom + downloadCount) - from; - m_lastFrom = (m_lastFrom * 95 + syncFrom) / 100; + unsigned count = max(max(hashFrom + hashCount, downloadFrom + downloadCount), max(syncFrom + syncCount, m_lastTo)) - from; + m_lastFrom = (m_lastFrom * 99 + syncFrom * 1) / 100; + m_lastTo = (m_lastTo * 99 + max(syncFrom + syncCount, hashFrom + hashCount) * 1) / 100; if (!count) { - m_lastFrom = (unsigned)-1; + m_lastFrom = m_lastTo = (unsigned)-1; return; } - cnote << "Range " << from << "-" << (from + count); + cnote << "Range " << from << "-" << (from + count) << "(" << hashFrom << "+" << hashCount << "," << downloadFrom << "+" << downloadCount << "," << syncFrom << "+" << syncCount << ")"; auto r = [&](unsigned u) { return toString((u - from) * 100 / count) + "%"; }; @@ -85,27 +87,48 @@ void SyncView::paintEvent(QPaintEvent*) if (count) { cnote << "Hashes:" << r(hashDone) << " Blocks:" << r(downloadFlank) << r(downloadDone) << r(downloadPoint); - cnote << "Importing:" << r(syncFrom) << r(syncImported) << r(syncImporting) << r(syncVerified) << r(syncVerifying) << r(syncUnverified) << r(syncUnknown); + cnote << "Importing:" << r(syncFrom) << r(syncImported) << r(syncImporting) << r(syncVerified) << r(syncVerifying) << r(syncUnverified); } - if (!man || man->chainEmpty() || !man->subCount()) - return; - - float s = min(rect().width(), rect().height()); + float squareSize = min(rect().width(), rect().height()); QPen pen; pen.setCapStyle(Qt::FlatCap); - pen.setWidthF(s / 10); - p.setPen(pen); + pen.setWidthF(squareSize / 20); auto middle = [&](float x) { - return QRectF(s / 2 - s / 2 * x, 0 + s / 2 - s / 2 * x, s * x, s * x); + return QRectF(squareSize / 2 - squareSize / 2 * x, 0 + squareSize / 2 - squareSize / 2 * x, squareSize * x, squareSize * x); + }; + + auto arcLen = [&](unsigned x) { + return x * -5760.f / count; + }; + auto arcPos = [&](unsigned x) { + return int(90 * 16.f + arcLen(x - from)) % 5760; }; - auto toArc = [&](unsigned x) { - return (x - from) * -5760.f / count; + p.setPen(Qt::NoPen); + p.setBrush(QColor::fromHsv(0, 0, 210)); + pen.setWidthF(0.f); + p.drawPie(middle(0.4f), arcPos(from), arcLen(hashDone - from)); + + auto progress = [&](unsigned h, unsigned s, unsigned v, float size, float thickness, unsigned nfrom, unsigned ncount) { + p.setBrush(Qt::NoBrush); + pen.setColor(QColor::fromHsv(h, s, v)); + pen.setWidthF(squareSize * thickness); + p.setPen(pen); + p.drawArc(middle(size), arcPos(nfrom), arcLen(ncount)); }; - const float arcFrom = 90 * 16.f; - p.drawArc(middle(0.5f), arcFrom, toArc(downloadDone)); - p.drawPie(middle(0.2f), arcFrom, toArc(hashDone)); + + progress(0, 50, 170, 0.4f, 0.12f, downloadFlank, downloadPoint - downloadFlank); + progress(0, 0, 150, 0.4f, 0.10f, from, downloadDone - from); + + progress(0, 0, 230, 0.7f, 0.090f, from, syncUnverified - from); + progress(60, 25, 210, 0.7f, 0.08f, from, syncVerifying - from); + progress(120, 25, 190, 0.7f, 0.07f, from, syncVerified - from); + + progress(0, 0, 220, 0.9f, 0.02f, from, count); + progress(0, 0, 100, 0.9f, 0.04f, from, syncFrom - from); + progress(0, 50, 100, 0.9f, 0.08f, syncFrom, syncImporting - syncFrom); + return; double ratio = (double)rect().width() / rect().height(); diff --git a/alethzero/DownloadView.h b/alethzero/DownloadView.h index 9ee2428b2..71fc41f3f 100644 --- a/alethzero/DownloadView.h +++ b/alethzero/DownloadView.h @@ -51,4 +51,5 @@ private: dev::eth::Client const* m_client = nullptr; unsigned m_lastFrom = (unsigned)-1; + unsigned m_lastTo = (unsigned)-1; }; diff --git a/alethzero/Main.ui b/alethzero/Main.ui index 37ff7f66c..97853e174 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -199,6 +199,7 @@ + @@ -1804,6 +1805,11 @@ font-size: 14pt &Sentinel... + + + &Rewind Chain... + + diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index ba4bec863..60c07fd8d 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1044,6 +1044,17 @@ void Main::on_vmInterpreter_triggered() { VMFactory::setKind(VMKind::Interpreter void Main::on_vmJIT_triggered() { VMFactory::setKind(VMKind::JIT); } void Main::on_vmSmart_triggered() { VMFactory::setKind(VMKind::Smart); } +void Main::on_rewindChain_triggered() +{ + bool ok; + int n = QInputDialog::getInt(this, "Rewind Chain", "Enter the number of the new chain head.", ethereum()->number() * 9 / 10, 1, ethereum()->number(), 1, &ok); + if (ok) + { + ethereum()->rewind(n); + refreshAll(); + } +} + void Main::on_urlEdit_returnPressed() { QString s = ui->urlEdit->text(); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index b1939534b..0e944b042 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -187,6 +187,7 @@ private slots: void on_vmInterpreter_triggered(); void on_vmJIT_triggered(); void on_vmSmart_triggered(); + void on_rewindChain_triggered(); // Debugger void on_debugCurrent_triggered(); diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index bf4eaf4d0..719ec016e 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -799,6 +799,25 @@ void BlockChain::clearBlockBlooms(unsigned _begin, unsigned _end) } } +void BlockChain::rewind(unsigned _newHead) +{ + DEV_WRITE_GUARDED(x_lastBlockHash) + { + if (_newHead >= m_lastBlockNumber) + return; + m_lastBlockHash = numberHash(_newHead); + m_lastBlockNumber = _newHead; + auto o = m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&m_lastBlockHash, 32)); + if (!o.ok()) + { + cwarn << "Error writing to extras database: " << o.ToString(); + cout << "Put" << toHex(bytesConstRef(ldb::Slice("best"))) << "=>" << toHex(bytesConstRef(ldb::Slice((char const*)&m_lastBlockHash, 32))); + cwarn << "Fail writing to extras database. Bombing out."; + exit(-1); + } + } +} + tuple BlockChain::treeRoute(h256 const& _from, h256 const& _to, bool _common, bool _pre, bool _post) const { // cdebug << "treeRoute" << _from << "..." << _to; @@ -1070,7 +1089,8 @@ bool BlockChain::isKnown(h256 const& _hash) const if (d.empty()) return false; } - return true; +// return true; + return details(_hash).number <= m_lastBlockNumber; // to allow rewind functionality. } bytes BlockChain::block(h256 const& _hash) const diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index 4cffca2df..1d88430b0 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -215,6 +215,9 @@ public: /// Will call _progress with the progress in this operation first param done, second total. void rebuild(std::string const& _path, ProgressCallback const& _progress = std::function(), bool _prepPoW = false); + /// Alter the head of the chain to some prior block along it. + void rewind(unsigned _newHead); + /** @returns a tuple of: * - an vector of hashes of all blocks between @a _from and @a _to, all blocks are ordered first by a number of * blocks that are parent-to-child, then two sibling blocks, then a number of blocks that are child-to-parent; diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index 5e0a523d8..f95a3880e 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -215,8 +215,10 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo return ImportResult::Malformed; } + clog(BlockQueueTraceChannel) << "Block" << h << "is" << bi.number << "parent is" << bi.parentHash; + // Check block doesn't already exist first! - if (_bc.details(h)) + if (_bc.isKnown(h)) { cblockq << "Already known in chain."; return ImportResult::AlreadyInChain; diff --git a/libethereum/Client.h b/libethereum/Client.h index 829ec77c1..fac54b010 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -217,6 +217,8 @@ public: std::string const& sentinel() const { return m_sentinel; } /// Set the extra data that goes into mined blocks. void setExtraData(bytes const& _extraData) { m_extraData = _extraData; } + /// Rewind to a prior head. + void rewind(unsigned _n) { m_bc.rewind(_n); } protected: /// InterfaceStub methods diff --git a/libethereum/State.cpp b/libethereum/State.cpp index f50545d08..10d637509 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -1212,6 +1212,7 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per uncommitToMine(); // OK - transaction looks valid - execute. + u256 startGasUsed = gasUsed(); #if ETH_PARANOIA ctrace << "Executing" << e.t() << "on" << h; ctrace << toHex(e.t().rlp()); @@ -1261,7 +1262,7 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per // Add to the user-originated transactions that we've executed. m_transactions.push_back(e.t()); - m_receipts.push_back(TransactionReceipt(rootHash(), e.gasUsed(), e.logs())); + m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + e.gasUsed(), e.logs())); m_transactionSet.insert(e.t().sha3()); } From d7357c8059116b6d6cdfcc50e5900ba0ac66f42f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 19:01:52 -0700 Subject: [PATCH 228/290] pair up hash with Address for transaction submission API. --- libethereum/ClientBase.cpp | 4 ++-- libethereum/ClientBase.h | 2 +- libethereum/Interface.cpp | 3 +-- libethereum/Interface.h | 2 +- libweb3jsonrpc/AccountHolder.cpp | 4 ++-- mix/ClientModel.cpp | 3 +-- mix/MixClient.cpp | 4 ++-- mix/MixClient.h | 4 ++-- neth/main.cpp | 2 -- 9 files changed, 12 insertions(+), 16 deletions(-) diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 2cef62680..f463b0195 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -45,7 +45,7 @@ State ClientBase::asOf(BlockNumber _h) const return asOf(bc().numberHash(_h)); } -h256 ClientBase::submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) +pair ClientBase::submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) { prepareForTransaction(); @@ -59,7 +59,7 @@ h256 ClientBase::submitTransaction(TransactionSkeleton const& _t, Secret const& StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged()); cnote << "New transaction " << t; - return t.sha3(); + return make_pair(t.sha3(), toAddress(ts.from, ts.nonce)); } // TODO: remove try/catch, allow exceptions diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index 05766b3a1..82f03def0 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -77,7 +77,7 @@ public: /// Submits the given transaction. /// @returns the new transaction's hash. - virtual h256 submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) override; + virtual std::pair submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) override; using Interface::submitTransaction; /// Makes the given call. Nothing is recorded into the state. diff --git a/libethereum/Interface.cpp b/libethereum/Interface.cpp index efa304bd5..e95e03a45 100644 --- a/libethereum/Interface.cpp +++ b/libethereum/Interface.cpp @@ -46,6 +46,5 @@ Address Interface::submitTransaction(Secret const& _secret, u256 const& _endowme ts.gas = _gas; ts.gasPrice = _gasPrice; ts.nonce = _nonce; - submitTransaction(ts, _secret); - return toAddress(toAddress(_secret), _nonce); + return submitTransaction(ts, _secret).second; } diff --git a/libethereum/Interface.h b/libethereum/Interface.h index c65670a30..973433af9 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -67,7 +67,7 @@ public: /// Submits a new transaction. /// @returns the transaction's hash. - virtual h256 submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) = 0; + virtual std::pair submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) = 0; /// Submits the given message-call transaction. void submitTransaction(Secret const& _secret, u256 const& _value, Address const& _dest, bytes const& _data = bytes(), u256 const& _gas = 10000, u256 const& _gasPrice = 10 * szabo, u256 const& _nonce = UndefinedU256); diff --git a/libweb3jsonrpc/AccountHolder.cpp b/libweb3jsonrpc/AccountHolder.cpp index f4b3a9f9f..43a7073d2 100644 --- a/libweb3jsonrpc/AccountHolder.cpp +++ b/libweb3jsonrpc/AccountHolder.cpp @@ -109,7 +109,7 @@ AddressHash SimpleAccountHolder::realAccounts() const h256 SimpleAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t) { if (isRealAccount(_t.from)) - return m_client()->submitTransaction(_t, m_keyManager.secret(_t.from, [&](){ return m_getPassword(_t.from); })); + return m_client()->submitTransaction(_t, m_keyManager.secret(_t.from, [&](){ return m_getPassword(_t.from); })).first; else if (isProxyAccount(_t.from)) queueTransaction(_t); return h256(); @@ -118,7 +118,7 @@ h256 SimpleAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t) h256 FixedAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t) { if (isRealAccount(_t.from)) - return m_client()->submitTransaction(_t, m_accounts[_t.from]); + return m_client()->submitTransaction(_t, m_accounts[_t.from]).first; else if (isProxyAccount(_t.from)) queueTransaction(_t); return h256(); diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index eae3f8834..90ff19feb 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -674,8 +674,7 @@ void ClientModel::debugRecord(unsigned _index) Address ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction) { - Address newAddress = m_client->submitTransaction(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice, _ctrTransaction.gasAuto); - return newAddress; + return m_client->submitTransaction(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice, _ctrTransaction.gasAuto); } void ClientModel::callAddress(Address const& _contract, bytes const& _data, TransactionSettings const& _tr) diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 7978ff1ac..c73763076 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -303,14 +303,14 @@ State MixClient::asOf(h256 const& _block) const return ret; } -h256 MixClient::submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto) +pair MixClient::submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto) { WriteGuard l(x_state); TransactionSkeleton ts = _ts; ts.nonce = m_state.transactionsFrom(toAddress(_secret)); eth::Transaction t(ts, _secret); executeTransaction(t, m_state, false, _gasAuto, _secret); - return t.sha3(); + return make_pair(t.sha3(), toAddress(ts.from, ts.nonce)); } dev::eth::ExecutionResult MixClient::call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto, FudgeFactor _ff) diff --git a/mix/MixClient.h b/mix/MixClient.h index e4ad9c133..748dd1cdc 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -58,8 +58,8 @@ public: dev::eth::ExecutionResult create(Address const& _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * eth::szabo, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override; using ClientBase::submitTransaction; - virtual h256 submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret) override { return submitTransaction(_ts, _secret, false); } - h256 submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto); + virtual std::pair submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret) override { return submitTransaction(_ts, _secret, false); } + std::pair submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto); dev::eth::ExecutionResult call(Address const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber, bool _gasAuto, eth::FudgeFactor _ff = eth::FudgeFactor::Strict); void setAddress(Address _us) override; diff --git a/neth/main.cpp b/neth/main.cpp index d5cb4bb4b..5ec253440 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -1057,9 +1057,7 @@ int main(int argc, char** argv) else if (gas < minGas) cwarn << "Minimum gas amount is" << minGas; else - { c->submitTransaction(us.secret(), endowment, init, gas); - } } } else if (c && cmd == "inspect") From 464c60145ed15d031897828ff4964e2b56da9ab2 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 19:06:54 -0700 Subject: [PATCH 229/290] Fix up the windows build. --- libdevcore/FixedHash.h | 2 +- libdevcrypto/Common.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 5257ed333..a9922063a 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -152,7 +152,7 @@ public: { FixedHash ret; for (auto& i: ret.m_data) - i = std::uniform_int_distribution(0, 255)(_eng); + i = (uint8_t)std::uniform_int_distribution(0, 255)(_eng); return ret; } diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index 6ff29988a..186c6ce06 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -345,9 +345,9 @@ void Nonce::initialiseIfNeeded() { // todo: replace w/entropy from user and system std::mt19937_64 s_eng(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count()); - std::uniform_int_distribution d(0, 255); + std::uniform_int_distribution d(0, 255); for (unsigned i = 0; i < 32; ++i) - m_value[i] = d(s_eng); + m_value[i] = (uint8_t)d(s_eng); } if (!m_value) BOOST_THROW_EXCEPTION(InvalidState()); From f9143270503ed9be48cf4362858c35521a93f7e3 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 8 Jul 2015 09:46:54 +0200 Subject: [PATCH 230/290] Restore the old default value of global work size It used to be 64 (local size) * 4096 (global multiplier). Miners reported a lot better results with those old defaults and as such we are bringing them back. --- libethash-cl/ethash_cl_miner.h | 2 +- libethcore/Ethash.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h index 8f7594be5..d1cb53ef9 100644 --- a/libethash-cl/ethash_cl_miner.h +++ b/libethash-cl/ethash_cl_miner.h @@ -20,7 +20,7 @@ class ethash_cl_miner { private: - enum { c_maxSearchResults = 63, c_bufferCount = 2, c_hashBatchSize = 1024, c_searchBatchSize = 1024 * 16 }; + enum { c_maxSearchResults = 63, c_bufferCount = 2, c_hashBatchSize = 1024 }; public: struct search_hook diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 9ec6dd71f..d24c8454e 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -55,7 +55,7 @@ namespace eth { const unsigned Ethash::defaultLocalWorkSize = 64; -const unsigned Ethash::defaultGlobalWorkSizeMultiplier = 512; // * CL_DEFAULT_LOCAL_WORK_SIZE +const unsigned Ethash::defaultGlobalWorkSizeMultiplier = 4096; // * CL_DEFAULT_LOCAL_WORK_SIZE const unsigned Ethash::defaultMSPerBatch = 0; const Ethash::WorkPackage Ethash::NullWorkPackage = Ethash::WorkPackage(); From f5b0c7cdce515724cf3856f58457029a1a693361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 8 Jul 2015 11:56:38 +0200 Subject: [PATCH 231/290] Increase Windows stack size to 16MB. (reverted from commit 8357930b25e5e4914d84eba507b7d94885ff5966) --- cmake/EthCompilerSettings.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 6701cf824..5fcb7d353 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -47,9 +47,10 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") add_compile_options(/MP /EHsc /wd4068 /wd4996 /wd4503 /wd4267 /wd4180 /wd4290 /wd4244 /wd4800 -D_WIN32_WINNT=0x0501 /DNOMINMAX /DMINIUPNP_STATICLIB) # disable empty object file warning set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221") - # warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/SAFESEH' specification + # warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/SAFESEH' specification # warning LNK4099: pdb was not found with lib - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ignore:4099,4075") + # stack size 16MB + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ignore:4099,4075 /STACK:16777216") # windows likes static if (NOT ETH_STATIC) From cd354c183132f4da497d362182c9783d94cf4c37 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Wed, 8 Jul 2015 12:19:50 +0200 Subject: [PATCH 232/290] FixedHash::operator++() --- libwhisper/BloomFilter.h | 4 ++-- libwhisper/Message.cpp | 4 +--- libwhisper/Message.h | 1 - 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/libwhisper/BloomFilter.h b/libwhisper/BloomFilter.h index 32ac15043..02cc80505 100644 --- a/libwhisper/BloomFilter.h +++ b/libwhisper/BloomFilter.h @@ -88,7 +88,7 @@ template bool TopicBloomFilterBase::isBitSet(FixedHash const& _h, unsigned _index) { unsigned iByte = _index / 8; - unsigned iBit = _index & 0x7; + unsigned iBit = _index % 8; return (_h[iByte] & c_powerOfTwoBitMmask[iBit]) != 0; } @@ -96,7 +96,7 @@ template void TopicBloomFilterBase::setBit(FixedHash& _h, unsigned _index) { unsigned iByte = _index / 8; - unsigned iBit = _index & 0x7; + unsigned iBit = _index % 8; _h[iByte] |= c_powerOfTwoBitMmask[iBit]; } diff --git a/libwhisper/Message.cpp b/libwhisper/Message.cpp index 435811a3b..dd72ff734 100644 --- a/libwhisper/Message.cpp +++ b/libwhisper/Message.cpp @@ -170,7 +170,7 @@ void Envelope::proveWork(unsigned _ms) chrono::high_resolution_clock::time_point then = chrono::high_resolution_clock::now() + chrono::milliseconds(_ms); while (chrono::high_resolution_clock::now() < then) // do it rounds of 1024 for efficiency - for (unsigned i = 0; i < 1024; ++i) + for (unsigned i = 0; i < 1024; ++i, ++d[1]) { auto fbs = dev::sha3(chuck).firstBitSet(); if (fbs > bestBitSet) @@ -178,8 +178,6 @@ void Envelope::proveWork(unsigned _ms) bestBitSet = fbs; m_nonce = (h256::Arith)d[1]; } - - incrementHash(d[1]); } } diff --git a/libwhisper/Message.h b/libwhisper/Message.h index fb89576e9..ae61f210a 100644 --- a/libwhisper/Message.h +++ b/libwhisper/Message.h @@ -81,7 +81,6 @@ public: void proveWork(unsigned _ms); bool matchesBloomFilter(TopicBloomFilterHash const& f) const; - static void incrementHash(h256& _h) { for (unsigned i = h256::size; i > 0 && !++_h[--i]; ) {} } private: Envelope(unsigned _exp, unsigned _ttl, AbridgedTopics const& _topic): m_expiry(_exp), m_ttl(_ttl), m_topic(_topic) {} From 0236886d3ef90c12431b1ffe8f413cc1c569b967 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 8 Jul 2015 13:14:21 +0200 Subject: [PATCH 233/290] bug fix. issue while getting the created contract address. --- mix/ClientModel.cpp | 8 ++++---- mix/ClientModel.h | 2 +- mix/MixClient.cpp | 6 ++++++ mix/MixClient.h | 3 +++ 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index eae3f8834..e7e8811a3 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -390,7 +390,8 @@ void ClientModel::executeSequence(vector const& _sequence) { bytes param = encoder.encodedData(); contractCode.insert(contractCode.end(), param.begin(), param.end()); - Address newAddress = deployContract(contractCode, transaction); + deployContract(contractCode, transaction); + Address newAddress = m_client->lastCreatedContractAddr(); std::pair contractToken = retrieveToken(transaction.contractId); m_contractAddresses[contractToken] = newAddress; m_contractNames[newAddress] = contractToken.first; @@ -672,10 +673,9 @@ void ClientModel::debugRecord(unsigned _index) showDebuggerForTransaction(e); } -Address ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction) +void ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction) { - Address newAddress = m_client->submitTransaction(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice, _ctrTransaction.gasAuto); - return newAddress; + m_client->submitTransaction(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice, _ctrTransaction.gasAuto); } void ClientModel::callAddress(Address const& _contract, bytes const& _data, TransactionSettings const& _tr) diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 92f06b48b..66a14ad5b 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -252,7 +252,7 @@ private: QVariantMap contractAddresses() const; QVariantList gasCosts() const; void executeSequence(std::vector const& _sequence); - dev::Address deployContract(bytes const& _code, TransactionSettings const& _tr = TransactionSettings()); + void deployContract(bytes const& _code, TransactionSettings const& _tr = TransactionSettings()); void callAddress(Address const& _contract, bytes const& _data, TransactionSettings const& _tr); void onNewTransaction(); void onStateReset(); diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 7978ff1ac..c41661046 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -313,6 +313,12 @@ h256 MixClient::submitTransaction(eth::TransactionSkeleton const& _ts, Secret co return t.sha3(); } +Address MixClient::lastCreatedContractAddr() const +{ + Transaction tr = m_state.pending().back(); + return tr.isCreation() ? right160(sha3(rlpList(tr.sender(), tr.nonce()))) : Address(); +} + dev::eth::ExecutionResult MixClient::call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto, FudgeFactor _ff) { (void)_blockNumber; diff --git a/mix/MixClient.h b/mix/MixClient.h index e4ad9c133..5b1b155a1 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -76,6 +76,9 @@ public: using Interface::blockInfo; // to remove warning about hiding virtual function eth::BlockInfo blockInfo() const; + /// return the new address generated by the last tr (if creation). returns empty address if other cases. + Address lastCreatedContractAddr() const; + protected: /// ClientBase methods using ClientBase::asOf; From 9f164af459ff5c299c70d6965b2f5ab682817784 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 8 Jul 2015 14:12:35 +0200 Subject: [PATCH 234/290] small changes --- mix/ClientModel.cpp | 6 +++--- mix/ClientModel.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index e7e8811a3..23f68996c 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -390,8 +390,7 @@ void ClientModel::executeSequence(vector const& _sequence) { bytes param = encoder.encodedData(); contractCode.insert(contractCode.end(), param.begin(), param.end()); - deployContract(contractCode, transaction); - Address newAddress = m_client->lastCreatedContractAddr(); + Address newAddress = deployContract(contractCode, transaction); std::pair contractToken = retrieveToken(transaction.contractId); m_contractAddresses[contractToken] = newAddress; m_contractNames[newAddress] = contractToken.first; @@ -673,9 +672,10 @@ void ClientModel::debugRecord(unsigned _index) showDebuggerForTransaction(e); } -void ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction) +Address ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction) { m_client->submitTransaction(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice, _ctrTransaction.gasAuto); + return m_client->lastCreatedContractAddr(); } void ClientModel::callAddress(Address const& _contract, bytes const& _data, TransactionSettings const& _tr) diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 66a14ad5b..ca8c36b79 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -252,7 +252,7 @@ private: QVariantMap contractAddresses() const; QVariantList gasCosts() const; void executeSequence(std::vector const& _sequence); - void deployContract(bytes const& _code, TransactionSettings const& _tr = TransactionSettings()); + Address deployContract(bytes const& _code, TransactionSettings const& _tr = TransactionSettings()); void callAddress(Address const& _contract, bytes const& _data, TransactionSettings const& _tr); void onNewTransaction(); void onStateReset(); From 4a99266ffbe5e575cb731c0ef7036b28fa9f1e13 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 8 Jul 2015 14:30:52 +0200 Subject: [PATCH 235/290] Prevent crash if not compiled with FATDB. --- alethzero/ExportState.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/alethzero/ExportState.cpp b/alethzero/ExportState.cpp index c11132768..d975dea14 100644 --- a/alethzero/ExportState.cpp +++ b/alethzero/ExportState.cpp @@ -127,11 +127,21 @@ void ExportStateDialog::fillContracts() ui->contracts->clear(); ui->accounts->setEnabled(true); ui->contracts->setEnabled(true); - for (auto i: ethereum()->addresses(m_block)) + try { - string r = m_main->render(i); - (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(QString::fromStdString(r)).arg((unsigned)ethereum()->countAt(i)), ethereum()->codeAt(i).empty() ? ui->accounts : ui->contracts)) - ->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size)); + for (auto i: ethereum()->addresses(m_block)) + { + string r = m_main->render(i); + (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(QString::fromStdString(r)).arg((unsigned)ethereum()->countAt(i)), ethereum()->codeAt(i).empty() ? ui->accounts : ui->contracts)) + ->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size)); + } + } + catch (InterfaceNotSupported const&) + { + ui->accounts->setEnabled(false); + ui->contracts->setEnabled(false); + ui->json->setEnabled(false); + ui->json->setText(QString("This feature requires compilation with FATDB support.")); } } From 24d7ca9ebc6bfdf94ba14b75dde2f2dd6015b8c8 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 8 Jul 2015 14:37:06 +0200 Subject: [PATCH 236/290] TransactionQueue docs --- libethereum/TransactionQueue.cpp | 21 +++++------ libethereum/TransactionQueue.h | 61 ++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 19 deletions(-) diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 36d337e7b..2554544a3 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -36,12 +36,12 @@ TransactionQueue::TransactionQueue(unsigned _limit, unsigned _futureLimit): m_limit(_limit), m_futureLimit(_futureLimit) { - unsigned verifierThreads = std::max(thread::hardware_concurrency(), 3U) - 2U; - for (unsigned i = 0; i < verifierThreads; ++i) - m_verifiers.emplace_back([=](){ - setThreadName("txcheck" + toString(i)); - this->verifierBody(); - }); + unsigned verifierThreads = std::max(thread::hardware_concurrency(), 3U) - 2U; + for (unsigned i = 0; i < verifierThreads; ++i) + m_verifiers.emplace_back([=](){ + setThreadName("txcheck" + toString(i)); + this->verifierBody(); + }); } TransactionQueue::~TransactionQueue() @@ -68,6 +68,9 @@ ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, IfDropped _ try { + // Check validity of _transactionRLP as a transaction. To do this we just deserialise and attempt to determine the sender. + // If it doesn't work, the signature is bad. + // The transaction's nonce may yet be invalid (or, it could be "valid" but we may be missing a marginally older transaction). t = Transaction(_transactionRLP, CheckTransaction::Everything); UpgradeGuard ul(l); ir = manageImport_WITH_LOCK(h, t); @@ -99,7 +102,6 @@ ImportResult TransactionQueue::import(Transaction const& _transaction, IfDropped ImportResult ret; { UpgradableGuard l(m_lock); - // TODO: keep old transactions around and check in State for nonce validity auto ir = check_WITH_LOCK(h, _ik); if (ir != ImportResult::Success) return ir; @@ -132,11 +134,7 @@ ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transactio { try { - // Check validity of _transactionRLP as a transaction. To do this we just deserialise and attempt to determine the sender. - // If it doesn't work, the signature is bad. - // The transaction's nonce may yet be invalid (or, it could be "valid" but we may be missing a marginally older transaction). assert(_h == _transaction.sha3()); - // Remove any prior transaction with the same nonce but a lower gas price. // Bomb out if there's a prior transaction with higher gas price. auto cs = m_currentByAddressAndNonce.find(_transaction.from()); @@ -263,7 +261,6 @@ unsigned TransactionQueue::waiting(Address const& _a) const void TransactionQueue::setFuture(h256 const& _txHash) { -// cdebug << "txQ::setFuture" << _t.first; WriteGuard l(m_lock); auto it = m_currentByHash.find(_txHash); if (it == m_currentByHash.end()) diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index ad8bd4a87..f6c140e6f 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -42,39 +42,84 @@ struct TransactionQueueChannel: public LogChannel { static const char* name(); s struct TransactionQueueTraceChannel: public LogChannel { static const char* name(); static const int verbosity = 7; }; #define ctxq dev::LogOutputStream() -enum class IfDropped { Ignore, Retry }; +/// Import transaction policy +enum class IfDropped +{ + Ignore, ///< Don't import transaction that was previously dropped. + Retry ///< Import transaction even if it was dropped before. +}; /** * @brief A queue of Transactions, each stored as RLP. - * Maintains a transaction queue sorted by nonce diff and gas price + * Maintains a transaction queue sorted by nonce diff and gas price. * @threadsafe */ class TransactionQueue { public: /// @brief TransactionQueue - /// @param _limit Maximum number of pending transactions in the queue - /// @param _futureLimit Maximum number of future nonce transactions + /// @param _limit Maximum number of pending transactions in the queue. + /// @param _futureLimit Maximum number of future nonce transactions. TransactionQueue(unsigned _limit = 1024, unsigned _futureLimit = 1024); ~TransactionQueue(); + /// Add transaction to the queue to be verified and imported. + /// @param _data RLP encoded transaction data. + /// @param _nodeId Optional network identified of a node transaction comes from. void enqueue(RLP const& _data, h512 const& _nodeId); + + /// Verify and add transaction to the queue synchronously. + /// @param _tx RLP encoded transaction data. + /// @param _ik Set to Retry to force re-addinga transaction that was previously dropped. + /// @returns Import result code. ImportResult import(bytes const& _tx, IfDropped _ik = IfDropped::Ignore) { return import(&_tx, _ik); } + + /// Verify and add transaction to the queue synchronously. + /// @param _tx Trasnaction data. + /// @param _ik Set to Retry to force re-addinga transaction that was previously dropped. + /// @returns Import result code. ImportResult import(Transaction const& _tx, IfDropped _ik = IfDropped::Ignore); + /// Remove transaction from the queue + /// @param _txHash Trasnaction hash void drop(h256 const& _txHash); + /// Get number of pending transactions for account. + /// @returns Pending transaction count. unsigned waiting(Address const& _a) const; + + /// Get top transactions from the queue. Returned transactions are not removed from the queue automatically. + /// @param _limit Max number of transactions to return. + /// @returns up to _limit transactions ordered by nonce and gas price. Transactions topTransactions(unsigned _limit) const; + + /// Get a hash set of transactions in the queue + /// @returns A hash set of all transactions in the queue h256Hash knownTransactions() const; + + /// Get max nonce for an account + /// @returns Max transaction nonce for account in the queue u256 maxNonce(Address const& _a) const; + + /// Mark transaction as future. It wont be retured in topTransactions list until a transaction with a preceeding nonce is imported or marked with dropGood + /// @param _t Transaction hash void setFuture(h256 const& _t); + + /// Drop a trasnaction from the list if exists and move following future trasnactions to current (if any) + /// @param _t Transaction hash void dropGood(Transaction const& _t); + /// Clear the queue void clear(); + + /// Register a handler that will be called once there is a new transaction imported template Handler<> onReady(T const& _t) { return m_onReady.add(_t); } + + /// Register a handler that will be called once asynchronous verification is comeplte an transaction has been imported template Handler onImport(T const& _t) { return m_onImport.add(_t); } private: + + /// Verified and imported transaction struct VerifiedTransaction { VerifiedTransaction(Transaction const& _t): transaction(_t) {} @@ -83,9 +128,10 @@ private: VerifiedTransaction(VerifiedTransaction const&) = delete; VerifiedTransaction& operator=(VerifiedTransaction const&) = delete; - Transaction transaction; + Transaction transaction; ///< Transaction data }; + /// Trasnaction pending verification struct UnverifiedTransaction { UnverifiedTransaction() {} @@ -96,13 +142,14 @@ private: UnverifiedTransaction(UnverifiedTransaction const&) = delete; UnverifiedTransaction& operator=(UnverifiedTransaction const&) = delete; - bytes transaction; - h512 nodeId; + bytes transaction; ///< RLP encoded transaction data + h512 nodeId; ///< Network Id of the peer transaction comes from }; struct PriorityCompare { TransactionQueue& queue; + /// Compare transaction by nonce height and gas price. bool operator()(VerifiedTransaction const& _first, VerifiedTransaction const& _second) const { u256 const& height1 = _first.transaction.nonce() - queue.m_currentByAddressAndNonce[_first.transaction.sender()].begin()->first; From ca539eb0b42bc274446823d7eca9ff676a308e06 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 8 Jul 2015 15:06:18 +0200 Subject: [PATCH 237/290] Fix AES Test One of the AES tests was making an incorrect assumption about the string constructor of FixedHash. Said constructor only works with hexadecimal string representations --- test/libdevcrypto/AES.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libdevcrypto/AES.cpp b/test/libdevcrypto/AES.cpp index 071f1509c..06f0515d6 100644 --- a/test/libdevcrypto/AES.cpp +++ b/test/libdevcrypto/AES.cpp @@ -79,7 +79,7 @@ BOOST_AUTO_TEST_CASE(AuthenticatedStreamConstructor) { cout << "AuthenticatedStreamConstructor" << endl; - Secret const sec("test"); + Secret const sec(dev::sha3("test")); crypto::aes::AuthenticatedStream as(crypto::aes::Encrypt, sec, 0); BOOST_CHECK(as.getMacInterval() == 0); as.adjustInterval(1); From 767ead8450e82f53313da3a690f39ecb4f88c573 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 10:32:16 -0700 Subject: [PATCH 238/290] Reorganise logs. --- libethereum/EthereumHost.cpp | 26 +++++++++++++++++--------- libethereum/EthereumHost.h | 2 ++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 186eb6fa8..f00ec7dc7 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -45,6 +45,12 @@ static unsigned const c_maxSendTransactions = 256; char const* const EthereumHost::s_stateNames[static_cast(SyncState::Size)] = {"Idle", "Waiting", "Hashes", "Blocks", "NewBlocks" }; +#ifdef _WIN32 +const char* EthereumHostTrace::name() { return EthPurple "^" EthGray " "; } +#else +const char* EthereumHostTrace::name() { return EthPurple "⧫" EthGray " "; } +#endif + EthereumHost::EthereumHost(BlockChain const& _ch, TransactionQueue& _tq, BlockQueue& _bq, u256 _networkId): HostCapability(), Worker ("ethsync"), @@ -67,7 +73,7 @@ bool EthereumHost::ensureInitialised() { // First time - just initialise. m_latestBlockSent = m_chain.currentHash(); - clog(NetNote) << "Initialising: latest=" << m_latestBlockSent; + clog(EthereumHostTrace) << "Initialising: latest=" << m_latestBlockSent; Guard l(x_transactions); m_transactionsSent = m_tq.knownTransactions(); @@ -150,7 +156,7 @@ void EthereumHost::maintainTransactions() RLPStream ts; _p->prep(ts, TransactionsPacket, n).appendRaw(b, n); _p->sealAndSend(ts); - cnote << "Sent" << n << "transactions to " << _p->session()->info().clientVersion; + clog(EthereumHostTrace) << "Sent" << n << "transactions to " << _p->session()->info().clientVersion; } _p->m_requireTransactions = false; return true; @@ -206,11 +212,15 @@ void EthereumHost::maintainBlocks(h256 const& _currentHash) if (diff(detailsFrom.number, detailsTo.number) < 20) { // don't be sending more than 20 "new" blocks. if there are any more we were probably waaaay behind. - clog(NetMessageSummary) << "Sending a new block (current is" << _currentHash << ", was" << m_latestBlockSent << ")"; + clog(EthereumHostTrace) << "Sending a new block (current is" << _currentHash << ", was" << m_latestBlockSent << ")"; h256s blocks = get<0>(m_chain.treeRoute(m_latestBlockSent, _currentHash, false, false, true)); - auto s = randomSelection(25, [&](EthereumPeer* p){ DEV_GUARDED(p->x_knownBlocks) return !p->m_knownBlocks.count(_currentHash); return false; }); + auto s = randomSelection(25, [&](EthereumPeer* p){ + DEV_GUARDED(p->x_knownBlocks) + return !p->m_knownBlocks.count(_currentHash); + return false; + }); for (shared_ptr const& p: get<0>(s)) for (auto const& b: blocks) { @@ -292,11 +302,11 @@ void EthereumHost::onPeerTransactions(std::shared_ptr _peer, RLP c { if (_peer->isCriticalSyncing()) { - clog(NetAllDetail) << "Ignoring transaction from peer we are syncing with"; + clog(EthereumHostTrace) << "Ignoring transaction from peer we are syncing with"; return; } unsigned itemCount = _r.itemCount(); - clog(NetAllDetail) << "Transactions (" << dec << itemCount << "entries)"; + clog(EthereumHostTrace) << "Transactions (" << dec << itemCount << "entries)"; m_tq.enqueue(_r, _peer->session()->id()); } @@ -351,10 +361,8 @@ void EthereumHost::onTransactionImported(ImportResult _ir, h256 const& _h, h512 break; case ImportResult::AlreadyKnown: // if we already had the transaction, then don't bother sending it on. - { - Guard l(x_transactions); + DEV_GUARDED(x_transactions) m_transactionsSent.insert(_h); - } peer->addRating(0); break; case ImportResult::Success: diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index b65ddb5d0..6cb82ebb4 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -49,6 +49,8 @@ class TransactionQueue; class BlockQueue; class BlockChainSync; +struct EthereumHostTrace: public LogChannel { static const char* name(); static const int verbosity = 6; }; + /** * @brief The EthereumHost class * @warning None of this is thread-safe. You have been warned. From d94999967d6734e6a1576eb9ba4b9af657929b92 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 13:04:30 -0700 Subject: [PATCH 239/290] Undo hard fork. --- libethereum/State.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 8ba3b438a..f50545d08 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -1212,7 +1212,6 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per uncommitToMine(); // OK - transaction looks valid - execute. - u256 startGasUsed = gasUsed(); #if ETH_PARANOIA ctrace << "Executing" << e.t() << "on" << h; ctrace << toHex(e.t().rlp()); @@ -1262,7 +1261,7 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per // Add to the user-originated transactions that we've executed. m_transactions.push_back(e.t()); - m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + (m_currentBlock.number >= 830000 ? e.gasUsedNoRefunds() : e.gasUsed()), e.logs())); + m_receipts.push_back(TransactionReceipt(rootHash(), e.gasUsed(), e.logs())); m_transactionSet.insert(e.t().sha3()); } From 99b27469b596940771541b1a6b48850a8d4bcf67 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 13:09:25 -0700 Subject: [PATCH 240/290] Don't use PRNG for key generation! --- libdevcrypto/Common.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index 8bf95d02f..e45d1cfb6 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -262,16 +262,9 @@ bytes dev::scrypt(std::string const& _pass, bytes const& _salt, uint64_t _n, uin KeyPair KeyPair::create() { - static boost::thread_specific_ptr s_eng; - static unsigned s_id = 0; - if (!s_eng.get()) - s_eng.reset(new mt19937_64(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count() + ++s_id)); - - uniform_int_distribution d(0, 255); - for (int i = 0; i < 100; ++i) { - KeyPair ret(FixedHash<32>::random(*s_eng.get())); + KeyPair ret(FixedHash<32>::random()); if (ret.address()) return ret; } From e92e107fe91fdc1202bfdb6e70dd6980887bd600 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 13:11:16 -0700 Subject: [PATCH 241/290] Better casting. --- libdevcore/FixedHash.h | 2 +- libdevcrypto/Common.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 09bc3393b..139c0d943 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -151,7 +151,7 @@ public: { FixedHash ret; for (auto& i: ret.m_data) - i = std::uniform_int_distribution(0, 255)(_eng); + i = std::uniform_int_distribution(0, 255)(_eng); return ret; } diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index e45d1cfb6..e75623799 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -344,9 +344,9 @@ void Nonce::initialiseIfNeeded() { // todo: replace w/entropy from user and system std::mt19937_64 s_eng(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count()); - std::uniform_int_distribution d(0, 255); + std::uniform_int_distribution d(0, 255); for (unsigned i = 0; i < 32; ++i) - m_value[i] = byte(d(s_eng)); + m_value[i] = d(s_eng); } if (!m_value) BOOST_THROW_EXCEPTION(InvalidState()); From 8c3fa55dab559da7d8eb4e092cec8d3b2cd7f803 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 14:42:35 -0700 Subject: [PATCH 242/290] windows build fix. --- libdevcore/FixedHash.h | 1 + libdevcrypto/Common.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 139c0d943..5257ed333 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -24,6 +24,7 @@ #pragma once #include +#include #include #include #include "CommonData.h" diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index e75623799..6ff29988a 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -22,6 +22,7 @@ #include "Common.h" #include +#include #include #include #include From b8fa3ce53090c1247d644dce6ef9e48dd7020382 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 15:37:58 -0700 Subject: [PATCH 243/290] Better visualisation of sync. --- alethzero/DownloadView.cpp | 82 ++++++++++++++++++++++++++++++---- alethzero/DownloadView.h | 12 ++--- alethzero/Main.ui | 4 +- alethzero/MainWin.cpp | 4 +- exp/main.cpp | 2 +- libdevcore/RangeMask.h | 14 ++++++ libethereum/BlockChainSync.cpp | 2 +- libethereum/DownloadMan.cpp | 10 +++++ libethereum/DownloadMan.h | 33 ++++++++------ 9 files changed, 130 insertions(+), 33 deletions(-) diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp index 210649edb..5112f961c 100644 --- a/alethzero/DownloadView.cpp +++ b/alethzero/DownloadView.cpp @@ -30,29 +30,95 @@ using namespace std; using namespace dev; using namespace dev::eth; -DownloadView::DownloadView(QWidget* _p): QWidget(_p) +SyncView::SyncView(QWidget* _p): QWidget(_p) { } -void DownloadView::paintEvent(QPaintEvent*) +void SyncView::paintEvent(QPaintEvent*) { QPainter p(this); - p.fillRect(rect(), Qt::white); - if (!m_man || m_man->chainEmpty() || !m_man->subCount()) + + if (!m_client) + return; + + DownloadMan const* man = m_client->downloadMan(); + BlockQueueStatus bqs = m_client->blockQueueStatus(); + SyncStatus sync = m_client->syncStatus(); + + unsigned syncFrom = m_client->numberFromHash(PendingBlockHash); + unsigned syncImported = syncFrom; + unsigned syncImporting = syncImported + bqs.importing; + unsigned syncVerified = syncImporting + bqs.verified; + unsigned syncVerifying = syncVerified + bqs.verifying; + unsigned syncUnverified = syncVerifying + bqs.unverified; + unsigned syncUnknown = syncUnverified + bqs.unknown; + + // best effort guess. assumes there's no forks. + unsigned downloadFrom = m_client->numberFromHash(m_client->isKnown(man->firstBlock()) ? man->firstBlock() : PendingBlockHash); + unsigned downloadCount = sync.blocksTotal; + DownloadMan::Overview overview = man->overview(); + unsigned downloadDone = downloadFrom + overview.total; + unsigned downloadFlank = downloadFrom + overview.firstIncomplete; + unsigned downloadPoint = downloadFrom + overview.lastComplete; + + unsigned hashFrom = sync.state == SyncState::Hashes ? m_client->numberFromHash(PendingBlockHash) : downloadFrom; + unsigned hashCount = sync.state == SyncState::Hashes ? sync.hashesTotal : downloadCount; + unsigned hashDone = hashFrom + (sync.state == SyncState::Hashes ? sync.hashesReceived : hashCount); + + m_lastFrom = min(syncFrom, m_lastFrom); + unsigned from = min(min(hashFrom, downloadFrom), min(syncFrom, m_lastFrom)); + unsigned count = max(hashFrom + hashCount, downloadFrom + downloadCount) - from; + m_lastFrom = (m_lastFrom * 95 + syncFrom) / 100; + + if (!count) + { + m_lastFrom = (unsigned)-1; return; + } + + cnote << "Range " << from << "-" << (from + count); + auto r = [&](unsigned u) { + return toString((u - from) * 100 / count) + "%"; + }; + + if (count) + { + cnote << "Hashes:" << r(hashDone) << " Blocks:" << r(downloadFlank) << r(downloadDone) << r(downloadPoint); + cnote << "Importing:" << r(syncFrom) << r(syncImported) << r(syncImporting) << r(syncVerified) << r(syncVerifying) << r(syncUnverified) << r(syncUnknown); + } + + if (!man || man->chainEmpty() || !man->subCount()) + return; + + float s = min(rect().width(), rect().height()); + QPen pen; + pen.setCapStyle(Qt::FlatCap); + pen.setWidthF(s / 10); + p.setPen(pen); + auto middle = [&](float x) { + return QRectF(s / 2 - s / 2 * x, 0 + s / 2 - s / 2 * x, s * x, s * x); + }; + + auto toArc = [&](unsigned x) { + return (x - from) * -5760.f / count; + }; + const float arcFrom = 90 * 16.f; + p.drawArc(middle(0.5f), arcFrom, toArc(downloadDone)); + p.drawPie(middle(0.2f), arcFrom, toArc(hashDone)); + return; double ratio = (double)rect().width() / rect().height(); if (ratio < 1) ratio = 1 / ratio; - double n = min(16.0, min(rect().width(), rect().height()) / ceil(sqrt(m_man->chainSize() / ratio))); + double n = min(16.0, min(rect().width(), rect().height()) / ceil(sqrt(man->chainSize() / ratio))); // QSizeF area(rect().width() / floor(rect().width() / n), rect().height() / floor(rect().height() / n)); QSizeF area(n, n); QPointF pos(0, 0); - auto bg = m_man->blocksGot(); - unsigned subCount = m_man->subCount(); + auto bg = man->blocksGot(); + unsigned subCount = man->subCount(); if (subCount == 0) return; unsigned dh = 360 / subCount; @@ -64,7 +130,7 @@ void DownloadView::paintEvent(QPaintEvent*) else { unsigned h = 0; - m_man->foreachSub([&](DownloadSub const& sub) + man->foreachSub([&](DownloadSub const& sub) { if (sub.askedContains(i)) s = h; diff --git a/alethzero/DownloadView.h b/alethzero/DownloadView.h index d0fc445f8..9ee2428b2 100644 --- a/alethzero/DownloadView.h +++ b/alethzero/DownloadView.h @@ -32,21 +32,23 @@ #endif namespace dev { namespace eth { -class DownloadMan; +class Client; }} -class DownloadView: public QWidget +class SyncView: public QWidget { Q_OBJECT public: - DownloadView(QWidget* _p = nullptr); + SyncView(QWidget* _p = nullptr); - void setDownloadMan(dev::eth::DownloadMan const* _man) { m_man = _man; } + void setEthereum(dev::eth::Client const* _c) { m_client = _c; } protected: virtual void paintEvent(QPaintEvent*); private: - dev::eth::DownloadMan const* m_man = nullptr; + dev::eth::Client const* m_client = nullptr; + + unsigned m_lastFrom = (unsigned)-1; }; diff --git a/alethzero/Main.ui b/alethzero/Main.ui index b2e3a9a29..37ff7f66c 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -1149,7 +1149,7 @@ font-size: 14pt 0 - + @@ -1814,7 +1814,7 @@ font-size: 14pt 1
- DownloadView + SyncView QWidget
DownloadView.h
1 diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index bc569c5cf..ba4bec863 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1993,12 +1993,12 @@ void Main::on_net_triggered() web3()->setNetworkPreferences(netPrefs(), ui->dropPeers->isChecked()); ethereum()->setNetworkId(m_privateChain.size() ? sha3(m_privateChain.toStdString()) : h256()); web3()->startNetwork(); - ui->downloadView->setDownloadMan(ethereum()->downloadMan()); + ui->downloadView->setEthereum(ethereum()); ui->enode->setText(QString::fromStdString(web3()->enode())); } else { - ui->downloadView->setDownloadMan(nullptr); + ui->downloadView->setEthereum(nullptr); writeSettings(); web3()->stopNetwork(); } diff --git a/exp/main.cpp b/exp/main.cpp index 1db9b4267..88608f8cf 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -135,7 +135,7 @@ int main() DownloadSub s0(man); DownloadSub s1(man); DownloadSub s2(man); - man.resetToChain(h256s({u256(0), u256(1), u256(2), u256(3), u256(4), u256(5), u256(6), u256(7), u256(8)})); + man.resetToChain(h256s({u256(0), u256(1), u256(2), u256(3), u256(4), u256(5), u256(6), u256(7), u256(8)}), 0); assert((s0.nextFetch(2) == h256Set{(u256)7, (u256)8})); assert((s1.nextFetch(2) == h256Set{(u256)5, (u256)6})); assert((s2.nextFetch(2) == h256Set{(u256)3, (u256)4})); diff --git a/libdevcore/RangeMask.h b/libdevcore/RangeMask.h index eccc8305d..6c32517f5 100644 --- a/libdevcore/RangeMask.h +++ b/libdevcore/RangeMask.h @@ -200,6 +200,20 @@ public: return c; } + size_t firstOut() const + { + if (m_ranges.empty() || !m_ranges.count(m_all.first)) + return m_all.first; + return m_ranges.at(m_all.first); + } + + size_t lastIn() const + { + if (m_ranges.empty()) + return m_all.first; + return m_ranges.rbegin()->second - 1; + } + private: /// The ground range. UnsignedRange m_all; diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index e22f10880..5dd1a97cb 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -80,7 +80,7 @@ DownloadMan& BlockChainSync::downloadMan() void BlockChainSync::abortSync() { - downloadMan().resetToChain(h256s()); + downloadMan().reset(); } void BlockChainSync::onPeerStatus(std::shared_ptr _peer) diff --git a/libethereum/DownloadMan.cpp b/libethereum/DownloadMan.cpp index 5e68e3c49..a9d353292 100644 --- a/libethereum/DownloadMan.cpp +++ b/libethereum/DownloadMan.cpp @@ -24,6 +24,16 @@ using namespace std; using namespace dev; using namespace dev::eth; +DownloadMan::Overview DownloadMan::overview() const +{ + ReadGuard l(m_lock); + Overview ret; + ret.firstIncomplete = m_blocksGot.firstOut(); + ret.lastComplete = ret.lastStarted = m_blocksGot.lastIn();// TODO: lastStarted properly + ret.total = m_blocksGot.size(); + return ret; +} + DownloadSub::DownloadSub(DownloadMan& _man): m_man(&_man) { WriteGuard l(m_man->x_subs); diff --git a/libethereum/DownloadMan.h b/libethereum/DownloadMan.h index ac99e1d36..b697d87ae 100644 --- a/libethereum/DownloadMan.h +++ b/libethereum/DownloadMan.h @@ -82,6 +82,14 @@ class DownloadMan friend class DownloadSub; public: + struct Overview + { + size_t total; + size_t firstIncomplete; + size_t lastComplete; + size_t lastStarted; + }; + ~DownloadMan() { for (auto i: m_subs) @@ -97,11 +105,9 @@ public: void resetToChain(h256s const& _chain) { - { - ReadGuard l(x_subs); + DEV_READ_GUARDED(x_subs) for (auto i: m_subs) i->resetFetch(); - } WriteGuard l(m_lock); m_chain.clear(); m_chain.reserve(_chain.size()); @@ -112,11 +118,9 @@ public: void reset() { - { - ReadGuard l(x_subs); + DEV_READ_GUARDED(x_subs) for (auto i: m_subs) i->resetFetch(); - } WriteGuard l(m_lock); m_chain.clear(); m_blocksGot.reset(); @@ -127,11 +131,9 @@ public: ReadGuard l(m_lock); auto ret = m_blocksGot; if (!_desperate) - { - ReadGuard l(x_subs); - for (auto i: m_subs) - ret += i->m_asked; - } + DEV_READ_GUARDED(x_subs) + for (auto i: m_subs) + ret += i->m_asked; return ret; } @@ -144,12 +146,15 @@ public: h256s remaining() const { h256s ret; - ReadGuard l(m_lock); - for (auto i: m_blocksGot.inverted()) - ret.push_back(m_chain[i]); + DEV_READ_GUARDED(m_lock) + for (auto i: m_blocksGot.inverted()) + ret.push_back(m_chain[i]); return ret; } + h256 firstBlock() const { return m_chain.empty() ? h256() : m_chain[0]; } + Overview overview() const; + size_t chainSize() const { ReadGuard l(m_lock); return m_chain.size(); } size_t chainEmpty() const { ReadGuard l(m_lock); return m_chain.empty(); } void foreachSub(std::function const& _f) const { ReadGuard l(x_subs); for(auto i: m_subs) _f(*i); } From b3a1038fe5adef6a926f56dc29b2016bceed98ca Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 18:41:07 -0700 Subject: [PATCH 244/290] Nicer import graph. --- alethzero/DownloadView.cpp | 59 ++++++++++++++++++++++++++------------ alethzero/DownloadView.h | 1 + alethzero/Main.ui | 6 ++++ alethzero/MainWin.cpp | 11 +++++++ alethzero/MainWin.h | 1 + libethereum/BlockChain.cpp | 22 +++++++++++++- libethereum/BlockChain.h | 3 ++ libethereum/BlockQueue.cpp | 4 ++- libethereum/Client.h | 2 ++ libethereum/State.cpp | 3 +- 10 files changed, 91 insertions(+), 21 deletions(-) diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp index 5112f961c..046b8973a 100644 --- a/alethzero/DownloadView.cpp +++ b/alethzero/DownloadView.cpp @@ -52,7 +52,7 @@ void SyncView::paintEvent(QPaintEvent*) unsigned syncVerified = syncImporting + bqs.verified; unsigned syncVerifying = syncVerified + bqs.verifying; unsigned syncUnverified = syncVerifying + bqs.unverified; - unsigned syncUnknown = syncUnverified + bqs.unknown; + unsigned syncCount = syncUnverified + bqs.unknown - syncFrom; // best effort guess. assumes there's no forks. unsigned downloadFrom = m_client->numberFromHash(m_client->isKnown(man->firstBlock()) ? man->firstBlock() : PendingBlockHash); @@ -67,17 +67,19 @@ void SyncView::paintEvent(QPaintEvent*) unsigned hashDone = hashFrom + (sync.state == SyncState::Hashes ? sync.hashesReceived : hashCount); m_lastFrom = min(syncFrom, m_lastFrom); + m_lastTo = max(max(syncFrom + syncCount, hashFrom + hashCount), m_lastTo); unsigned from = min(min(hashFrom, downloadFrom), min(syncFrom, m_lastFrom)); - unsigned count = max(hashFrom + hashCount, downloadFrom + downloadCount) - from; - m_lastFrom = (m_lastFrom * 95 + syncFrom) / 100; + unsigned count = max(max(hashFrom + hashCount, downloadFrom + downloadCount), max(syncFrom + syncCount, m_lastTo)) - from; + m_lastFrom = (m_lastFrom * 99 + syncFrom * 1) / 100; + m_lastTo = (m_lastTo * 99 + max(syncFrom + syncCount, hashFrom + hashCount) * 1) / 100; if (!count) { - m_lastFrom = (unsigned)-1; + m_lastFrom = m_lastTo = (unsigned)-1; return; } - cnote << "Range " << from << "-" << (from + count); + cnote << "Range " << from << "-" << (from + count) << "(" << hashFrom << "+" << hashCount << "," << downloadFrom << "+" << downloadCount << "," << syncFrom << "+" << syncCount << ")"; auto r = [&](unsigned u) { return toString((u - from) * 100 / count) + "%"; }; @@ -85,27 +87,48 @@ void SyncView::paintEvent(QPaintEvent*) if (count) { cnote << "Hashes:" << r(hashDone) << " Blocks:" << r(downloadFlank) << r(downloadDone) << r(downloadPoint); - cnote << "Importing:" << r(syncFrom) << r(syncImported) << r(syncImporting) << r(syncVerified) << r(syncVerifying) << r(syncUnverified) << r(syncUnknown); + cnote << "Importing:" << r(syncFrom) << r(syncImported) << r(syncImporting) << r(syncVerified) << r(syncVerifying) << r(syncUnverified); } - if (!man || man->chainEmpty() || !man->subCount()) - return; - - float s = min(rect().width(), rect().height()); + float squareSize = min(rect().width(), rect().height()); QPen pen; pen.setCapStyle(Qt::FlatCap); - pen.setWidthF(s / 10); - p.setPen(pen); + pen.setWidthF(squareSize / 20); auto middle = [&](float x) { - return QRectF(s / 2 - s / 2 * x, 0 + s / 2 - s / 2 * x, s * x, s * x); + return QRectF(squareSize / 2 - squareSize / 2 * x, 0 + squareSize / 2 - squareSize / 2 * x, squareSize * x, squareSize * x); + }; + + auto arcLen = [&](unsigned x) { + return x * -5760.f / count; + }; + auto arcPos = [&](unsigned x) { + return int(90 * 16.f + arcLen(x - from)) % 5760; }; - auto toArc = [&](unsigned x) { - return (x - from) * -5760.f / count; + p.setPen(Qt::NoPen); + p.setBrush(QColor::fromHsv(0, 0, 210)); + pen.setWidthF(0.f); + p.drawPie(middle(0.4f), arcPos(from), arcLen(hashDone - from)); + + auto progress = [&](unsigned h, unsigned s, unsigned v, float size, float thickness, unsigned nfrom, unsigned ncount) { + p.setBrush(Qt::NoBrush); + pen.setColor(QColor::fromHsv(h, s, v)); + pen.setWidthF(squareSize * thickness); + p.setPen(pen); + p.drawArc(middle(size), arcPos(nfrom), arcLen(ncount)); }; - const float arcFrom = 90 * 16.f; - p.drawArc(middle(0.5f), arcFrom, toArc(downloadDone)); - p.drawPie(middle(0.2f), arcFrom, toArc(hashDone)); + + progress(0, 50, 170, 0.4f, 0.12f, downloadFlank, downloadPoint - downloadFlank); + progress(0, 0, 150, 0.4f, 0.10f, from, downloadDone - from); + + progress(0, 0, 230, 0.7f, 0.090f, from, syncUnverified - from); + progress(60, 25, 210, 0.7f, 0.08f, from, syncVerifying - from); + progress(120, 25, 190, 0.7f, 0.07f, from, syncVerified - from); + + progress(0, 0, 220, 0.9f, 0.02f, from, count); + progress(0, 0, 100, 0.9f, 0.04f, from, syncFrom - from); + progress(0, 50, 100, 0.9f, 0.08f, syncFrom, syncImporting - syncFrom); + return; double ratio = (double)rect().width() / rect().height(); diff --git a/alethzero/DownloadView.h b/alethzero/DownloadView.h index 9ee2428b2..71fc41f3f 100644 --- a/alethzero/DownloadView.h +++ b/alethzero/DownloadView.h @@ -51,4 +51,5 @@ private: dev::eth::Client const* m_client = nullptr; unsigned m_lastFrom = (unsigned)-1; + unsigned m_lastTo = (unsigned)-1; }; diff --git a/alethzero/Main.ui b/alethzero/Main.ui index 37ff7f66c..97853e174 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -199,6 +199,7 @@ + @@ -1804,6 +1805,11 @@ font-size: 14pt &Sentinel... + + + &Rewind Chain... + + diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index ba4bec863..60c07fd8d 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1044,6 +1044,17 @@ void Main::on_vmInterpreter_triggered() { VMFactory::setKind(VMKind::Interpreter void Main::on_vmJIT_triggered() { VMFactory::setKind(VMKind::JIT); } void Main::on_vmSmart_triggered() { VMFactory::setKind(VMKind::Smart); } +void Main::on_rewindChain_triggered() +{ + bool ok; + int n = QInputDialog::getInt(this, "Rewind Chain", "Enter the number of the new chain head.", ethereum()->number() * 9 / 10, 1, ethereum()->number(), 1, &ok); + if (ok) + { + ethereum()->rewind(n); + refreshAll(); + } +} + void Main::on_urlEdit_returnPressed() { QString s = ui->urlEdit->text(); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index b1939534b..0e944b042 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -187,6 +187,7 @@ private slots: void on_vmInterpreter_triggered(); void on_vmJIT_triggered(); void on_vmSmart_triggered(); + void on_rewindChain_triggered(); // Debugger void on_debugCurrent_triggered(); diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index bf4eaf4d0..719ec016e 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -799,6 +799,25 @@ void BlockChain::clearBlockBlooms(unsigned _begin, unsigned _end) } } +void BlockChain::rewind(unsigned _newHead) +{ + DEV_WRITE_GUARDED(x_lastBlockHash) + { + if (_newHead >= m_lastBlockNumber) + return; + m_lastBlockHash = numberHash(_newHead); + m_lastBlockNumber = _newHead; + auto o = m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&m_lastBlockHash, 32)); + if (!o.ok()) + { + cwarn << "Error writing to extras database: " << o.ToString(); + cout << "Put" << toHex(bytesConstRef(ldb::Slice("best"))) << "=>" << toHex(bytesConstRef(ldb::Slice((char const*)&m_lastBlockHash, 32))); + cwarn << "Fail writing to extras database. Bombing out."; + exit(-1); + } + } +} + tuple BlockChain::treeRoute(h256 const& _from, h256 const& _to, bool _common, bool _pre, bool _post) const { // cdebug << "treeRoute" << _from << "..." << _to; @@ -1070,7 +1089,8 @@ bool BlockChain::isKnown(h256 const& _hash) const if (d.empty()) return false; } - return true; +// return true; + return details(_hash).number <= m_lastBlockNumber; // to allow rewind functionality. } bytes BlockChain::block(h256 const& _hash) const diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index 4cffca2df..1d88430b0 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -215,6 +215,9 @@ public: /// Will call _progress with the progress in this operation first param done, second total. void rebuild(std::string const& _path, ProgressCallback const& _progress = std::function(), bool _prepPoW = false); + /// Alter the head of the chain to some prior block along it. + void rewind(unsigned _newHead); + /** @returns a tuple of: * - an vector of hashes of all blocks between @a _from and @a _to, all blocks are ordered first by a number of * blocks that are parent-to-child, then two sibling blocks, then a number of blocks that are child-to-parent; diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index 5e0a523d8..f95a3880e 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -215,8 +215,10 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo return ImportResult::Malformed; } + clog(BlockQueueTraceChannel) << "Block" << h << "is" << bi.number << "parent is" << bi.parentHash; + // Check block doesn't already exist first! - if (_bc.details(h)) + if (_bc.isKnown(h)) { cblockq << "Already known in chain."; return ImportResult::AlreadyInChain; diff --git a/libethereum/Client.h b/libethereum/Client.h index 829ec77c1..fac54b010 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -217,6 +217,8 @@ public: std::string const& sentinel() const { return m_sentinel; } /// Set the extra data that goes into mined blocks. void setExtraData(bytes const& _extraData) { m_extraData = _extraData; } + /// Rewind to a prior head. + void rewind(unsigned _n) { m_bc.rewind(_n); } protected: /// InterfaceStub methods diff --git a/libethereum/State.cpp b/libethereum/State.cpp index f50545d08..10d637509 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -1212,6 +1212,7 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per uncommitToMine(); // OK - transaction looks valid - execute. + u256 startGasUsed = gasUsed(); #if ETH_PARANOIA ctrace << "Executing" << e.t() << "on" << h; ctrace << toHex(e.t().rlp()); @@ -1261,7 +1262,7 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per // Add to the user-originated transactions that we've executed. m_transactions.push_back(e.t()); - m_receipts.push_back(TransactionReceipt(rootHash(), e.gasUsed(), e.logs())); + m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + e.gasUsed(), e.logs())); m_transactionSet.insert(e.t().sha3()); } From 9d5b632c5821da43fc525c2c74501e4edacce7d2 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 19:01:52 -0700 Subject: [PATCH 245/290] pair up hash with Address for transaction submission API. --- libethereum/ClientBase.cpp | 4 ++-- libethereum/ClientBase.h | 2 +- libethereum/Interface.cpp | 3 +-- libethereum/Interface.h | 2 +- libweb3jsonrpc/AccountHolder.cpp | 4 ++-- mix/ClientModel.cpp | 5 ++--- mix/MixClient.cpp | 4 ++-- mix/MixClient.h | 4 ++-- neth/main.cpp | 2 -- 9 files changed, 13 insertions(+), 17 deletions(-) diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 2cef62680..f463b0195 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -45,7 +45,7 @@ State ClientBase::asOf(BlockNumber _h) const return asOf(bc().numberHash(_h)); } -h256 ClientBase::submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) +pair ClientBase::submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) { prepareForTransaction(); @@ -59,7 +59,7 @@ h256 ClientBase::submitTransaction(TransactionSkeleton const& _t, Secret const& StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged()); cnote << "New transaction " << t; - return t.sha3(); + return make_pair(t.sha3(), toAddress(ts.from, ts.nonce)); } // TODO: remove try/catch, allow exceptions diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index 05766b3a1..82f03def0 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -77,7 +77,7 @@ public: /// Submits the given transaction. /// @returns the new transaction's hash. - virtual h256 submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) override; + virtual std::pair submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) override; using Interface::submitTransaction; /// Makes the given call. Nothing is recorded into the state. diff --git a/libethereum/Interface.cpp b/libethereum/Interface.cpp index efa304bd5..e95e03a45 100644 --- a/libethereum/Interface.cpp +++ b/libethereum/Interface.cpp @@ -46,6 +46,5 @@ Address Interface::submitTransaction(Secret const& _secret, u256 const& _endowme ts.gas = _gas; ts.gasPrice = _gasPrice; ts.nonce = _nonce; - submitTransaction(ts, _secret); - return toAddress(toAddress(_secret), _nonce); + return submitTransaction(ts, _secret).second; } diff --git a/libethereum/Interface.h b/libethereum/Interface.h index c65670a30..973433af9 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -67,7 +67,7 @@ public: /// Submits a new transaction. /// @returns the transaction's hash. - virtual h256 submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) = 0; + virtual std::pair submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) = 0; /// Submits the given message-call transaction. void submitTransaction(Secret const& _secret, u256 const& _value, Address const& _dest, bytes const& _data = bytes(), u256 const& _gas = 10000, u256 const& _gasPrice = 10 * szabo, u256 const& _nonce = UndefinedU256); diff --git a/libweb3jsonrpc/AccountHolder.cpp b/libweb3jsonrpc/AccountHolder.cpp index f4b3a9f9f..43a7073d2 100644 --- a/libweb3jsonrpc/AccountHolder.cpp +++ b/libweb3jsonrpc/AccountHolder.cpp @@ -109,7 +109,7 @@ AddressHash SimpleAccountHolder::realAccounts() const h256 SimpleAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t) { if (isRealAccount(_t.from)) - return m_client()->submitTransaction(_t, m_keyManager.secret(_t.from, [&](){ return m_getPassword(_t.from); })); + return m_client()->submitTransaction(_t, m_keyManager.secret(_t.from, [&](){ return m_getPassword(_t.from); })).first; else if (isProxyAccount(_t.from)) queueTransaction(_t); return h256(); @@ -118,7 +118,7 @@ h256 SimpleAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t) h256 FixedAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t) { if (isRealAccount(_t.from)) - return m_client()->submitTransaction(_t, m_accounts[_t.from]); + return m_client()->submitTransaction(_t, m_accounts[_t.from]).first; else if (isProxyAccount(_t.from)) queueTransaction(_t); return h256(); diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 23f68996c..c4a05ef29 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -672,10 +672,9 @@ void ClientModel::debugRecord(unsigned _index) showDebuggerForTransaction(e); } -Address ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction) +pair ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction) { - m_client->submitTransaction(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice, _ctrTransaction.gasAuto); - return m_client->lastCreatedContractAddr(); + return m_client->submitTransaction(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice, _ctrTransaction.gasAuto); } void ClientModel::callAddress(Address const& _contract, bytes const& _data, TransactionSettings const& _tr) diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index c41661046..6fdaf301b 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -303,14 +303,14 @@ State MixClient::asOf(h256 const& _block) const return ret; } -h256 MixClient::submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto) +pair MixClient::submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto) { WriteGuard l(x_state); TransactionSkeleton ts = _ts; ts.nonce = m_state.transactionsFrom(toAddress(_secret)); eth::Transaction t(ts, _secret); executeTransaction(t, m_state, false, _gasAuto, _secret); - return t.sha3(); + return make_pair(t.sha3(), toAddress(ts.from, ts.nonce)); } Address MixClient::lastCreatedContractAddr() const diff --git a/mix/MixClient.h b/mix/MixClient.h index 5b1b155a1..f9574e90a 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -58,8 +58,8 @@ public: dev::eth::ExecutionResult create(Address const& _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * eth::szabo, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override; using ClientBase::submitTransaction; - virtual h256 submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret) override { return submitTransaction(_ts, _secret, false); } - h256 submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto); + virtual std::pair submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret) override { return submitTransaction(_ts, _secret, false); } + std::pair submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto); dev::eth::ExecutionResult call(Address const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber, bool _gasAuto, eth::FudgeFactor _ff = eth::FudgeFactor::Strict); void setAddress(Address _us) override; diff --git a/neth/main.cpp b/neth/main.cpp index d5cb4bb4b..5ec253440 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -1057,9 +1057,7 @@ int main(int argc, char** argv) else if (gas < minGas) cwarn << "Minimum gas amount is" << minGas; else - { c->submitTransaction(us.secret(), endowment, init, gas); - } } } else if (c && cmd == "inspect") From 0e583ffc388921910bc5f5337f59f5ac9686ba0b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Jul 2015 19:06:54 -0700 Subject: [PATCH 246/290] Fix up the windows build. --- libdevcore/FixedHash.h | 2 +- libdevcrypto/Common.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 5257ed333..a9922063a 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -152,7 +152,7 @@ public: { FixedHash ret; for (auto& i: ret.m_data) - i = std::uniform_int_distribution(0, 255)(_eng); + i = (uint8_t)std::uniform_int_distribution(0, 255)(_eng); return ret; } diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index 6ff29988a..186c6ce06 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -345,9 +345,9 @@ void Nonce::initialiseIfNeeded() { // todo: replace w/entropy from user and system std::mt19937_64 s_eng(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count()); - std::uniform_int_distribution d(0, 255); + std::uniform_int_distribution d(0, 255); for (unsigned i = 0; i < 32; ++i) - m_value[i] = d(s_eng); + m_value[i] = (uint8_t)d(s_eng); } if (!m_value) BOOST_THROW_EXCEPTION(InvalidState()); From d65a496e18c11bc71ba1001fbd47be6f899348a9 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 8 Jul 2015 07:02:57 -0700 Subject: [PATCH 247/290] Mix fix. --- mix/ClientModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index c4a05ef29..90ff19feb 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -672,7 +672,7 @@ void ClientModel::debugRecord(unsigned _index) showDebuggerForTransaction(e); } -pair ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction) +Address ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction) { return m_client->submitTransaction(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice, _ctrTransaction.gasAuto); } From aede1619c898945d2642e0672dabdcfd7f170b91 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 8 Jul 2015 08:30:19 -0700 Subject: [PATCH 248/290] Reversion of hardfork. --- libethereum/State.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index bc87be4ab..10d637509 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -1212,7 +1212,7 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per uncommitToMine(); // OK - transaction looks valid - execute. - u256 startGasUsed = e.gasUsed(); + u256 startGasUsed = gasUsed(); #if ETH_PARANOIA ctrace << "Executing" << e.t() << "on" << h; ctrace << toHex(e.t().rlp()); From a4e468b17149a52ddf51d504fd966c9def6e09f6 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 8 Jul 2015 09:38:13 -0700 Subject: [PATCH 249/290] Download view cleanups. --- alethzero/DownloadView.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp index 046b8973a..c87f14685 100644 --- a/alethzero/DownloadView.cpp +++ b/alethzero/DownloadView.cpp @@ -66,12 +66,8 @@ void SyncView::paintEvent(QPaintEvent*) unsigned hashCount = sync.state == SyncState::Hashes ? sync.hashesTotal : downloadCount; unsigned hashDone = hashFrom + (sync.state == SyncState::Hashes ? sync.hashesReceived : hashCount); - m_lastFrom = min(syncFrom, m_lastFrom); - m_lastTo = max(max(syncFrom + syncCount, hashFrom + hashCount), m_lastTo); - unsigned from = min(min(hashFrom, downloadFrom), min(syncFrom, m_lastFrom)); - unsigned count = max(max(hashFrom + hashCount, downloadFrom + downloadCount), max(syncFrom + syncCount, m_lastTo)) - from; - m_lastFrom = (m_lastFrom * 99 + syncFrom * 1) / 100; - m_lastTo = (m_lastTo * 99 + max(syncFrom + syncCount, hashFrom + hashCount) * 1) / 100; + unsigned from = min(min(hashFrom, downloadFrom), syncFrom); + unsigned count = max(max(hashFrom + hashCount, downloadFrom + downloadCount), syncFrom + syncCount) - from; if (!count) { From 3472ae930b8060a76dd3b7d5d019b829f0403268 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 8 Jul 2015 09:38:33 -0700 Subject: [PATCH 250/290] Fix sendTransaction in mix. --- mix/MixClient.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index c73763076..8373c7c51 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -307,7 +307,8 @@ pair MixClient::submitTransaction(eth::TransactionSkeleton const& { WriteGuard l(x_state); TransactionSkeleton ts = _ts; - ts.nonce = m_state.transactionsFrom(toAddress(_secret)); + ts.from = toAddress(_secret); + ts.nonce = m_state.transactionsFrom(ts.from); eth::Transaction t(ts, _secret); executeTransaction(t, m_state, false, _gasAuto, _secret); return make_pair(t.sha3(), toAddress(ts.from, ts.nonce)); From 56091064db569543a6b3ab24bdb1c75c7e15b956 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 8 Jul 2015 18:21:28 +0200 Subject: [PATCH 251/290] work around invalid NewBlock packet --- libethereum/BlockChainSync.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 5dd1a97cb..6f19c2812 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -296,10 +296,14 @@ void BlockChainSync::onPeerNewBlock(std::shared_ptr _peer, RLP con case ImportResult::FutureTimeUnknown: case ImportResult::UnknownParent: + { logNewBlock(h); clog(NetMessageDetail) << "Received block with no known parent. Resyncing..."; - resetSyncFor(_peer, h, _r[1].toInt()); - break; + u256 totalDifficulty = _r[1].toInt(); + if (totalDifficulty > _peer->m_totalDifficulty) + resetSyncFor(_peer, h, totalDifficulty); + } + break; default:; } From 53c993b022964fc2020e6689af77c0ff1762df41 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 8 Jul 2015 18:48:17 +0200 Subject: [PATCH 252/290] style --- libethereum/BlockChainSync.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 6f19c2812..b3b168cb7 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -302,8 +302,8 @@ void BlockChainSync::onPeerNewBlock(std::shared_ptr _peer, RLP con u256 totalDifficulty = _r[1].toInt(); if (totalDifficulty > _peer->m_totalDifficulty) resetSyncFor(_peer, h, totalDifficulty); + break; } - break; default:; } From 4990aeaf06fb2bc87109d82d41ac245669337810 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Wed, 8 Jul 2015 18:56:25 +0200 Subject: [PATCH 253/290] clean up eth cli interactive interface --- eth/main.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index f32eabbf0..d2853eb73 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -75,12 +75,8 @@ void interactiveHelp() << "Commands:" << endl << " netstart Starts the network subsystem on a specific port." << endl << " netstop Stops the network subsystem." << endl - << " jsonstart Starts the JSON-RPC server." << endl - << " jsonstop Stops the JSON-RPC server." << endl << " connect Connects to a specific peer." << endl << " verbosity () Gets or sets verbosity level." << endl - << " setetherprice

Resets the ether price." << endl - << " setpriority

Resets the transaction priority." << endl << " minestart Starts mining." << endl << " minestop Stops mining." << endl << " mineforce Forces mining, even when there are no transactions." << endl From a8a8fa5ced19a7f0f6f138e9af7508016c448500 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 8 Jul 2015 19:35:04 +0200 Subject: [PATCH 254/290] start pv60 sync after 10sec delay --- libethereum/BlockChainSync.cpp | 4 +++- libethereum/BlockChainSync.h | 6 +++--- libethereum/EthereumHost.cpp | 25 ++++++++++++++++++++++++- libethereum/EthereumHost.h | 1 + 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index b3b168cb7..5249c41e0 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -298,10 +298,12 @@ void BlockChainSync::onPeerNewBlock(std::shared_ptr _peer, RLP con case ImportResult::UnknownParent: { logNewBlock(h); - clog(NetMessageDetail) << "Received block with no known parent. Resyncing..."; u256 totalDifficulty = _r[1].toInt(); if (totalDifficulty > _peer->m_totalDifficulty) + { + clog(NetMessageDetail) << "Received block with no known parent. Resyncing..."; resetSyncFor(_peer, h, totalDifficulty); + } break; } default:; diff --git a/libethereum/BlockChainSync.h b/libethereum/BlockChainSync.h index 4fb7bae2c..6be17bc74 100644 --- a/libethereum/BlockChainSync.h +++ b/libethereum/BlockChainSync.h @@ -58,6 +58,9 @@ public: /// @returns true is Sync is in progress virtual bool isSyncing() const = 0; + /// Restart sync + virtual void restartSync() = 0; + /// Called by peer to report status virtual void onPeerStatus(std::shared_ptr _peer); @@ -92,9 +95,6 @@ protected: /// Resume downloading after witing state virtual void continueSync() = 0; - /// Restart sync - virtual void restartSync() = 0; - /// Called after all blocks have been donloaded virtual void completeSync() = 0; diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index f00ec7dc7..1c9a491a8 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -88,6 +88,7 @@ void EthereumHost::reset() if (m_sync) m_sync->abortSync(); m_sync.reset(); + m_syncStart = 0; m_latestBlockSent = h256(); Guard tl(x_transactions); @@ -115,6 +116,21 @@ void EthereumHost::doWork() foreachPeer([](std::shared_ptr _p) { _p->tick(); return true; }); + if (m_syncStart) + { + Guard l(x_sync); + if (!m_sync) + { + time_t now = std::chrono::system_clock::to_time_t(chrono::system_clock::now()); + if ((now - m_syncStart) > 10) + { + m_sync.reset(new PV60Sync(*this)); + m_syncStart = 0; + m_sync->restartSync(); + } + } + } + // return netChange; // TODO: Figure out what to do with netChange. (void)netChange; @@ -259,7 +275,14 @@ BlockChainSync* EthereumHost::sync() pv61 = true; return !pv61; }); - m_sync.reset(pv61 ? new PV61Sync(*this) : new PV60Sync(*this)); + if (pv61) + { + m_syncStart = 0; + m_sync.reset(new PV61Sync(*this)); + } + else if (!m_syncStart) + m_syncStart = std::chrono::system_clock::to_time_t(chrono::system_clock::now()); + return m_sync.get(); } diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index 6cb82ebb4..9afaa8413 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -138,6 +138,7 @@ private: mutable Mutex x_transactions; DownloadMan m_man; std::unique_ptr m_sync; + std::atomic m_syncStart = { 0 }; }; } From b9e6d54a39d206ed7ed34f48816ddcdd0ab15782 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 8 Jul 2015 11:10:46 -0700 Subject: [PATCH 255/290] More easily accessible d/l viz. --- alethzero/DownloadView.cpp | 127 +++++++++++++++++-------------------- alethzero/DownloadView.h | 5 +- 2 files changed, 61 insertions(+), 71 deletions(-) diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp index c87f14685..a7128a59f 100644 --- a/alethzero/DownloadView.cpp +++ b/alethzero/DownloadView.cpp @@ -38,6 +38,8 @@ void SyncView::paintEvent(QPaintEvent*) { QPainter p(this); p.fillRect(rect(), Qt::white); + p.setRenderHint(QPainter::Antialiasing, true); + p.setRenderHint(QPainter::HighQualityAntialiasing, true); if (!m_client) return; @@ -59,23 +61,47 @@ void SyncView::paintEvent(QPaintEvent*) unsigned downloadCount = sync.blocksTotal; DownloadMan::Overview overview = man->overview(); unsigned downloadDone = downloadFrom + overview.total; - unsigned downloadFlank = downloadFrom + overview.firstIncomplete; - unsigned downloadPoint = downloadFrom + overview.lastComplete; +// unsigned downloadFlank = downloadFrom + (sync.state == SyncState::Blocks ? overview.firstIncomplete : downloadCount); + unsigned downloadPoint = downloadFrom + (sync.state == SyncState::Blocks ? overview.lastComplete : downloadCount); unsigned hashFrom = sync.state == SyncState::Hashes ? m_client->numberFromHash(PendingBlockHash) : downloadFrom; unsigned hashCount = sync.state == SyncState::Hashes ? sync.hashesTotal : downloadCount; unsigned hashDone = hashFrom + (sync.state == SyncState::Hashes ? sync.hashesReceived : hashCount); - unsigned from = min(min(hashFrom, downloadFrom), syncFrom); - unsigned count = max(max(hashFrom + hashCount, downloadFrom + downloadCount), syncFrom + syncCount) - from; - - if (!count) + QString labelText = QString("PV%1").arg(sync.protocolVersion); + QColor labelBack = QColor::fromHsv(sync.protocolVersion == 60 ? 30 : sync.protocolVersion == 61 ? 120 : 240, 15, 220); + QColor labelFore = labelBack.darker(); + switch (sync.state) { - m_lastFrom = m_lastTo = (unsigned)-1; - return; + case SyncState::Hashes: + m_lastSyncFrom = hashFrom; + m_lastSyncCount = hashCount; + m_wasEstimate = sync.hashesEstimated; + break; + case SyncState::Blocks: + if (m_wasEstimate) + { + m_lastSyncFrom = downloadFrom; + m_lastSyncCount = downloadCount; + m_wasEstimate = false; + } + break; + case SyncState::Idle: + if (!syncCount) + { + m_lastSyncFrom = (unsigned)-1; + m_lastSyncCount = 0; + labelBack = QColor::fromHsv(0, 0, 200); + labelFore = Qt::white; + labelText = "Idle"; + } + default: break; } - cnote << "Range " << from << "-" << (from + count) << "(" << hashFrom << "+" << hashCount << "," << downloadFrom << "+" << downloadCount << "," << syncFrom << "+" << syncCount << ")"; + unsigned from = min(min(hashFrom, downloadFrom), min(syncFrom, m_lastSyncFrom)); + unsigned count = max(max(hashFrom + hashCount, downloadFrom + downloadCount), max(syncFrom + syncCount, m_lastSyncFrom + m_lastSyncCount)) - from; + +/* cnote << "Range " << from << "-" << (from + count) << "(" << hashFrom << "+" << hashCount << "," << downloadFrom << "+" << downloadCount << "," << syncFrom << "+" << syncCount << ")"; auto r = [&](unsigned u) { return toString((u - from) * 100 / count) + "%"; }; @@ -85,27 +111,22 @@ void SyncView::paintEvent(QPaintEvent*) cnote << "Hashes:" << r(hashDone) << " Blocks:" << r(downloadFlank) << r(downloadDone) << r(downloadPoint); cnote << "Importing:" << r(syncFrom) << r(syncImported) << r(syncImporting) << r(syncVerified) << r(syncVerifying) << r(syncUnverified); } - - float squareSize = min(rect().width(), rect().height()); +*/ QPen pen; pen.setCapStyle(Qt::FlatCap); - pen.setWidthF(squareSize / 20); + float squareSize = min(rect().width(), rect().height()); + auto middleRect = [&](float w, float h) { + return QRectF(squareSize / 2 - w / 2, squareSize / 2 - h / 2, w, h); + }; auto middle = [&](float x) { - return QRectF(squareSize / 2 - squareSize / 2 * x, 0 + squareSize / 2 - squareSize / 2 * x, squareSize * x, squareSize * x); + return middleRect(squareSize * x, squareSize * x); }; - auto arcLen = [&](unsigned x) { return x * -5760.f / count; }; auto arcPos = [&](unsigned x) { return int(90 * 16.f + arcLen(x - from)) % 5760; }; - - p.setPen(Qt::NoPen); - p.setBrush(QColor::fromHsv(0, 0, 210)); - pen.setWidthF(0.f); - p.drawPie(middle(0.4f), arcPos(from), arcLen(hashDone - from)); - auto progress = [&](unsigned h, unsigned s, unsigned v, float size, float thickness, unsigned nfrom, unsigned ncount) { p.setBrush(Qt::NoBrush); pen.setColor(QColor::fromHsv(h, s, v)); @@ -114,57 +135,25 @@ void SyncView::paintEvent(QPaintEvent*) p.drawArc(middle(size), arcPos(nfrom), arcLen(ncount)); }; - progress(0, 50, 170, 0.4f, 0.12f, downloadFlank, downloadPoint - downloadFlank); - progress(0, 0, 150, 0.4f, 0.10f, from, downloadDone - from); - - progress(0, 0, 230, 0.7f, 0.090f, from, syncUnverified - from); - progress(60, 25, 210, 0.7f, 0.08f, from, syncVerifying - from); - progress(120, 25, 190, 0.7f, 0.07f, from, syncVerified - from); - - progress(0, 0, 220, 0.9f, 0.02f, from, count); - progress(0, 0, 100, 0.9f, 0.04f, from, syncFrom - from); - progress(0, 50, 100, 0.9f, 0.08f, syncFrom, syncImporting - syncFrom); + progress(0, 0, 220, 0.6f, 0.02f, from, hashDone); // Download rail + progress(240, 25, 170, 0.6f, 0.02f, downloadDone, downloadPoint - downloadDone); // Latest download point + progress(240, 50, 120, 0.6f, 0.04f, from, downloadDone - from); // Downloaded - return; + progress(0, 0, 220, 0.9f, 0.02f, from, count); // Sync rail + progress(0, 0, 170, 0.9f, 0.02f, from, syncUnverified - from); // Verification rail + progress(60, 25, 170, 0.9f, 0.02f, from, syncVerifying - from); // Verifying. + progress(120, 25, 170, 0.9f, 0.02f, from, syncVerified - from); // Verified. + progress(120, 50, 120, 0.9f, 0.04f, from, syncFrom - from); // Imported. + progress(240, 25, 170, 0.9f, 0.04f, syncFrom, syncImporting - syncFrom); // Importing. - double ratio = (double)rect().width() / rect().height(); - if (ratio < 1) - ratio = 1 / ratio; - double n = min(16.0, min(rect().width(), rect().height()) / ceil(sqrt(man->chainSize() / ratio))); - -// QSizeF area(rect().width() / floor(rect().width() / n), rect().height() / floor(rect().height() / n)); - QSizeF area(n, n); - QPointF pos(0, 0); - - auto bg = man->blocksGot(); - unsigned subCount = man->subCount(); - if (subCount == 0) - return; - unsigned dh = 360 / subCount; - for (unsigned i = bg.all().first, ei = bg.all().second; i < ei; ++i) + if (sync.state != SyncState::Idle || !count) { - int s = -2; - if (bg.contains(i)) - s = -1; - else - { - unsigned h = 0; - man->foreachSub([&](DownloadSub const& sub) - { - if (sub.askedContains(i)) - s = h; - h++; - }); - } - if (s == -2) - p.fillRect(QRectF(QPointF(pos) + QPointF(3 * area.width() / 8, 3 * area.height() / 8), area / 4), Qt::black); - else if (s == -1) - p.fillRect(QRectF(QPointF(pos) + QPointF(1 * area.width() / 8, 1 * area.height() / 8), area * 3 / 4), Qt::black); - else - p.fillRect(QRectF(QPointF(pos) + QPointF(1 * area.width() / 8, 1 * area.height() / 8), area * 3 / 4), QColor::fromHsv(s * dh, 64, 128)); - - pos.setX(pos.x() + n); - if (pos.x() >= rect().width() - n) - pos = QPoint(0, pos.y() + n); + p.setBrush(QBrush(labelBack)); + p.setFont(QFont("Helvetica", 10, QFont::Bold)); + QRectF r = p.boundingRect(middle(1.f), Qt::AlignCenter, labelText); + r.adjust(-r.width() / 8, -r.height() / 8, r.width() / 8, r.height() / 8); + p.setPen(QPen(labelFore, r.height() / 10)); + p.drawRoundedRect(r, r.height() / 4, r.height() / 4); + p.drawText(r, Qt::AlignCenter, labelText); } } diff --git a/alethzero/DownloadView.h b/alethzero/DownloadView.h index 71fc41f3f..f3c8b1001 100644 --- a/alethzero/DownloadView.h +++ b/alethzero/DownloadView.h @@ -50,6 +50,7 @@ protected: private: dev::eth::Client const* m_client = nullptr; - unsigned m_lastFrom = (unsigned)-1; - unsigned m_lastTo = (unsigned)-1; + unsigned m_lastSyncFrom = (unsigned)-1; + unsigned m_lastSyncCount = 0; + bool m_wasEstimate = false; }; From fbe0d01ee761b9b792630c21baa3becb3861d14f Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 8 Jul 2015 21:01:32 +0200 Subject: [PATCH 256/290] style --- libethereum/EthereumHost.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 1c9a491a8..88f95f64f 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -118,17 +118,17 @@ void EthereumHost::doWork() if (m_syncStart) { - Guard l(x_sync); - if (!m_sync) - { - time_t now = std::chrono::system_clock::to_time_t(chrono::system_clock::now()); - if ((now - m_syncStart) > 10) + DEV_GUARDED(x_sync); + if (!m_sync) { - m_sync.reset(new PV60Sync(*this)); - m_syncStart = 0; - m_sync->restartSync(); + time_t now = std::chrono::system_clock::to_time_t(chrono::system_clock::now()); + if (now - m_syncStart > 10) + { + m_sync.reset(new PV60Sync(*this)); + m_syncStart = 0; + m_sync->restartSync(); + } } - } } // return netChange; From 5b4c6f86788b744b7171df61ec622a0a6ef61880 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 8 Jul 2015 21:21:32 +0200 Subject: [PATCH 257/290] fixed reported sync protocol version --- libethereum/BlockChainSync.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 5249c41e0..6aede0c16 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -1170,9 +1170,9 @@ SyncStatus PV61Sync::status() const { RecursiveGuard l(x_sync); SyncStatus res = PV60Sync::status(); + res.protocolVersion = 61; if (m_state == SyncState::Hashes && isPV61Syncing()) { - res.protocolVersion = 61; res.hashesReceived = 0; for (auto const& d : m_readyChainMap) res.hashesReceived += d.second.size(); From 9fe06a6f989d530c0189316ce045819110027209 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 8 Jul 2015 12:31:54 -0700 Subject: [PATCH 258/290] Nicer syncing, --- alethzero/DownloadView.cpp | 92 ++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp index a7128a59f..a3b445f68 100644 --- a/alethzero/DownloadView.cpp +++ b/alethzero/DownloadView.cpp @@ -36,12 +36,12 @@ SyncView::SyncView(QWidget* _p): QWidget(_p) void SyncView::paintEvent(QPaintEvent*) { - QPainter p(this); - p.fillRect(rect(), Qt::white); - p.setRenderHint(QPainter::Antialiasing, true); - p.setRenderHint(QPainter::HighQualityAntialiasing, true); + QPainter painter(this); + painter.fillRect(rect(), Qt::white); + painter.setRenderHint(QPainter::Antialiasing, true); + painter.setRenderHint(QPainter::HighQualityAntialiasing, true); - if (!m_client) + if (!m_client || !isVisible()) return; DownloadMan const* man = m_client->downloadMan(); @@ -57,19 +57,17 @@ void SyncView::paintEvent(QPaintEvent*) unsigned syncCount = syncUnverified + bqs.unknown - syncFrom; // best effort guess. assumes there's no forks. - unsigned downloadFrom = m_client->numberFromHash(m_client->isKnown(man->firstBlock()) ? man->firstBlock() : PendingBlockHash); - unsigned downloadCount = sync.blocksTotal; - DownloadMan::Overview overview = man->overview(); - unsigned downloadDone = downloadFrom + overview.total; -// unsigned downloadFlank = downloadFrom + (sync.state == SyncState::Blocks ? overview.firstIncomplete : downloadCount); - unsigned downloadPoint = downloadFrom + (sync.state == SyncState::Blocks ? overview.lastComplete : downloadCount); + unsigned downloadFrom = sync.state == SyncState::Idle ? m_lastSyncFrom : m_client->numberFromHash(m_client->isKnown(man->firstBlock()) ? man->firstBlock() : PendingBlockHash); + unsigned downloadCount = sync.state == SyncState::Idle ? m_lastSyncCount : sync.blocksTotal; + unsigned downloadDone = downloadFrom + (sync.state == SyncState::Idle ? m_lastSyncCount : sync.blocksReceived); + unsigned downloadPoint = downloadFrom + (sync.state == SyncState::Idle ? m_lastSyncCount : man->overview().lastComplete); unsigned hashFrom = sync.state == SyncState::Hashes ? m_client->numberFromHash(PendingBlockHash) : downloadFrom; unsigned hashCount = sync.state == SyncState::Hashes ? sync.hashesTotal : downloadCount; unsigned hashDone = hashFrom + (sync.state == SyncState::Hashes ? sync.hashesReceived : hashCount); QString labelText = QString("PV%1").arg(sync.protocolVersion); - QColor labelBack = QColor::fromHsv(sync.protocolVersion == 60 ? 30 : sync.protocolVersion == 61 ? 120 : 240, 15, 220); + QColor labelBack = QColor::fromHsv(sync.protocolVersion == 60 ? 30 : sync.protocolVersion == 61 ? 120 : 240, 25, 200); QColor labelFore = labelBack.darker(); switch (sync.state) { @@ -112,48 +110,56 @@ void SyncView::paintEvent(QPaintEvent*) cnote << "Importing:" << r(syncFrom) << r(syncImported) << r(syncImporting) << r(syncVerified) << r(syncVerifying) << r(syncUnverified); } */ - QPen pen; - pen.setCapStyle(Qt::FlatCap); - float squareSize = min(rect().width(), rect().height()); + float const squareSize = min(rect().width(), rect().height()); auto middleRect = [&](float w, float h) { - return QRectF(squareSize / 2 - w / 2, squareSize / 2 - h / 2, w, h); + return QRectF(rect().width() / 2 - w / 2, rect().height() / 2 - h / 2, w, h); }; auto middle = [&](float x) { return middleRect(squareSize * x, squareSize * x); }; - auto arcLen = [&](unsigned x) { - return x * -5760.f / count; + auto pieProgress = [&](unsigned h, unsigned s, unsigned v, float size, float thickness, unsigned nfrom, unsigned ncount) { + auto arcLen = [&](unsigned x) { + return x * -5760.f / count; + }; + auto arcPos = [&](unsigned x) { + return int(90 * 16.f + arcLen(x - from)) % 5760; + }; + painter.setPen(QPen(QColor::fromHsv(h, s, v), squareSize * thickness, Qt::SolidLine, Qt::FlatCap)); + painter.setBrush(Qt::NoBrush); + painter.drawArc(middle(size), arcPos(nfrom), arcLen(ncount)); }; - auto arcPos = [&](unsigned x) { - return int(90 * 16.f + arcLen(x - from)) % 5760; + auto pieProgress2 = [&](unsigned h, unsigned s, unsigned v, float size, float orbit, float thickness, unsigned nfrom, unsigned ncount) { + pieProgress(h, s, v, size - orbit, thickness, nfrom, ncount); + pieProgress(h, s, v, size + orbit, thickness, nfrom, ncount); }; - auto progress = [&](unsigned h, unsigned s, unsigned v, float size, float thickness, unsigned nfrom, unsigned ncount) { - p.setBrush(Qt::NoBrush); - pen.setColor(QColor::fromHsv(h, s, v)); - pen.setWidthF(squareSize * thickness); - p.setPen(pen); - p.drawArc(middle(size), arcPos(nfrom), arcLen(ncount)); + auto pieLabel = [&](QString text, float points, QColor fore, QColor back) { + painter.setBrush(QBrush(back)); + painter.setFont(QFont("Helvetica", points, QFont::Bold)); + QRectF r = painter.boundingRect(middle(1.f), Qt::AlignCenter, text); + r.adjust(-r.width() / 4, -r.height() / 8, r.width() / 4, r.height() / 8); + painter.setPen(QPen(fore, r.height() / 20)); + painter.drawRoundedRect(r, r.height() / 4, r.height() / 4); + painter.drawText(r, Qt::AlignCenter, text); }; - progress(0, 0, 220, 0.6f, 0.02f, from, hashDone); // Download rail - progress(240, 25, 170, 0.6f, 0.02f, downloadDone, downloadPoint - downloadDone); // Latest download point - progress(240, 50, 120, 0.6f, 0.04f, from, downloadDone - from); // Downloaded + function progress = pieProgress; + function progress2 = pieProgress2; + function label = pieLabel; + + if (sync.state != SyncState::Idle) + { + progress(0, 0, 220, 0.6f, 0.02f, from, hashDone - from); // Download rail + progress(240, 25, 170, 0.6f, 0.02f, downloadDone, downloadPoint - downloadDone); // Latest download point + progress(240, 50, 120, 0.6f, 0.04f, from, downloadDone - from); // Downloaded + } progress(0, 0, 220, 0.9f, 0.02f, from, count); // Sync rail progress(0, 0, 170, 0.9f, 0.02f, from, syncUnverified - from); // Verification rail - progress(60, 25, 170, 0.9f, 0.02f, from, syncVerifying - from); // Verifying. - progress(120, 25, 170, 0.9f, 0.02f, from, syncVerified - from); // Verified. - progress(120, 50, 120, 0.9f, 0.04f, from, syncFrom - from); // Imported. - progress(240, 25, 170, 0.9f, 0.04f, syncFrom, syncImporting - syncFrom); // Importing. + progress2(60, 25, 170, 0.9f, 0.04f, 0.01f, from, syncVerifying - from); // Verifying. + progress2(120, 25, 170, 0.9f, 0.04f, 0.01f, from, syncVerified - from); // Verified. + progress(120, 50, 120, 0.9f, 0.05f, from, syncFrom - from); // Imported. + progress(0, 0, 120, 0.9f, 0.02f, syncFrom, syncImporting - syncFrom); // Importing. - if (sync.state != SyncState::Idle || !count) - { - p.setBrush(QBrush(labelBack)); - p.setFont(QFont("Helvetica", 10, QFont::Bold)); - QRectF r = p.boundingRect(middle(1.f), Qt::AlignCenter, labelText); - r.adjust(-r.width() / 8, -r.height() / 8, r.width() / 8, r.height() / 8); - p.setPen(QPen(labelFore, r.height() / 10)); - p.drawRoundedRect(r, r.height() / 4, r.height() / 4); - p.drawText(r, Qt::AlignCenter, labelText); - } + if (sync.state != SyncState::Idle || (sync.state == SyncState::Idle && !syncCount)) + label(labelText, 11, labelFore, labelBack); } From 5d16f389d6b59130315daf18b79e5e1ff687714d Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 8 Jul 2015 12:48:21 -0700 Subject: [PATCH 259/290] Horizontal option for sync grpah. --- alethzero/DownloadView.cpp | 66 +++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp index a3b445f68..17f91655b 100644 --- a/alethzero/DownloadView.cpp +++ b/alethzero/DownloadView.cpp @@ -41,7 +41,7 @@ void SyncView::paintEvent(QPaintEvent*) painter.setRenderHint(QPainter::Antialiasing, true); painter.setRenderHint(QPainter::HighQualityAntialiasing, true); - if (!m_client || !isVisible()) + if (!m_client || !isVisible() || !rect().width() || !rect().height()) return; DownloadMan const* man = m_client->downloadMan(); @@ -117,7 +117,7 @@ void SyncView::paintEvent(QPaintEvent*) auto middle = [&](float x) { return middleRect(squareSize * x, squareSize * x); }; - auto pieProgress = [&](unsigned h, unsigned s, unsigned v, float size, float thickness, unsigned nfrom, unsigned ncount) { + auto pieProgress = [&](unsigned h, unsigned s, unsigned v, float row, float thickness, unsigned nfrom, unsigned ncount) { auto arcLen = [&](unsigned x) { return x * -5760.f / count; }; @@ -126,11 +126,7 @@ void SyncView::paintEvent(QPaintEvent*) }; painter.setPen(QPen(QColor::fromHsv(h, s, v), squareSize * thickness, Qt::SolidLine, Qt::FlatCap)); painter.setBrush(Qt::NoBrush); - painter.drawArc(middle(size), arcPos(nfrom), arcLen(ncount)); - }; - auto pieProgress2 = [&](unsigned h, unsigned s, unsigned v, float size, float orbit, float thickness, unsigned nfrom, unsigned ncount) { - pieProgress(h, s, v, size - orbit, thickness, nfrom, ncount); - pieProgress(h, s, v, size + orbit, thickness, nfrom, ncount); + painter.drawArc(middle(0.5 + row / 2), arcPos(nfrom), arcLen(ncount)); }; auto pieLabel = [&](QString text, float points, QColor fore, QColor back) { painter.setBrush(QBrush(back)); @@ -142,23 +138,55 @@ void SyncView::paintEvent(QPaintEvent*) painter.drawText(r, Qt::AlignCenter, text); }; - function progress = pieProgress; - function progress2 = pieProgress2; - function label = pieLabel; + auto hProgress = [&](unsigned h, unsigned s, unsigned v, float row, float thickness, unsigned nfrom, unsigned ncount) { + QRectF r = rect(); + painter.setPen(QPen(QColor::fromHsv(h, s, v), r.height() * thickness, Qt::SolidLine, Qt::FlatCap)); + painter.setBrush(Qt::NoBrush); + painter.drawLine(QPointF((nfrom - from) * r.width() / count, row * r.height() * 0.8 + 0.2), QPointF((nfrom + ncount - from) * r.width() / count, row)); + }; + auto hLabel = [&](QString text, float points, QColor fore, QColor back) { + painter.setBrush(QBrush(back)); + painter.setFont(QFont("Helvetica", points, QFont::Bold)); + QRectF r = painter.boundingRect(rect(), Qt::AlignTop | Qt::AlignHCenter, text); + r.adjust(-r.width() / 4, -r.height() / 8, r.width() / 4, r.height() / 8); + painter.setPen(QPen(fore, r.height() / 20)); + painter.drawRoundedRect(r, r.height() / 4, r.height() / 4); + painter.drawText(r, Qt::AlignCenter, text); + }; + + function progress; + auto progress2 = [&](unsigned h, unsigned s, unsigned v, float row, float orbit, float thickness, unsigned nfrom, unsigned ncount) { + progress(h, s, v, row - orbit, thickness, nfrom, ncount); + progress(h, s, v, row + orbit, thickness, nfrom, ncount); + }; + function label; + if (rect().width() / rect().height() > 5) + { + progress = hProgress; + label = hLabel; + } + else if (rect().height() / rect().width() > 5) + { + } + else + { + progress = pieProgress; + label = pieLabel; + } if (sync.state != SyncState::Idle) { - progress(0, 0, 220, 0.6f, 0.02f, from, hashDone - from); // Download rail - progress(240, 25, 170, 0.6f, 0.02f, downloadDone, downloadPoint - downloadDone); // Latest download point - progress(240, 50, 120, 0.6f, 0.04f, from, downloadDone - from); // Downloaded + progress(0, 0, 220, 0.4f, 0.02f, from, hashDone - from); // Download rail + progress(240, 25, 170, 0.4f, 0.02f, downloadDone, downloadPoint - downloadDone); // Latest download point + progress(240, 50, 120, 0.4f, 0.04f, from, downloadDone - from); // Downloaded } - progress(0, 0, 220, 0.9f, 0.02f, from, count); // Sync rail - progress(0, 0, 170, 0.9f, 0.02f, from, syncUnverified - from); // Verification rail - progress2(60, 25, 170, 0.9f, 0.04f, 0.01f, from, syncVerifying - from); // Verifying. - progress2(120, 25, 170, 0.9f, 0.04f, 0.01f, from, syncVerified - from); // Verified. - progress(120, 50, 120, 0.9f, 0.05f, from, syncFrom - from); // Imported. - progress(0, 0, 120, 0.9f, 0.02f, syncFrom, syncImporting - syncFrom); // Importing. + progress(0, 0, 220, 0.8f, 0.02f, from, count); // Sync rail + progress(0, 0, 170, 0.8f, 0.02f, from, syncUnverified - from); // Verification rail + progress2(60, 25, 170, 0.8f, 0.05f, 0.01f, from, syncVerifying - from); // Verifying. + progress2(120, 25, 170, 0.8f, 0.05f, 0.01f, from, syncVerified - from); // Verified. + progress(120, 50, 120, 0.8f, 0.05f, from, syncFrom - from); // Imported. + progress(0, 0, 120, 0.8f, 0.02f, syncFrom, syncImporting - syncFrom); // Importing. if (sync.state != SyncState::Idle || (sync.state == SyncState::Idle && !syncCount)) label(labelText, 11, labelFore, labelBack); From 020ef4b81132eaa3071f3f49de338debd0ec6dc9 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 8 Jul 2015 21:44:09 +0200 Subject: [PATCH 260/290] ethashcl doesnt depend on ethcore At least not anymore. Moved global constants into ethash_cl_miner class instead of being in Ethash class. --- ethminer/MinerAux.h | 26 ++++++++++++++++++++------ libethash-cl/ethash_cl_miner.cpp | 12 +++++++----- libethash-cl/ethash_cl_miner.h | 8 ++++++++ libethcore/Ethash.cpp | 3 --- libethcore/Ethash.h | 6 ------ 5 files changed, 35 insertions(+), 20 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index d5145b97c..edfd2ad3f 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -40,6 +40,9 @@ #include #include #include +#if ETH_ETHASHCL || !ETH_TRUE +#include +#endif #if ETH_JSONRPC || !ETH_TRUE #include #include @@ -128,6 +131,7 @@ public: cerr << "Bad " << arg << " option: " << argv[i] << endl; BOOST_THROW_EXCEPTION(BadArgument()); } +#if ETH_ETHASHCL || !ETH_TRUE else if (arg == "--cl-global-work" && i + 1 < argc) try { m_globalWorkSizeMultiplier = stol(argv[++i]); @@ -155,6 +159,7 @@ public: cerr << "Bad " << arg << " option: " << argv[i] << endl; BOOST_THROW_EXCEPTION(BadArgument()); } +#endif else if (arg == "--list-devices") m_shouldListDevices = true; else if (arg == "--allow-opencl-cpu") @@ -292,6 +297,7 @@ public: ProofOfWork::CPUMiner::setNumInstances(m_miningThreads); else if (m_minerType == MinerType::GPU) { +#if ETH_ETHASHCL || !ETH_TRUE if (!ProofOfWork::GPUMiner::configureGPU( m_localWorkSize, m_globalWorkSizeMultiplier, @@ -304,6 +310,10 @@ public: )) exit(1); ProofOfWork::GPUMiner::setNumInstances(m_miningThreads); +#else + cerr << "Selected GPU mining without having compiled with -DETHASHCL=1" << endl; + exit(1); +#endif } if (mode == OperationMode::DAGInit) doInitDAG(m_initDAG); @@ -344,10 +354,12 @@ public: << " --allow-opencl-cpu Allows CPU to be considered as an OpenCL device if the OpenCL platform supports it." << endl << " --list-devices List the detected OpenCL devices and exit." << endl << " --current-block Let the miner know the current block number at configuration time. Will help determine DAG size and required GPU memory." << endl +#if ETH_ETHASHCL || !ETH_TRUE << " --cl-extragpu-mem Set the memory (in MB) you believe your GPU requires for stuff other than mining. Windows rendering e.t.c.." << endl - << " --cl-local-work Set the OpenCL local work size. Default is " << toString(dev::eth::Ethash::defaultLocalWorkSize) << endl - << " --cl-global-work Set the OpenCL global work size as a multiple of the local work size. Default is " << toString(dev::eth::Ethash::defaultGlobalWorkSizeMultiplier) << " * " << toString(dev::eth::Ethash::defaultLocalWorkSize) << endl - << " --cl-ms-per-batch Set the OpenCL target milliseconds per batch (global workgroup size). Default is " << toString(dev::eth::Ethash::defaultMSPerBatch) << ". If 0 is given then no autoadjustment of global work size will happen" << endl + << " --cl-local-work Set the OpenCL local work size. Default is " << toString(ethash_cl_miner::defaultLocalWorkSize) << endl + << " --cl-global-work Set the OpenCL global work size as a multiple of the local work size. Default is " << toString(ethash_cl_miner::defaultGlobalWorkSizeMultiplier) << " * " << toString(ethash_cl_miner::defaultLocalWorkSize) << endl + << " --cl-ms-per-batch Set the OpenCL target milliseconds per batch (global workgroup size). Default is " << toString(ethash_cl_miner::defaultMSPerBatch) << ". If 0 is given then no autoadjustment of global work size will happen" << endl +#endif ; } @@ -536,9 +548,11 @@ private: unsigned m_miningThreads = UINT_MAX; bool m_shouldListDevices = false; bool m_clAllowCPU = false; - unsigned m_globalWorkSizeMultiplier = dev::eth::Ethash::defaultGlobalWorkSizeMultiplier; - unsigned m_localWorkSize = dev::eth::Ethash::defaultLocalWorkSize; - unsigned m_msPerBatch = dev::eth::Ethash::defaultMSPerBatch; +#if ETH_ETHASHCL || !ETH_TRUE + unsigned m_globalWorkSizeMultiplier = ethash_cl_miner::defaultGlobalWorkSizeMultiplier; + unsigned m_localWorkSize = ethash_cl_miner::defaultLocalWorkSize; + unsigned m_msPerBatch = ethash_cl_miner::defaultMSPerBatch; +#endif boost::optional m_currentBlock; // default value is 350MB of GPU memory for other stuff (windows system rendering, e.t.c.) unsigned m_extraGPUMemory = 350000000; diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 8b8cb0b51..0e5e8a214 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include "ethash_cl_miner.h" #include "ethash_cl_miner_kernel.h" @@ -50,7 +49,10 @@ #undef max using namespace std; -using namespace dev::eth; + +const unsigned ethash_cl_miner::defaultLocalWorkSize = 64; +const unsigned ethash_cl_miner::defaultGlobalWorkSizeMultiplier = 4096; // * CL_DEFAULT_LOCAL_WORK_SIZE +const unsigned ethash_cl_miner::defaultMSPerBatch = 0; // TODO: If at any point we can use libdevcore in here then we should switch to using a LogChannel #define ETHCL_LOG(_contents) cout << "[OPENCL]:" << _contents << endl @@ -183,9 +185,9 @@ bool ethash_cl_miner::configureGPU( bool ethash_cl_miner::s_allowCPU = false; unsigned ethash_cl_miner::s_extraRequiredGPUMem; -unsigned ethash_cl_miner::s_msPerBatch = Ethash::defaultMSPerBatch; -unsigned ethash_cl_miner::s_workgroupSize = Ethash::defaultLocalWorkSize; -unsigned ethash_cl_miner::s_initialGlobalWorkSize = Ethash::defaultGlobalWorkSizeMultiplier * Ethash::defaultLocalWorkSize; +unsigned ethash_cl_miner::s_msPerBatch = ethash_cl_miner::defaultMSPerBatch; +unsigned ethash_cl_miner::s_workgroupSize = ethash_cl_miner::defaultLocalWorkSize; +unsigned ethash_cl_miner::s_initialGlobalWorkSize = ethash_cl_miner::defaultGlobalWorkSizeMultiplier * ethash_cl_miner::defaultLocalWorkSize; bool ethash_cl_miner::searchForAllDevices(function _callback) { diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h index d1cb53ef9..06e8550b1 100644 --- a/libethash-cl/ethash_cl_miner.h +++ b/libethash-cl/ethash_cl_miner.h @@ -65,6 +65,14 @@ public: void hash_chunk(uint8_t* _ret, uint8_t const* _header, uint64_t _nonce, unsigned _count); void search_chunk(uint8_t const*_header, uint64_t _target, search_hook& _hook); + /* -- default values -- */ + /// Default value of the local work size. Also known as workgroup size. + static const unsigned defaultLocalWorkSize; + /// Default value of the global work size as a multiplier of the local work size + static const unsigned defaultGlobalWorkSizeMultiplier; + /// Default value of the milliseconds per global work size (per batch) + static const unsigned defaultMSPerBatch; + private: static std::vector getDevices(std::vector const& _platforms, unsigned _platformId); diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index d24c8454e..fc0e07f12 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -54,9 +54,6 @@ namespace dev namespace eth { -const unsigned Ethash::defaultLocalWorkSize = 64; -const unsigned Ethash::defaultGlobalWorkSizeMultiplier = 4096; // * CL_DEFAULT_LOCAL_WORK_SIZE -const unsigned Ethash::defaultMSPerBatch = 0; const Ethash::WorkPackage Ethash::NullWorkPackage = Ethash::WorkPackage(); std::string Ethash::name() diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 804c92984..e9ddf16ca 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -150,12 +150,6 @@ public: #else using GPUMiner = CPUMiner; #endif - /// Default value of the local work size. Also known as workgroup size. - static const unsigned defaultLocalWorkSize; - /// Default value of the global work size as a multiplier of the local work size - static const unsigned defaultGlobalWorkSizeMultiplier; - /// Default value of the milliseconds per global work size (per batch) - static const unsigned defaultMSPerBatch; }; } From 50eca1578820a04df88a9131d92b358f8de9e273 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 8 Jul 2015 14:56:08 -0700 Subject: [PATCH 261/290] More tweaks for view. --- alethzero/DownloadView.cpp | 42 ++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp index 17f91655b..788a106d3 100644 --- a/alethzero/DownloadView.cpp +++ b/alethzero/DownloadView.cpp @@ -72,9 +72,12 @@ void SyncView::paintEvent(QPaintEvent*) switch (sync.state) { case SyncState::Hashes: - m_lastSyncFrom = hashFrom; - m_lastSyncCount = hashCount; - m_wasEstimate = sync.hashesEstimated; + if (!syncCount || !sync.hashesEstimated) + { + m_lastSyncFrom = min(hashFrom, m_lastSyncFrom); + m_lastSyncCount = max(hashFrom + hashCount, m_lastSyncFrom + m_lastSyncCount) - m_lastSyncFrom; + m_wasEstimate = sync.hashesEstimated; + } break; case SyncState::Blocks: if (m_wasEstimate) @@ -128,6 +131,10 @@ void SyncView::paintEvent(QPaintEvent*) painter.setBrush(Qt::NoBrush); painter.drawArc(middle(0.5 + row / 2), arcPos(nfrom), arcLen(ncount)); }; + auto pieProgress2 = [&](unsigned h, unsigned s, unsigned v, float row, float orbit, float thickness, unsigned nfrom, unsigned ncount) { + pieProgress(h, s, v, row - orbit, thickness, nfrom, ncount); + pieProgress(h, s, v, row + orbit, thickness, nfrom, ncount); + }; auto pieLabel = [&](QString text, float points, QColor fore, QColor back) { painter.setBrush(QBrush(back)); painter.setFont(QFont("Helvetica", points, QFont::Bold)); @@ -138,31 +145,35 @@ void SyncView::paintEvent(QPaintEvent*) painter.drawText(r, Qt::AlignCenter, text); }; + float lineHeight = painter.boundingRect(rect(), Qt::AlignTop | Qt::AlignHCenter, "Ay").height(); auto hProgress = [&](unsigned h, unsigned s, unsigned v, float row, float thickness, unsigned nfrom, unsigned ncount) { QRectF r = rect(); - painter.setPen(QPen(QColor::fromHsv(h, s, v), r.height() * thickness, Qt::SolidLine, Qt::FlatCap)); + painter.setPen(QPen(QColor::fromHsv(h, s, v), r.height() * thickness * 3, Qt::SolidLine, Qt::FlatCap)); painter.setBrush(Qt::NoBrush); - painter.drawLine(QPointF((nfrom - from) * r.width() / count, row * r.height() * 0.8 + 0.2), QPointF((nfrom + ncount - from) * r.width() / count, row)); + auto y = row * (r.height() - lineHeight) + lineHeight; + painter.drawLine(QPointF((nfrom - from) * r.width() / count, y), QPointF((nfrom + ncount - from) * r.width() / count, y)); + }; + auto hProgress2 = [&](unsigned h, unsigned s, unsigned v, float row, float orbit, float thickness, unsigned nfrom, unsigned ncount) { + hProgress(h, s, v, row - orbit * 3, thickness, nfrom, ncount); + hProgress(h, s, v, row + orbit * 3, thickness, nfrom, ncount); }; auto hLabel = [&](QString text, float points, QColor fore, QColor back) { painter.setBrush(QBrush(back)); painter.setFont(QFont("Helvetica", points, QFont::Bold)); QRectF r = painter.boundingRect(rect(), Qt::AlignTop | Qt::AlignHCenter, text); - r.adjust(-r.width() / 4, -r.height() / 8, r.width() / 4, r.height() / 8); + r.adjust(-r.width() / 4, r.height() / 8, r.width() / 4, 3 * r.height() / 8); painter.setPen(QPen(fore, r.height() / 20)); painter.drawRoundedRect(r, r.height() / 4, r.height() / 4); painter.drawText(r, Qt::AlignCenter, text); }; function progress; - auto progress2 = [&](unsigned h, unsigned s, unsigned v, float row, float orbit, float thickness, unsigned nfrom, unsigned ncount) { - progress(h, s, v, row - orbit, thickness, nfrom, ncount); - progress(h, s, v, row + orbit, thickness, nfrom, ncount); - }; + function progress2; function label; if (rect().width() / rect().height() > 5) { progress = hProgress; + progress2 = hProgress2; label = hLabel; } else if (rect().height() / rect().width() > 5) @@ -171,20 +182,21 @@ void SyncView::paintEvent(QPaintEvent*) else { progress = pieProgress; + progress2 = pieProgress2; label = pieLabel; } if (sync.state != SyncState::Idle) { - progress(0, 0, 220, 0.4f, 0.02f, from, hashDone - from); // Download rail + progress(0, 0, 220, 0.4f, 0.02f, from, hashDone - from); // Download rail progress(240, 25, 170, 0.4f, 0.02f, downloadDone, downloadPoint - downloadDone); // Latest download point - progress(240, 50, 120, 0.4f, 0.04f, from, downloadDone - from); // Downloaded + progress(240, 50, 120, 0.4f, 0.04f, from, downloadDone - from); // Downloaded } - progress(0, 0, 220, 0.8f, 0.02f, from, count); // Sync rail + progress(0, 0, 220, 0.8f, 0.01f, from, count); // Sync rail progress(0, 0, 170, 0.8f, 0.02f, from, syncUnverified - from); // Verification rail - progress2(60, 25, 170, 0.8f, 0.05f, 0.01f, from, syncVerifying - from); // Verifying. - progress2(120, 25, 170, 0.8f, 0.05f, 0.01f, from, syncVerified - from); // Verified. + progress2(60, 25, 170, 0.8f, 0.06f, 0.005f, from, syncVerifying - from); // Verifying. + progress2(120, 25, 170, 0.8f, 0.06f, 0.005f, from, syncVerified - from); // Verified. progress(120, 50, 120, 0.8f, 0.05f, from, syncFrom - from); // Imported. progress(0, 0, 120, 0.8f, 0.02f, syncFrom, syncImporting - syncFrom); // Importing. From 5a99bc96b792866115a59bce206ffdb9e6b94b32 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 9 Jul 2015 00:32:02 +0200 Subject: [PATCH 262/290] free non-null pointer in jsconsole --- libjsconsole/JSConsole.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libjsconsole/JSConsole.h b/libjsconsole/JSConsole.h index 77f316442..fc190a637 100644 --- a/libjsconsole/JSConsole.h +++ b/libjsconsole/JSConsole.h @@ -58,7 +58,7 @@ public: std::string rl; #if ETH_READLINE char* buff = readline(promptForIndentionLevel(openBrackets).c_str()); - isEmpty = !(buff && *buff); + isEmpty = !buff; if (!isEmpty) { rl = std::string(buff); From de97b4993980b5480bd8014b9626ec33cc9cf3d3 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 8 Jul 2015 16:41:13 -0700 Subject: [PATCH 263/290] Rescue a corrupted database. --- eth/main.cpp | 12 ++++++++++- libethereum/BlockChain.cpp | 41 ++++++++++++++++++++++++++++++++++++++ libethereum/BlockChain.h | 3 +++ libethereum/Client.h | 2 ++ 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/eth/main.cpp b/eth/main.cpp index d2853eb73..73adddf1e 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -131,6 +131,7 @@ void help() #endif << " -K,--kill First kill the blockchain." << endl << " -R,--rebuild Rebuild the blockchain from the existing database." << endl + << " --rescue Attempt to rescue a corrupt database." << endl << " --genesis-nonce Set the Genesis Nonce to the given hex nonce." << endl << " -s,--import-secret Import a secret key into the key store and use as the default." << endl << " -S,--import-session-secret Import a secret key into the key store and use as the default for this session only." << endl @@ -265,7 +266,8 @@ enum class OperationMode { Node, Import, - Export + Export, + Rescue }; enum class Format @@ -1253,6 +1255,8 @@ int main(int argc, char** argv) killChain = WithExisting::Kill; else if (arg == "-R" || arg == "--rebuild") killChain = WithExisting::Verify; + else if (arg == "-R" || arg == "--rescue") + mode = OperationMode::Rescue; else if ((arg == "-c" || arg == "--client-name") && i + 1 < argc) { if (arg == "-c") @@ -1552,6 +1556,12 @@ int main(int argc, char** argv) } }; + if (mode == OperationMode::Rescue) + { + web3.ethereum()->rescue(); + exit(0); + } + if (mode == OperationMode::Export) { ofstream fout(filename, std::ofstream::binary); diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 719ec016e..f4fc96f46 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -192,6 +192,8 @@ unsigned BlockChain::open(std::string const& _path, WithExisting _we) } } + m_writeOptions.sync = true; + if (_we != WithExisting::Verify && !details(m_genesisHash)) { // Insert details of genesis block. @@ -799,6 +801,45 @@ void BlockChain::clearBlockBlooms(unsigned _begin, unsigned _end) } } +void BlockChain::rescue(OverlayDB& _db) +{ + cout << "Rescuing database..." << endl; + + unsigned u = 1; + while (isKnown(numberHash(u))) + u *= 2; + unsigned l = u / 2; + cout << "Finding last likely block number..." << endl; + while (u - l > 1) + { + unsigned m = (u + l) / 2; + cout << " " << m << flush; + if (isKnown(numberHash(m))) + l = m; + else + u = m; + } + cout << " lowest is " << l << endl; + for (;; --l) + { + h256 h = numberHash(l); + cout << "Checking validity of " << l << " (" << h << ")..." << flush; + try + { + cout << "block..." << flush; + BlockInfo bi = info(h); + cout << "details..." << flush; + BlockDetails bd = details(h); + cout << "state..." << flush; + if (_db.exists(sha3(bi.stateRoot))) + break; + } + catch (...) {} + } + cout << "OK." << endl; + rewind(l); +} + void BlockChain::rewind(unsigned _newHead) { DEV_WRITE_GUARDED(x_lastBlockHash) diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index 1d88430b0..638c9c3af 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -218,6 +218,9 @@ public: /// Alter the head of the chain to some prior block along it. void rewind(unsigned _newHead); + /// Rescue the database. + void rescue(OverlayDB& _db); + /** @returns a tuple of: * - an vector of hashes of all blocks between @a _from and @a _to, all blocks are ordered first by a number of * blocks that are parent-to-child, then two sibling blocks, then a number of blocks that are child-to-parent; diff --git a/libethereum/Client.h b/libethereum/Client.h index fac54b010..d433ecb6d 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -219,6 +219,8 @@ public: void setExtraData(bytes const& _extraData) { m_extraData = _extraData; } /// Rewind to a prior head. void rewind(unsigned _n) { m_bc.rewind(_n); } + /// Rescue the chain. + void rescue() { m_bc.rescue(m_stateDB); } protected: /// InterfaceStub methods From a8e46ed89831b7f9ed2aca48ed4d9bd5bf192f7b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 8 Jul 2015 16:54:48 -0700 Subject: [PATCH 264/290] Fix for rescue? --- libethereum/BlockChain.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index f4fc96f46..43b115c49 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -806,8 +806,19 @@ void BlockChain::rescue(OverlayDB& _db) cout << "Rescuing database..." << endl; unsigned u = 1; - while (isKnown(numberHash(u))) - u *= 2; + while (true) + { + try { + if (isKnown(numberHash(u))) + u *= 2; + else + break; + } + catch (...) + { + break; + } + } unsigned l = u / 2; cout << "Finding last likely block number..." << endl; while (u - l > 1) From 4eeb90e81344bde707d8e8a1cb6309a661ae16d2 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 9 Jul 2015 09:16:47 +0200 Subject: [PATCH 265/290] Style regarding public class constants --- ethminer/MinerAux.h | 12 ++++++------ libethash-cl/ethash_cl_miner.cpp | 12 ++++++------ libethash-cl/ethash_cl_miner.h | 6 +++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index edfd2ad3f..964a23635 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -356,9 +356,9 @@ public: << " --current-block Let the miner know the current block number at configuration time. Will help determine DAG size and required GPU memory." << endl #if ETH_ETHASHCL || !ETH_TRUE << " --cl-extragpu-mem Set the memory (in MB) you believe your GPU requires for stuff other than mining. Windows rendering e.t.c.." << endl - << " --cl-local-work Set the OpenCL local work size. Default is " << toString(ethash_cl_miner::defaultLocalWorkSize) << endl - << " --cl-global-work Set the OpenCL global work size as a multiple of the local work size. Default is " << toString(ethash_cl_miner::defaultGlobalWorkSizeMultiplier) << " * " << toString(ethash_cl_miner::defaultLocalWorkSize) << endl - << " --cl-ms-per-batch Set the OpenCL target milliseconds per batch (global workgroup size). Default is " << toString(ethash_cl_miner::defaultMSPerBatch) << ". If 0 is given then no autoadjustment of global work size will happen" << endl + << " --cl-local-work Set the OpenCL local work size. Default is " << toString(ethash_cl_miner::c_defaultLocalWorkSize) << endl + << " --cl-global-work Set the OpenCL global work size as a multiple of the local work size. Default is " << toString(ethash_cl_miner::c_defaultGlobalWorkSizeMultiplier) << " * " << toString(ethash_cl_miner::c_defaultLocalWorkSize) << endl + << " --cl-ms-per-batch Set the OpenCL target milliseconds per batch (global workgroup size). Default is " << toString(ethash_cl_miner::c_defaultMSPerBatch) << ". If 0 is given then no autoadjustment of global work size will happen" << endl #endif ; } @@ -549,9 +549,9 @@ private: bool m_shouldListDevices = false; bool m_clAllowCPU = false; #if ETH_ETHASHCL || !ETH_TRUE - unsigned m_globalWorkSizeMultiplier = ethash_cl_miner::defaultGlobalWorkSizeMultiplier; - unsigned m_localWorkSize = ethash_cl_miner::defaultLocalWorkSize; - unsigned m_msPerBatch = ethash_cl_miner::defaultMSPerBatch; + unsigned m_globalWorkSizeMultiplier = ethash_cl_miner::c_defaultGlobalWorkSizeMultiplier; + unsigned m_localWorkSize = ethash_cl_miner::c_defaultLocalWorkSize; + unsigned m_msPerBatch = ethash_cl_miner::c_defaultMSPerBatch; #endif boost::optional m_currentBlock; // default value is 350MB of GPU memory for other stuff (windows system rendering, e.t.c.) diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 0e5e8a214..44cbf65e9 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -50,9 +50,9 @@ using namespace std; -const unsigned ethash_cl_miner::defaultLocalWorkSize = 64; -const unsigned ethash_cl_miner::defaultGlobalWorkSizeMultiplier = 4096; // * CL_DEFAULT_LOCAL_WORK_SIZE -const unsigned ethash_cl_miner::defaultMSPerBatch = 0; +const unsigned ethash_cl_miner::c_defaultLocalWorkSize = 64; +const unsigned ethash_cl_miner::c_defaultGlobalWorkSizeMultiplier = 4096; // * CL_DEFAULT_LOCAL_WORK_SIZE +const unsigned ethash_cl_miner::c_defaultMSPerBatch = 0; // TODO: If at any point we can use libdevcore in here then we should switch to using a LogChannel #define ETHCL_LOG(_contents) cout << "[OPENCL]:" << _contents << endl @@ -185,9 +185,9 @@ bool ethash_cl_miner::configureGPU( bool ethash_cl_miner::s_allowCPU = false; unsigned ethash_cl_miner::s_extraRequiredGPUMem; -unsigned ethash_cl_miner::s_msPerBatch = ethash_cl_miner::defaultMSPerBatch; -unsigned ethash_cl_miner::s_workgroupSize = ethash_cl_miner::defaultLocalWorkSize; -unsigned ethash_cl_miner::s_initialGlobalWorkSize = ethash_cl_miner::defaultGlobalWorkSizeMultiplier * ethash_cl_miner::defaultLocalWorkSize; +unsigned ethash_cl_miner::s_msPerBatch = ethash_cl_miner::c_defaultMSPerBatch; +unsigned ethash_cl_miner::s_workgroupSize = ethash_cl_miner::c_defaultLocalWorkSize; +unsigned ethash_cl_miner::s_initialGlobalWorkSize = ethash_cl_miner::c_defaultGlobalWorkSizeMultiplier * ethash_cl_miner::c_defaultLocalWorkSize; bool ethash_cl_miner::searchForAllDevices(function _callback) { diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h index 06e8550b1..1dd1ea406 100644 --- a/libethash-cl/ethash_cl_miner.h +++ b/libethash-cl/ethash_cl_miner.h @@ -67,11 +67,11 @@ public: /* -- default values -- */ /// Default value of the local work size. Also known as workgroup size. - static const unsigned defaultLocalWorkSize; + static const unsigned c_defaultLocalWorkSize; /// Default value of the global work size as a multiplier of the local work size - static const unsigned defaultGlobalWorkSizeMultiplier; + static const unsigned c_defaultGlobalWorkSizeMultiplier; /// Default value of the milliseconds per global work size (per batch) - static const unsigned defaultMSPerBatch; + static const unsigned c_defaultMSPerBatch; private: From 35174e2798a7e92a63a6f2eaaf91efc64b0792b5 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 9 Jul 2015 11:36:05 +0200 Subject: [PATCH 266/290] More style: change const location --- libethash-cl/ethash_cl_miner.cpp | 6 +++--- libethash-cl/ethash_cl_miner.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 44cbf65e9..8e2a7dc4d 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -50,9 +50,9 @@ using namespace std; -const unsigned ethash_cl_miner::c_defaultLocalWorkSize = 64; -const unsigned ethash_cl_miner::c_defaultGlobalWorkSizeMultiplier = 4096; // * CL_DEFAULT_LOCAL_WORK_SIZE -const unsigned ethash_cl_miner::c_defaultMSPerBatch = 0; +unsigned const ethash_cl_miner::c_defaultLocalWorkSize = 64; +unsigned const ethash_cl_miner::c_defaultGlobalWorkSizeMultiplier = 4096; // * CL_DEFAULT_LOCAL_WORK_SIZE +unsigned const ethash_cl_miner::c_defaultMSPerBatch = 0; // TODO: If at any point we can use libdevcore in here then we should switch to using a LogChannel #define ETHCL_LOG(_contents) cout << "[OPENCL]:" << _contents << endl diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h index 1dd1ea406..094541cf9 100644 --- a/libethash-cl/ethash_cl_miner.h +++ b/libethash-cl/ethash_cl_miner.h @@ -67,11 +67,11 @@ public: /* -- default values -- */ /// Default value of the local work size. Also known as workgroup size. - static const unsigned c_defaultLocalWorkSize; + static unsigned const c_defaultLocalWorkSize; /// Default value of the global work size as a multiplier of the local work size - static const unsigned c_defaultGlobalWorkSizeMultiplier; + static unsigned const c_defaultGlobalWorkSizeMultiplier; /// Default value of the milliseconds per global work size (per batch) - static const unsigned c_defaultMSPerBatch; + static unsigned const c_defaultMSPerBatch; private: From 1863def3a1185eb2f3a18b4e0bc233652885a0c5 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 9 Jul 2015 00:00:30 +0200 Subject: [PATCH 267/290] ethminer no longer depends on boost Introducing an extra boolean argument to remove the boost::optional dependency. Too bad we have to wait for C++17 to get an std::optional --- ethminer/MinerAux.h | 6 +++++- libethash-cl/ethash_cl_miner.cpp | 5 +++-- libethash-cl/ethash_cl_miner.h | 6 +++--- libethcore/Ethash.cpp | 4 +++- libethcore/Ethash.h | 5 +++-- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 964a23635..e3fd585fe 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -211,7 +211,10 @@ public: else if (arg == "-G" || arg == "--opencl") m_minerType = MinerType::GPU; else if (arg == "--current-block" && i + 1 < argc) + { m_currentBlock = stol(argv[++i]); + m_currentBlockGiven = true; + } else if (arg == "--no-precompute") { m_precompute = false; @@ -306,6 +309,7 @@ public: m_openclDevice, m_clAllowCPU, m_extraGPUMemory, + m_currentBlockGiven, m_currentBlock )) exit(1); @@ -553,7 +557,7 @@ private: unsigned m_localWorkSize = ethash_cl_miner::c_defaultLocalWorkSize; unsigned m_msPerBatch = ethash_cl_miner::c_defaultMSPerBatch; #endif - boost::optional m_currentBlock; + uint64_t m_currentBlock = 0; // default value is 350MB of GPU memory for other stuff (windows system rendering, e.t.c.) unsigned m_extraGPUMemory = 350000000; diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 8e2a7dc4d..528898182 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -149,7 +149,8 @@ bool ethash_cl_miner::configureGPU( unsigned _msPerBatch, bool _allowCPU, unsigned _extraGPUMemory, - boost::optional _currentBlock + bool _currentBlockGiven, + uint64_t _currentBlock ) { s_workgroupSize = _localWorkSize; @@ -158,7 +159,7 @@ bool ethash_cl_miner::configureGPU( s_allowCPU = _allowCPU; s_extraRequiredGPUMem = _extraGPUMemory; // by default let's only consider the DAG of the first epoch - uint64_t dagSize = _currentBlock ? ethash_get_datasize(*_currentBlock) : 1073739904U; + uint64_t dagSize = _currentBlockGiven ? ethash_get_datasize(_currentBlock) : 1073739904U; uint64_t requiredSize = dagSize + _extraGPUMemory; return searchForAllDevices(_platformId, [&requiredSize](cl::Device const _device) -> bool { diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h index 094541cf9..da467bf9d 100644 --- a/libethash-cl/ethash_cl_miner.h +++ b/libethash-cl/ethash_cl_miner.h @@ -1,6 +1,6 @@ #pragma once -#define __CL_ENABLE_EXCEPTIONS +#define __CL_ENABLE_EXCEPTIONS #define CL_USE_DEPRECATED_OPENCL_2_0_APIS #if defined(__clang__) @@ -12,7 +12,6 @@ #include "cl.hpp" #endif -#include #include #include #include @@ -50,7 +49,8 @@ public: unsigned _msPerBatch, bool _allowCPU, unsigned _extraGPUMemory, - boost::optional _currentBlock + bool _currentBlockGiven, + uint64_t _currentBlock ); bool init( diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index fc0e07f12..f2c64fe7d 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -416,7 +416,8 @@ bool Ethash::GPUMiner::configureGPU( unsigned _deviceId, bool _allowCPU, unsigned _extraGPUMemory, - boost::optional _currentBlock + bool _currentBlockGiven, + uint64_t _currentBlock ) { s_platformId = _platformId; @@ -435,6 +436,7 @@ bool Ethash::GPUMiner::configureGPU( _msPerBatch, _allowCPU, _extraGPUMemory, + _currentBlockGiven, _currentBlock) ) { diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index e9ddf16ca..d00fe67fe 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -88,7 +88,7 @@ public: static unsigned instances() { return s_numInstances > 0 ? s_numInstances : std::thread::hardware_concurrency(); } static std::string platformInfo(); static void listDevices() {} - static bool configureGPU(unsigned, unsigned, unsigned, unsigned, unsigned, bool, unsigned, boost::optional) { return false; } + static bool configureGPU(unsigned, unsigned, unsigned, unsigned, unsigned, bool, unsigned, bool, uint64_t) { return false; } static void setNumInstances(unsigned _instances) { s_numInstances = std::min(_instances, std::thread::hardware_concurrency()); } protected: void kickOff() override @@ -125,7 +125,8 @@ public: unsigned _deviceId, bool _allowCPU, unsigned _extraGPUMemory, - boost::optional _currentBlock + bool _currentBlockGiven, + uint64_t _currentBlock ); static void setNumInstances(unsigned _instances) { s_numInstances = std::min(_instances, getNumDevices()); } From af6f5c3a13486883b5e9bafb40d60894ef684de6 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 9 Jul 2015 12:54:05 +0200 Subject: [PATCH 268/290] simplify clminer current block code --- ethminer/MinerAux.h | 4 ---- libethash-cl/ethash_cl_miner.cpp | 3 +-- libethash-cl/ethash_cl_miner.h | 1 - libethcore/Ethash.cpp | 2 -- libethcore/Ethash.h | 3 +-- 5 files changed, 2 insertions(+), 11 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index e3fd585fe..80886cd7a 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -211,10 +211,7 @@ public: else if (arg == "-G" || arg == "--opencl") m_minerType = MinerType::GPU; else if (arg == "--current-block" && i + 1 < argc) - { m_currentBlock = stol(argv[++i]); - m_currentBlockGiven = true; - } else if (arg == "--no-precompute") { m_precompute = false; @@ -309,7 +306,6 @@ public: m_openclDevice, m_clAllowCPU, m_extraGPUMemory, - m_currentBlockGiven, m_currentBlock )) exit(1); diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 528898182..942819ba8 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -149,7 +149,6 @@ bool ethash_cl_miner::configureGPU( unsigned _msPerBatch, bool _allowCPU, unsigned _extraGPUMemory, - bool _currentBlockGiven, uint64_t _currentBlock ) { @@ -159,7 +158,7 @@ bool ethash_cl_miner::configureGPU( s_allowCPU = _allowCPU; s_extraRequiredGPUMem = _extraGPUMemory; // by default let's only consider the DAG of the first epoch - uint64_t dagSize = _currentBlockGiven ? ethash_get_datasize(_currentBlock) : 1073739904U; + uint64_t dagSize = ethash_get_datasize(_currentBlock); uint64_t requiredSize = dagSize + _extraGPUMemory; return searchForAllDevices(_platformId, [&requiredSize](cl::Device const _device) -> bool { diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h index da467bf9d..fb28dc04b 100644 --- a/libethash-cl/ethash_cl_miner.h +++ b/libethash-cl/ethash_cl_miner.h @@ -49,7 +49,6 @@ public: unsigned _msPerBatch, bool _allowCPU, unsigned _extraGPUMemory, - bool _currentBlockGiven, uint64_t _currentBlock ); diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index f2c64fe7d..9be76926d 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -416,7 +416,6 @@ bool Ethash::GPUMiner::configureGPU( unsigned _deviceId, bool _allowCPU, unsigned _extraGPUMemory, - bool _currentBlockGiven, uint64_t _currentBlock ) { @@ -436,7 +435,6 @@ bool Ethash::GPUMiner::configureGPU( _msPerBatch, _allowCPU, _extraGPUMemory, - _currentBlockGiven, _currentBlock) ) { diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index d00fe67fe..7ffd887d0 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -88,7 +88,7 @@ public: static unsigned instances() { return s_numInstances > 0 ? s_numInstances : std::thread::hardware_concurrency(); } static std::string platformInfo(); static void listDevices() {} - static bool configureGPU(unsigned, unsigned, unsigned, unsigned, unsigned, bool, unsigned, bool, uint64_t) { return false; } + static bool configureGPU(unsigned, unsigned, unsigned, unsigned, unsigned, bool, unsigned, uint64_t) { return false; } static void setNumInstances(unsigned _instances) { s_numInstances = std::min(_instances, std::thread::hardware_concurrency()); } protected: void kickOff() override @@ -125,7 +125,6 @@ public: unsigned _deviceId, bool _allowCPU, unsigned _extraGPUMemory, - bool _currentBlockGiven, uint64_t _currentBlock ); static void setNumInstances(unsigned _instances) { s_numInstances = std::min(_instances, getNumDevices()); } From 1d5a25991d9d610d06beac3b53010494160dfd1e Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 9 Jul 2015 14:39:35 +0200 Subject: [PATCH 269/290] Prevent handles call on shutdown --- libethcore/Common.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libethcore/Common.h b/libethcore/Common.h index fe9692ed3..296f0d01d 100644 --- a/libethcore/Common.h +++ b/libethcore/Common.h @@ -157,7 +157,8 @@ public: ~Signal() { for (auto const& h : m_fire) - h.second->reset(); + if (auto l = h.second.lock()) + l->reset(); } std::shared_ptr add(Callback const& _h) @@ -168,10 +169,15 @@ public: return h; } - void operator()(Args&... _args) { for (auto const& f: m_fire) f.second->fire(std::forward(_args)...); } + void operator()(Args&... _args) + { + for (auto const& f: m_fire) + if (auto h = f.second.lock()) + h->fire(std::forward(_args)...); + } private: - std::map> m_fire; + std::map> m_fire; }; template using Handler = std::shared_ptr::HandlerAux>; From bb3d31c8483640bbc2a1f97a212a7fa6c9e1a4e6 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 8 Jul 2015 19:32:43 +0200 Subject: [PATCH 270/290] Versioning for Solidity. --- libsolidity/Version.cpp | 39 +++++++++++++++++++++++++++++++++++ libsolidity/Version.h | 36 ++++++++++++++++++++++++++++++++ solc/CommandLineInterface.cpp | 10 ++++++--- 3 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 libsolidity/Version.cpp create mode 100644 libsolidity/Version.h diff --git a/libsolidity/Version.cpp b/libsolidity/Version.cpp new file mode 100644 index 000000000..971fb334b --- /dev/null +++ b/libsolidity/Version.cpp @@ -0,0 +1,39 @@ +/* + 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 Christian + * @date 2015 + * Versioning. + */ + +#include +#include +#include +#include + +using namespace dev; +using namespace dev::solidity; +using namespace std; + +char const* dev::solidity::VersionNumber = "0.1.0"; +extern string const dev::solidity::VersionString = + string(dev::solidity::VersionNumber) + + "-" + + string(DEV_QUOTED(ETH_COMMIT_HASH)).substr(0, 8) + + (ETH_CLEAN_REPO ? "" : "*") + + "/" DEV_QUOTED(ETH_BUILD_TYPE) "-" DEV_QUOTED(ETH_BUILD_PLATFORM); + diff --git a/libsolidity/Version.h b/libsolidity/Version.h new file mode 100644 index 000000000..6e00f07b4 --- /dev/null +++ b/libsolidity/Version.h @@ -0,0 +1,36 @@ +/* + 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 Christian + * @date 2015 + * Versioning. + */ + +#pragma once + +#include + +namespace dev +{ +namespace solidity +{ + +extern char const* VersionNumber; +extern std::string const VersionString; + +} +} diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index c95f34f62..00bf2ab33 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -81,9 +82,12 @@ static set const g_combinedJsonArgs{ static void version() { - cout << "solc, the solidity compiler commandline interface " << dev::Version << endl - << " by Christian and Lefteris , (c) 2014." << endl - << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl; + cout << + "solc, the solidity compiler commandline interface" << + endl << + "Version: " << + dev::solidity::VersionString << + endl; exit(0); } From 9c3983d1c655915fa4d81c4c5ff4aff93640f174 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 8 Jul 2015 01:13:56 +0200 Subject: [PATCH 271/290] Flexible string literals, convertible to bytesX, bytes and string. --- libsolidity/CompilerUtils.cpp | 138 ++++++++++++++---- libsolidity/CompilerUtils.h | 7 +- libsolidity/ExpressionCompiler.cpp | 13 +- libsolidity/LValue.cpp | 2 +- libsolidity/Types.cpp | 41 ++++-- libsolidity/Types.h | 36 ++++- mix/CodeModel.cpp | 3 +- test/libsolidity/SolidityEndToEndTest.cpp | 45 ++++-- .../SolidityNameAndTypeResolution.cpp | 15 +- test/libsolidity/solidityExecutionFramework.h | 6 + 10 files changed, 239 insertions(+), 67 deletions(-) diff --git a/libsolidity/CompilerUtils.cpp b/libsolidity/CompilerUtils.cpp index ed6a6cf7c..297e6aa09 100644 --- a/libsolidity/CompilerUtils.cpp +++ b/libsolidity/CompilerUtils.cpp @@ -113,6 +113,16 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound solAssert(ref->location() == DataLocation::Memory, ""); storeInMemoryDynamic(IntegerType(256), _padToWordBoundaries); } + else if (auto str = dynamic_cast(&_type)) + { + m_context << eth::Instruction::DUP1; + storeStringData(bytesConstRef(str->value())); + if (_padToWordBoundaries) + m_context << u256(((str->value().size() + 31) / 32) * 32); + else + m_context << u256(str->value().size()); + m_context << eth::Instruction::ADD; + } else { unsigned numBytes = prepareMemoryStore(_type, _padToWordBoundaries); @@ -169,7 +179,8 @@ void CompilerUtils::encodeToMemory( TypePointer type = targetType; if ( _givenTypes[i]->dataStoredIn(DataLocation::Storage) || - _givenTypes[i]->dataStoredIn(DataLocation::CallData) + _givenTypes[i]->dataStoredIn(DataLocation::CallData) || + _givenTypes[i]->getCategory() == Type::Category::StringLiteral ) type = _givenTypes[i]; // delay conversion else @@ -192,36 +203,48 @@ void CompilerUtils::encodeToMemory( solAssert(!!targetType, "Externalable type expected."); if (targetType->isDynamicallySized() && !_copyDynamicDataInPlace) { - solAssert(_givenTypes[i]->getCategory() == Type::Category::Array, "Unknown dynamic type."); - auto const& arrayType = dynamic_cast(*_givenTypes[i]); // copy tail pointer (=mem_end - mem_start) to memory m_context << eth::dupInstruction(2 + dynPointers) << eth::Instruction::DUP2; m_context << eth::Instruction::SUB; m_context << eth::dupInstruction(2 + dynPointers - thisDynPointer); m_context << eth::Instruction::MSTORE; - // now copy the array - copyToStackTop(argSize - stackPos + dynPointers + 2, arrayType.getSizeOnStack()); - // stack: ... - // copy length to memory - m_context << eth::dupInstruction(1 + arrayType.getSizeOnStack()); - if (arrayType.location() == DataLocation::CallData) - m_context << eth::Instruction::DUP2; // length is on stack - else if (arrayType.location() == DataLocation::Storage) - m_context << eth::Instruction::DUP3 << eth::Instruction::SLOAD; + // stack: ... + if (_givenTypes[i]->getCategory() == Type::Category::StringLiteral) + { + auto const& strType = dynamic_cast(*_givenTypes[i]); + m_context << u256(strType.value().size()); + storeInMemoryDynamic(IntegerType(256), true); + // stack: ... + storeInMemoryDynamic(strType, _padToWordBoundaries); + } else { - solAssert(arrayType.location() == DataLocation::Memory, ""); - m_context << eth::Instruction::DUP2 << eth::Instruction::MLOAD; + solAssert(_givenTypes[i]->getCategory() == Type::Category::Array, "Unknown dynamic type."); + auto const& arrayType = dynamic_cast(*_givenTypes[i]); + // now copy the array + copyToStackTop(argSize - stackPos + dynPointers + 2, arrayType.getSizeOnStack()); + // stack: ... + // copy length to memory + m_context << eth::dupInstruction(1 + arrayType.getSizeOnStack()); + if (arrayType.location() == DataLocation::CallData) + m_context << eth::Instruction::DUP2; // length is on stack + else if (arrayType.location() == DataLocation::Storage) + m_context << eth::Instruction::DUP3 << eth::Instruction::SLOAD; + else + { + solAssert(arrayType.location() == DataLocation::Memory, ""); + m_context << eth::Instruction::DUP2 << eth::Instruction::MLOAD; + } + // stack: ... + storeInMemoryDynamic(IntegerType(256), true); + // stack: ... + // copy the new memory pointer + m_context << eth::swapInstruction(arrayType.getSizeOnStack() + 1) << eth::Instruction::POP; + // stack: ... + // copy data part + ArrayUtils(m_context).copyArrayToMemory(arrayType, _padToWordBoundaries); + // stack: ... } - // stack: ... - storeInMemoryDynamic(IntegerType(256), true); - // stack: ... - // copy the new memory pointer - m_context << eth::swapInstruction(arrayType.getSizeOnStack() + 1) << eth::Instruction::POP; - // stack: ... - // copy data part - ArrayUtils(m_context).copyArrayToMemory(arrayType, _padToWordBoundaries); - // stack: ... thisDynPointer++; } @@ -269,22 +292,22 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp // conversion from bytes to integer. no need to clean the high bit // only to shift right because of opposite alignment IntegerType const& targetIntegerType = dynamic_cast(_targetType); - m_context << (u256(1) << (256 - typeOnStack.getNumBytes() * 8)) << eth::Instruction::SWAP1 << eth::Instruction::DIV; - if (targetIntegerType.getNumBits() < typeOnStack.getNumBytes() * 8) - convertType(IntegerType(typeOnStack.getNumBytes() * 8), _targetType, _cleanupNeeded); + m_context << (u256(1) << (256 - typeOnStack.numBytes() * 8)) << eth::Instruction::SWAP1 << eth::Instruction::DIV; + if (targetIntegerType.getNumBits() < typeOnStack.numBytes() * 8) + convertType(IntegerType(typeOnStack.numBytes() * 8), _targetType, _cleanupNeeded); } else { // clear lower-order bytes for conversion to shorter bytes - we always clean solAssert(targetTypeCategory == Type::Category::FixedBytes, "Invalid type conversion requested."); FixedBytesType const& targetType = dynamic_cast(_targetType); - if (targetType.getNumBytes() < typeOnStack.getNumBytes()) + if (targetType.numBytes() < typeOnStack.numBytes()) { - if (targetType.getNumBytes() == 0) + if (targetType.numBytes() == 0) m_context << eth::Instruction::DUP1 << eth::Instruction::XOR; else { - m_context << (u256(1) << (256 - targetType.getNumBytes() * 8)); + m_context << (u256(1) << (256 - targetType.numBytes() * 8)); m_context << eth::Instruction::DUP1 << eth::Instruction::SWAP2; m_context << eth::Instruction::DIV << eth::Instruction::MUL; } @@ -306,9 +329,9 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp // only to shift left because of opposite alignment FixedBytesType const& targetBytesType = dynamic_cast(_targetType); if (auto typeOnStack = dynamic_cast(&_typeOnStack)) - if (targetBytesType.getNumBytes() * 8 > typeOnStack->getNumBits()) + if (targetBytesType.numBytes() * 8 > typeOnStack->getNumBits()) cleanHigherOrderBits(*typeOnStack); - m_context << (u256(1) << (256 - targetBytesType.getNumBytes() * 8)) << eth::Instruction::MUL; + m_context << (u256(1) << (256 - targetBytesType.numBytes() * 8)) << eth::Instruction::MUL; } else if (targetTypeCategory == Type::Category::Enum) // just clean @@ -340,6 +363,37 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp } } break; + case Type::Category::StringLiteral: + { + auto const& literalType = dynamic_cast(_typeOnStack); + string const& value = literalType.value(); + bytesConstRef data(value); + if (targetTypeCategory == Type::Category::FixedBytes) + { + solAssert(data.size() <= 32, ""); + m_context << h256::Arith(h256(data, h256::AlignLeft)); + } + else if (targetTypeCategory == Type::Category::Array) + { + auto const& arrayType = dynamic_cast(_targetType); + solAssert(arrayType.isByteArray(), ""); + u256 storageSize(32 + ((data.size() + 31) / 32) * 32); + m_context << storageSize; + allocateMemory(); + // stack: mempos + m_context << eth::Instruction::DUP1 << u256(data.size()); + storeInMemoryDynamic(IntegerType(256)); + // stack: mempos datapos + storeStringData(data); + break; + } + else + solAssert( + false, + "Invalid conversion from string literal to " + _targetType.toString(false) + " requested." + ); + break; + } case Type::Category::Array: { solAssert(targetTypeCategory == stackTypeCategory, ""); @@ -606,6 +660,28 @@ void CompilerUtils::computeHashStatic() m_context << u256(32) << u256(0) << eth::Instruction::SHA3; } +void CompilerUtils::storeStringData(bytesConstRef _data) +{ + //@todo provide both alternatives to the optimiser + // stack: mempos + if (_data.size() <= 128) + { + for (unsigned i = 0; i < _data.size(); i += 32) + { + m_context << h256::Arith(h256(_data.cropped(i), h256::AlignLeft)); + storeInMemoryDynamic(IntegerType(256)); + } + m_context << eth::Instruction::POP; + } + else + { + // stack: mempos mempos_data + m_context.appendData(_data.toBytes()); + m_context << u256(_data.size()) << eth::Instruction::SWAP2; + m_context << eth::Instruction::CODECOPY; + } +} + unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWordBoundaries) { unsigned numBytes = _type.getCalldataEncodedSize(_padToWordBoundaries); diff --git a/libsolidity/CompilerUtils.h b/libsolidity/CompilerUtils.h index 7dd44da8f..dbb00a1de 100644 --- a/libsolidity/CompilerUtils.h +++ b/libsolidity/CompilerUtils.h @@ -148,7 +148,12 @@ private: /// Address of the precompiled identity contract. static const unsigned identityContractAddress; - //// Appends code that cleans higher-order bits for integer types. + /// Stores the given string in memory. + /// Stack pre: mempos + /// Stack post: + void storeStringData(bytesConstRef _data); + + /// Appends code that cleans higher-order bits for integer types. void cleanHigherOrderBits(IntegerType const& _typeOnStack); /// Prepares the given type for storing in memory by shifting it if necessary. diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 13cd40327..058358187 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -158,6 +158,11 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) utils().convertType(*type, *_assignment.getType()); type = _assignment.getType(); } + else + { + utils().convertType(*type, *type->mobileType()); + type = type->mobileType(); + } _assignment.getLeftHandSide().accept(*this); solAssert(!!m_currentLValue, "LValue not retrieved."); @@ -898,13 +903,15 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier) void ExpressionCompiler::endVisit(Literal const& _literal) { CompilerContext::LocationSetter locationSetter(m_context, _literal); - switch (_literal.getType()->getCategory()) + TypePointer type = _literal.getType(); + switch (type->getCategory()) { case Type::Category::IntegerConstant: case Type::Category::Bool: - case Type::Category::FixedBytes: - m_context << _literal.getType()->literalValue(&_literal); + m_context << type->literalValue(&_literal); break; + case Type::Category::StringLiteral: + break; // will be done during conversion default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Only integer, boolean and string literals implemented for now.")); } diff --git a/libsolidity/LValue.cpp b/libsolidity/LValue.cpp index 7b5879e44..82701ea95 100644 --- a/libsolidity/LValue.cpp +++ b/libsolidity/LValue.cpp @@ -209,7 +209,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc // stack: value storage_ref cleared_value multiplier value if (m_dataType.getCategory() == Type::Category::FixedBytes) m_context - << (u256(0x1) << (256 - 8 * dynamic_cast(m_dataType).getNumBytes())) + << (u256(0x1) << (256 - 8 * dynamic_cast(m_dataType).numBytes())) << eth::Instruction::SWAP1 << eth::Instruction::DIV; else if ( m_dataType.getCategory() == Type::Category::Integer && diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 5a949299e..3ea9caa7d 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -212,8 +212,7 @@ TypePointer Type::forLiteral(Literal const& _literal) case Token::Number: return make_shared(_literal); case Token::StringLiteral: - //@todo put larger strings into dynamic strings - return FixedBytesType::smallestTypeForLiteral(_literal.getValue()); + return make_shared(_literal); default: return shared_ptr(); } @@ -378,7 +377,7 @@ bool IntegerConstantType::isImplicitlyConvertibleTo(Type const& _convertTo) cons else if (_convertTo.getCategory() == Category::FixedBytes) { FixedBytesType const& fixedBytes = dynamic_cast(_convertTo); - return fixedBytes.getNumBytes() * 8 >= getIntegerType()->getNumBits(); + return fixedBytes.numBytes() * 8 >= getIntegerType()->getNumBits(); } else return false; @@ -530,6 +529,33 @@ shared_ptr IntegerConstantType::getIntegerType() const ); } +StringLiteralType::StringLiteralType(Literal const& _literal): + m_value(_literal.getValue()) +{ +} + +bool StringLiteralType::isImplicitlyConvertibleTo(Type const& _convertTo) const +{ + if (auto fixedBytes = dynamic_cast(&_convertTo)) + return size_t(fixedBytes->numBytes()) >= m_value.size(); + else if (auto arrayType = dynamic_cast(&_convertTo)) + return arrayType->isByteArray(); + else + return false; +} + +bool StringLiteralType::operator==(const Type& _other) const +{ + if (_other.getCategory() != getCategory()) + return false; + return m_value == dynamic_cast(_other).m_value; +} + +TypePointer StringLiteralType::mobileType() const +{ + return make_shared(DataLocation::Memory, true); +} + shared_ptr FixedBytesType::smallestTypeForLiteral(string const& _literal) { if (_literal.length() <= 32) @@ -590,15 +616,6 @@ bool FixedBytesType::operator==(Type const& _other) const return other.m_bytes == m_bytes; } -u256 FixedBytesType::literalValue(const Literal* _literal) const -{ - solAssert(_literal, ""); - u256 value = 0; - for (char c: _literal->getValue()) - value = (value << 8) | byte(c); - return value << ((32 - _literal->getValue().length()) * 8); -} - bool BoolType::isExplicitlyConvertibleTo(Type const& _convertTo) const { // conversion to integer is fine, but not to address diff --git a/libsolidity/Types.h b/libsolidity/Types.h index ba53a913b..e17a262c6 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -131,7 +131,7 @@ class Type: private boost::noncopyable, public std::enable_shared_from_this(_type); r.type = SolidityType::Type::Bytes; - r.size = static_cast(b->getNumBytes()); + r.size = static_cast(b->numBytes()); } break; case Type::Category::Contract: @@ -608,6 +608,7 @@ SolidityType CodeModel::nodeType(dev::solidity::Type const* _type) break; case Type::Category::Function: case Type::Category::IntegerConstant: + case Type::Category::StringLiteral: case Type::Category::Magic: case Type::Category::Mapping: case Type::Category::Modifier: diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 3ddb05528..ad2175461 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -564,20 +564,6 @@ BOOST_AUTO_TEST_CASE(strings) BOOST_CHECK(callContractFunction("pipeThrough(bytes2,bool)", string("\0\x02", 2), true) == encodeArgs(string("\0\x2", 2), true)); } -BOOST_AUTO_TEST_CASE(empty_string_on_stack) -{ - char const* sourceCode = R"( - contract test { - function run() external returns(bytes2 ret) { - var y = ""; - ret = y; - } - } - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("run()") == encodeArgs(byte(0x00))); -} - BOOST_AUTO_TEST_CASE(inc_dec_operators) { char const* sourceCode = R"( @@ -5001,6 +4987,37 @@ BOOST_AUTO_TEST_CASE(struct_named_constructor) BOOST_CHECK(callContractFunction("s()") == encodeArgs(u256(1), true)); } +BOOST_AUTO_TEST_CASE(literal_strings) +{ + char const* sourceCode = R"( + contract Test { + string public long; + string public medium; + string public short; + string public empty; + function f() returns (string) { + long = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; + medium = "01234567890123456789012345678901234567890123456789012345678901234567890123456789"; + short = "123"; + empty = ""; + return "Hello, World!"; + } + } + )"; + compileAndRun(sourceCode, 0, "Test"); + string longStr = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; + string medium = "01234567890123456789012345678901234567890123456789012345678901234567890123456789"; + string shortStr = "123"; + string hello = "Hello, World!"; + + BOOST_CHECK(callContractFunction("f()") == encodeDyn(hello)); + BOOST_CHECK(callContractFunction("long()") == encodeDyn(longStr)); + BOOST_CHECK(callContractFunction("medium()") == encodeDyn(medium)); + BOOST_CHECK(callContractFunction("short()") == encodeDyn(shortStr)); + BOOST_CHECK(callContractFunction("empty()") == encodeDyn(string())); +} + + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 50fcdbbe5..1e40ee4f6 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE(large_string_literal) char const* text = "contract test {\n" " function f() { var x = \"123456789012345678901234567890123\"; }" "}\n"; - BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); } BOOST_AUTO_TEST_CASE(balance) @@ -2097,6 +2097,19 @@ BOOST_AUTO_TEST_CASE(struct_named_constructor) BOOST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCode)); } +BOOST_AUTO_TEST_CASE(literal_strings) +{ + char const* text = R"( + contract Foo { + function f() { + string memory long = "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; + string memory short = "123"; + } + } + )"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/solidityExecutionFramework.h b/test/libsolidity/solidityExecutionFramework.h index 200940a43..03a201c72 100644 --- a/test/libsolidity/solidityExecutionFramework.h +++ b/test/libsolidity/solidityExecutionFramework.h @@ -145,6 +145,12 @@ public: { return bytes(); } + //@todo might be extended in the future + template + static bytes encodeDyn(Arg const& _arg) + { + return encodeArgs(u256(0x20), u256(_arg.size()), _arg); + } private: template From 8c43be62103ea1b0135e8dc5611088ff62528944 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 9 Jul 2015 20:45:13 +0200 Subject: [PATCH 272/290] update to latest version of wallet code --- .../StateTestsFiller/stWalletTestFiller.json | 98 +++++++++---------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/test/libethereum/StateTestsFiller/stWalletTestFiller.json b/test/libethereum/StateTestsFiller/stWalletTestFiller.json index de02277e8..93f898a4a 100644 --- a/test/libethereum/StateTestsFiller/stWalletTestFiller.json +++ b/test/libethereum/StateTestsFiller/stWalletTestFiller.json @@ -18,8 +18,8 @@ } }, "transaction" : { - "data" : "600160008181558180553373ffffffffffffffffffffffffffffffffffffffff166003819055815261010260205260408120919091556108ae90819061004590396000f3007c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", - "gasLimit" : "0x03d0c3", + "data" : "606060409081526001600081815581805533600160a060020a0316600381905581526101026020529182205561090a90819061003b90396000f300606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "gasLimit" : "0x03e9c1", "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", @@ -47,8 +47,8 @@ } }, "transaction" : { - "data" : "600160008181558180553373ffffffffffffffffffffffffffffffffffffffff166003819055815261010260205260408120919091556108ae90819061004590396000f3007c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", - "gasLimit" : "0x0a98b3", + "data" : "606060409081526001600081815581805533600160a060020a0316600381905581526101026020529182205561090a90819061003b90396000f300606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "gasLimit" : "0x0af991", "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", @@ -76,8 +76,8 @@ } }, "transaction" : { - "data" : "600160008181558180553373ffffffffffffffffffffffffffffffffffffffff166003819055815261010260205260408120919091556108ae90819061004590396000f3007c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", - "gasLimit" : "0x0a98b4", + "data" : "606060409081526001600081815581805533600160a060020a0316600381905581526101026020529182205561090a90819061003b90396000f300606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "gasLimit" : "10000000", "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", @@ -98,7 +98,7 @@ "pre" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "code" : "0x606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -138,7 +138,7 @@ "pre" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "code" : "0x606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -178,7 +178,7 @@ "pre" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "code" : "0x606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -218,7 +218,7 @@ "pre" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "code" : "0x606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -258,7 +258,7 @@ "pre" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "code" : "0x606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -298,7 +298,7 @@ "pre" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "code" : "0x606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -338,7 +338,7 @@ "pre" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "code" : "0x606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -378,7 +378,7 @@ "pre" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "code" : "0x606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -425,7 +425,7 @@ "pre" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "code" : "0x606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -465,7 +465,7 @@ "pre" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "code" : "0x606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -505,7 +505,7 @@ "pre" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "code" : "0x606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -545,7 +545,7 @@ "pre" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "code" : "0x606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -585,7 +585,7 @@ "pre" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "code" : "0x606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -625,7 +625,7 @@ "pre" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "code" : "0x606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -665,7 +665,7 @@ "pre" : { "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "code" : "0x606060405236156100775760e060020a6000350463173825d981146100795780632f54bf6e146100d55780634123cb6b146100f95780637065cb4814610102578063746c917114610136578063b75c7dc61461013f578063ba51a6df1461016f578063c2cf7326146101a3578063f00d4b5d146101e3575b005b610077600435600060003643604051808484808284375050509091019081526040519081900360200190209050610529815b600160a060020a033316600090815261010260205260408120548180808381141561066f57610806565b61021c6004355b600160a060020a0316600090815261010260205260408120541190565b61021c60015481565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506104a1816100ab565b61021c60005481565b610077600435600160a060020a033316600090815261010260205260408120549080808381141561022e576102b0565b610077600435600036436040518084848082843750505090910190815260405190819003602001902090506105e8816100ab565b61021c600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548290818181141561064157610665565b61007760043560243560006000364360405180848480828437505050909101908152604051908190036020019020905061033a816100ab565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156102b05781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b1561033357610348836100dc565b156103535750610335565b600160a060020a03841660009081526101026020526040812054925082141561037c5750610335565b6102b75b6101045460005b818110156107b557610104805482908110156100025760009182526000805160206108ea8339815191520154146103fa576101048054610103916000918490811015610002576000805160206108ea83398151915201548252506020919091526040812081815560018101829055600201555b600101610387565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561049c576104af826100dc565b156104ba575061049e565b6104c2610380565b60015460fa90106104d7576104d56104ec565b505b60015460fa9010610402575061049e565b6105a65b600060015b6001548110156107ef575b6001548110801561051c5750600281610100811015610002570154600014155b1561080f576001016104fc565b1561033557600160a060020a038316600090815261010260205260408120549250821415610557575061049c565b6001600160005054036000600050541115610572575061049c565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556104e8610380565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561049c576001548211156105fd575061049e565b600082905561060a610380565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106605760009450610665565b600194505b5050505092915050565b60008681526101036020526040812080549094509092508214156106f85781548355600183810183905561010480549182018082558280158290116106c7578183600052602060002091820191016106c791906107db565b505050600284018190556101048054889290811015610002576000919091526000805160206108ea83398151915201555b506001820154600284900a908116600014156108065760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18254600190116107f35760008681526101036020526040902060020154610104805490919081101561000257604060009081206000805160206108ea83398151915292909201819055808255600180830182905560029092015595506108069050565b6101048054600080835591909152610335906000805160206108ea833981519152908101905b808211156107ef57600081556001016107db565b5090565b8254600019018355600183018054821790555b50505050919050565b5b6001805411801561083257506001546002906101008110156100025701546000145b156108465760018054600019019055610810565b600154811080156108695750600154600290610100811015610002570154600014155b801561088357506002816101008110156100025701546000145b156108e457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b6104f156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -712,8 +712,8 @@ } }, "transaction" : { - "data" : "600160008181558180553373ffffffffffffffffffffffffffffffffffffffff16600381905581526101026020526040902055620151804204610107556109158061004b6000396000f3007c01000000000000000000000000000000000000000000000000000000006000350463173825d9811461007b5780632f54bf6e146100cd5780635c52c2f5146100fe5780637065cb4814610118578063b20d30a914610135578063b75c7dc614610152578063ba51a6df1461018f578063f00d4b5d146101ac57005b6101ce60043560006040600036808284379091209050610472815b73ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054818080838114156105bc5761071e565b6101d46004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b6101ce60406000368082843790912090506105ae81610096565b6101ce60043560406000368082843790912090506103c981610096565b6101ce60043560406000368082843790912090506105a281610096565b6101ce60043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156101de57610260565b6101ce600435604060003680828437909120905061055181610096565b6101ce600435602435600060406000368082843790912090506102d381610096565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561026057815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b156102cc576102e1836100d4565b156102ec57506102ce565b73ffffffffffffffffffffffffffffffffffffffff841660009081526101026020526040812054925082141561032257506102ce565b6103445b6101045460005b81811015610873576101048054829081106108bb57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061026757005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103c4576103d7826100d4565b156103e257506103c6565b6103ea610326565b60015460fa90101515610401576103ff610418565b505b60015460fa9010151561044257506103c6565b6105095b600060015b60015481101561075e575b600154811080156107ba575060028161010081106107b357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061036957005b156102ce5773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104ad57506103c4565b60016001600050540360006000505411156104c857506103c4565b600060028361010081106104d857005b015573ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812055610414610326565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156103c45760015482111561056657506103c6565b6000829055610573610326565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b156103c4575061010655565b156103c65760006101055550565b60008681526101036020526040812080549094509092508214156106475781548355600183810183905561010480549182018082558280158290116106d3578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106d15760008155600101610626565b6000918252602090912001555b506001820154600284900a9081166000141561071e5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156106ed57600086815261010360205261010480546040909220600201549091811061072757005b505b505050600284018190556101048054889290811061063a57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600091825260208083209091018290558782526101039052604081208181556001818101839055600290910191909155945061071e565b5090565b01546000145b156107c757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b600180541180156107685750600154600290610100811061076257005b0154600014155b1561079657600101610428565b600154811080156107eb575060015460029061010081106107e457005b0154600014155b80156108065750600281610100811061080057005b01546000145b1561081f57600154600290610100811061082457005b01555b61041d565b0154600282610100811061083457005b0155806101026000600283610100811061084a57005b015481526020810191909152604001600090812091909155600154600290610100811061081c57005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156102cc57600081556001016108a7565b600091825260208220015414151561090d57610104805461010391600091849081106108e357005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b60010161032d56", - "gasLimit" : "0x0b5291", + "data" : "606060409081526001600081815581805533600160a060020a0316600381905581526101026020529190912055620151804204610107556109b4806100456000396000f300606060405236156100985760e060020a6000350463173825d9811461009a5780632f54bf6e146100f65780634123cb6b1461011a5780635c52c2f5146101235780637065cb4814610154578063746c917114610188578063b20d30a914610191578063b75c7dc6146101c5578063ba51a6df146101f5578063c2cf732614610229578063f00d4b5d14610269578063f1736d86146102a2575b005b6100986004356000600036436040518084848082843750505090910190815260405190819003602001902090506105b9815b600160a060020a0333166000908152610102602052604081205481808083811415610719576108b0565b6102ac6004355b600160a060020a0316600090815261010260205260408120541190565b6102ac60015481565b6100986000364360405180848480828437505050909101908152604051908190036020019020905061070b816100cc565b61009860043560003643604051808484808284375050509091019081526040519081900360200190209050610531816100cc565b6102ac60005481565b610098600435600036436040518084848082843750505090910190815260405190819003602001902090506106ff816100cc565b610098600435600160a060020a03331660009081526101026020526040812054908080838114156102be57610340565b61009860043560003643604051808484808284375050509091019081526040519081900360200190209050610678816100cc565b6102ac600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156106d1576106f5565b6100986004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506103ca816100cc565b6102ac6101055481565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156103405781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156103c3576103d8836100fd565b156103e357506103c5565b600160a060020a03841660009081526101026020526040812054925082141561040c57506103c5565b6103475b6101045460005b8181101561085f576101048054829081101561000257600091825260008051602061099483398151915201541461048a5761010480546101039160009184908110156100025760008051602061099483398151915201548252506020919091526040812081815560018101829055600201555b600101610417565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561052c5761053f826100fd565b1561054a575061052e565b610552610410565b60015460fa90106105675761056561057c565b505b60015460fa9010610492575061052e565b6106365b600060015b600154811015610899575b600154811080156105ac5750600281610100811015610002570154600014155b156108b95760010161058c565b156103c557600160a060020a0383166000908152610102602052604081205492508214156105e7575061052c565b6001600160005054036000600050541115610602575061052c565b600060028361010081101561000257508301819055600160a060020a03841681526101026020526040812055610578610410565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561052c5760015482111561068d575061052e565b600082905561069a610410565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106f057600094506106f5565b600194505b5050505092915050565b1561052c575061010555565b1561052e5760006101065550565b60008681526101036020526040812080549094509092508214156107a2578154835560018381018390556101048054918201808255828015829011610771578183600052602060002091820191016107719190610885565b5050506002840181905561010480548892908110156100025760009190915260008051602061099483398151915201555b506001820154600284900a908116600014156108b05760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a182546001901161089d57600086815261010360205260409020600201546101048054909190811015610002576040600090812060008051602061099483398151915292909201819055808255600180830182905560029092015595506108b09050565b61010480546000808355919091526103c590600080516020610994833981519152908101905b808211156108995760008155600101610885565b5090565b8254600019018355600183018054821790555b50505050919050565b5b600180541180156108dc57506001546002906101008110156100025701546000145b156108f057600180546000190190556108ba565b600154811080156109135750600154600290610100811015610002570154600014155b801561092d57506002816101008110156100025701546000145b1561098e57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61058156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "gasLimit" : "0x0bfabb", "gasPrice" : "1", "nonce" : "1", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", @@ -741,8 +741,8 @@ } }, "transaction" : { - "data" : "600160008181558180553373ffffffffffffffffffffffffffffffffffffffff16600381905581526101026020526040902055620151804204610107556109158061004b6000396000f3007c01000000000000000000000000000000000000000000000000000000006000350463173825d9811461007b5780632f54bf6e146100cd5780635c52c2f5146100fe5780637065cb4814610118578063b20d30a914610135578063b75c7dc614610152578063ba51a6df1461018f578063f00d4b5d146101ac57005b6101ce60043560006040600036808284379091209050610472815b73ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054818080838114156105bc5761071e565b6101d46004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b6101ce60406000368082843790912090506105ae81610096565b6101ce60043560406000368082843790912090506103c981610096565b6101ce60043560406000368082843790912090506105a281610096565b6101ce60043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156101de57610260565b6101ce600435604060003680828437909120905061055181610096565b6101ce600435602435600060406000368082843790912090506102d381610096565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561026057815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b156102cc576102e1836100d4565b156102ec57506102ce565b73ffffffffffffffffffffffffffffffffffffffff841660009081526101026020526040812054925082141561032257506102ce565b6103445b6101045460005b81811015610873576101048054829081106108bb57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061026757005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103c4576103d7826100d4565b156103e257506103c6565b6103ea610326565b60015460fa90101515610401576103ff610418565b505b60015460fa9010151561044257506103c6565b6105095b600060015b60015481101561075e575b600154811080156107ba575060028161010081106107b357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061036957005b156102ce5773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104ad57506103c4565b60016001600050540360006000505411156104c857506103c4565b600060028361010081106104d857005b015573ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812055610414610326565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156103c45760015482111561056657506103c6565b6000829055610573610326565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b156103c4575061010655565b156103c65760006101055550565b60008681526101036020526040812080549094509092508214156106475781548355600183810183905561010480549182018082558280158290116106d3578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106d15760008155600101610626565b6000918252602090912001555b506001820154600284900a9081166000141561071e5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156106ed57600086815261010360205261010480546040909220600201549091811061072757005b505b505050600284018190556101048054889290811061063a57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600091825260208083209091018290558782526101039052604081208181556001818101839055600290910191909155945061071e565b5090565b01546000145b156107c757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b600180541180156107685750600154600290610100811061076257005b0154600014155b1561079657600101610428565b600154811080156107eb575060015460029061010081106107e457005b0154600014155b80156108065750600281610100811061080057005b01546000145b1561081f57600154600290610100811061082457005b01555b61041d565b0154600282610100811061083457005b0155806101026000600283610100811061084a57005b015481526020810191909152604001600090812091909155600154600290610100811061081c57005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156102cc57600081556001016108a7565b600091825260208220015414151561090d57610104805461010391600091849081106108e357005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b60010161032d56", - "gasLimit" : "0x0b5290", + "data" : "606060409081526001600081815581805533600160a060020a0316600381905581526101026020529190912055620151804204610107556109b4806100456000396000f300606060405236156100985760e060020a6000350463173825d9811461009a5780632f54bf6e146100f65780634123cb6b1461011a5780635c52c2f5146101235780637065cb4814610154578063746c917114610188578063b20d30a914610191578063b75c7dc6146101c5578063ba51a6df146101f5578063c2cf732614610229578063f00d4b5d14610269578063f1736d86146102a2575b005b6100986004356000600036436040518084848082843750505090910190815260405190819003602001902090506105b9815b600160a060020a0333166000908152610102602052604081205481808083811415610719576108b0565b6102ac6004355b600160a060020a0316600090815261010260205260408120541190565b6102ac60015481565b6100986000364360405180848480828437505050909101908152604051908190036020019020905061070b816100cc565b61009860043560003643604051808484808284375050509091019081526040519081900360200190209050610531816100cc565b6102ac60005481565b610098600435600036436040518084848082843750505090910190815260405190819003602001902090506106ff816100cc565b610098600435600160a060020a03331660009081526101026020526040812054908080838114156102be57610340565b61009860043560003643604051808484808284375050509091019081526040519081900360200190209050610678816100cc565b6102ac600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156106d1576106f5565b6100986004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506103ca816100cc565b6102ac6101055481565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156103405781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156103c3576103d8836100fd565b156103e357506103c5565b600160a060020a03841660009081526101026020526040812054925082141561040c57506103c5565b6103475b6101045460005b8181101561085f576101048054829081101561000257600091825260008051602061099483398151915201541461048a5761010480546101039160009184908110156100025760008051602061099483398151915201548252506020919091526040812081815560018101829055600201555b600101610417565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561052c5761053f826100fd565b1561054a575061052e565b610552610410565b60015460fa90106105675761056561057c565b505b60015460fa9010610492575061052e565b6106365b600060015b600154811015610899575b600154811080156105ac5750600281610100811015610002570154600014155b156108b95760010161058c565b156103c557600160a060020a0383166000908152610102602052604081205492508214156105e7575061052c565b6001600160005054036000600050541115610602575061052c565b600060028361010081101561000257508301819055600160a060020a03841681526101026020526040812055610578610410565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561052c5760015482111561068d575061052e565b600082905561069a610410565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106f057600094506106f5565b600194505b5050505092915050565b1561052c575061010555565b1561052e5760006101065550565b60008681526101036020526040812080549094509092508214156107a2578154835560018381018390556101048054918201808255828015829011610771578183600052602060002091820191016107719190610885565b5050506002840181905561010480548892908110156100025760009190915260008051602061099483398151915201555b506001820154600284900a908116600014156108b05760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a182546001901161089d57600086815261010360205260409020600201546101048054909190811015610002576040600090812060008051602061099483398151915292909201819055808255600180830182905560029092015595506108b09050565b61010480546000808355919091526103c590600080516020610994833981519152908101905b808211156108995760008155600101610885565b5090565b8254600019018355600183018054821790555b50505050919050565b5b600180541180156108dc57506001546002906101008110156100025701546000145b156108f057600180546000190190556108ba565b600154811080156109135750600154600290610100811015610002570154600014155b801561092d57506002816101008110156100025701546000145b1561098e57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61058156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "gasLimit" : "0x0bfaba", "gasPrice" : "1", "nonce" : "1", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", @@ -770,8 +770,8 @@ } }, "transaction" : { - "data" : "600160008181558180553373ffffffffffffffffffffffffffffffffffffffff16600381905581526101026020526040902055620151804204610107556109158061004b6000396000f3007c01000000000000000000000000000000000000000000000000000000006000350463173825d9811461007b5780632f54bf6e146100cd5780635c52c2f5146100fe5780637065cb4814610118578063b20d30a914610135578063b75c7dc614610152578063ba51a6df1461018f578063f00d4b5d146101ac57005b6101ce60043560006040600036808284379091209050610472815b73ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054818080838114156105bc5761071e565b6101d46004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b6101ce60406000368082843790912090506105ae81610096565b6101ce60043560406000368082843790912090506103c981610096565b6101ce60043560406000368082843790912090506105a281610096565b6101ce60043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156101de57610260565b6101ce600435604060003680828437909120905061055181610096565b6101ce600435602435600060406000368082843790912090506102d381610096565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561026057815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b156102cc576102e1836100d4565b156102ec57506102ce565b73ffffffffffffffffffffffffffffffffffffffff841660009081526101026020526040812054925082141561032257506102ce565b6103445b6101045460005b81811015610873576101048054829081106108bb57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061026757005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103c4576103d7826100d4565b156103e257506103c6565b6103ea610326565b60015460fa90101515610401576103ff610418565b505b60015460fa9010151561044257506103c6565b6105095b600060015b60015481101561075e575b600154811080156107ba575060028161010081106107b357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061036957005b156102ce5773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104ad57506103c4565b60016001600050540360006000505411156104c857506103c4565b600060028361010081106104d857005b015573ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812055610414610326565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156103c45760015482111561056657506103c6565b6000829055610573610326565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b156103c4575061010655565b156103c65760006101055550565b60008681526101036020526040812080549094509092508214156106475781548355600183810183905561010480549182018082558280158290116106d3578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106d15760008155600101610626565b6000918252602090912001555b506001820154600284900a9081166000141561071e5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156106ed57600086815261010360205261010480546040909220600201549091811061072757005b505b505050600284018190556101048054889290811061063a57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600091825260208083209091018290558782526101039052604081208181556001818101839055600290910191909155945061071e565b5090565b01546000145b156107c757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b600180541180156107685750600154600290610100811061076257005b0154600014155b1561079657600101610428565b600154811080156107eb575060015460029061010081106107e457005b0154600014155b80156108065750600281610100811061080057005b01546000145b1561081f57600154600290610100811061082457005b01555b61041d565b0154600282610100811061083457005b0155806101026000600283610100811061084a57005b015481526020810191909152604001600090812091909155600154600290610100811061081c57005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156102cc57600081556001016108a7565b600091825260208220015414151561090d57610104805461010391600091849081106108e357005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b60010161032d56", - "gasLimit" : "0x043a28", + "data" : "606060409081526001600081815581805533600160a060020a0316600381905581526101026020529190912055620151804204610107556109b4806100456000396000f300606060405236156100985760e060020a6000350463173825d9811461009a5780632f54bf6e146100f65780634123cb6b1461011a5780635c52c2f5146101235780637065cb4814610154578063746c917114610188578063b20d30a914610191578063b75c7dc6146101c5578063ba51a6df146101f5578063c2cf732614610229578063f00d4b5d14610269578063f1736d86146102a2575b005b6100986004356000600036436040518084848082843750505090910190815260405190819003602001902090506105b9815b600160a060020a0333166000908152610102602052604081205481808083811415610719576108b0565b6102ac6004355b600160a060020a0316600090815261010260205260408120541190565b6102ac60015481565b6100986000364360405180848480828437505050909101908152604051908190036020019020905061070b816100cc565b61009860043560003643604051808484808284375050509091019081526040519081900360200190209050610531816100cc565b6102ac60005481565b610098600435600036436040518084848082843750505090910190815260405190819003602001902090506106ff816100cc565b610098600435600160a060020a03331660009081526101026020526040812054908080838114156102be57610340565b61009860043560003643604051808484808284375050509091019081526040519081900360200190209050610678816100cc565b6102ac600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156106d1576106f5565b6100986004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506103ca816100cc565b6102ac6101055481565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156103405781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156103c3576103d8836100fd565b156103e357506103c5565b600160a060020a03841660009081526101026020526040812054925082141561040c57506103c5565b6103475b6101045460005b8181101561085f576101048054829081101561000257600091825260008051602061099483398151915201541461048a5761010480546101039160009184908110156100025760008051602061099483398151915201548252506020919091526040812081815560018101829055600201555b600101610417565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561052c5761053f826100fd565b1561054a575061052e565b610552610410565b60015460fa90106105675761056561057c565b505b60015460fa9010610492575061052e565b6106365b600060015b600154811015610899575b600154811080156105ac5750600281610100811015610002570154600014155b156108b95760010161058c565b156103c557600160a060020a0383166000908152610102602052604081205492508214156105e7575061052c565b6001600160005054036000600050541115610602575061052c565b600060028361010081101561000257508301819055600160a060020a03841681526101026020526040812055610578610410565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561052c5760015482111561068d575061052e565b600082905561069a610410565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106f057600094506106f5565b600194505b5050505092915050565b1561052c575061010555565b1561052e5760006101065550565b60008681526101036020526040812080549094509092508214156107a2578154835560018381018390556101048054918201808255828015829011610771578183600052602060002091820191016107719190610885565b5050506002840181905561010480548892908110156100025760009190915260008051602061099483398151915201555b506001820154600284900a908116600014156108b05760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a182546001901161089d57600086815261010360205260409020600201546101048054909190811015610002576040600090812060008051602061099483398151915292909201819055808255600180830182905560029092015595506108b09050565b61010480546000808355919091526103c590600080516020610994833981519152908101905b808211156108995760008155600101610885565b5090565b8254600019018355600183018054821790555b50505050919050565b5b600180541180156108dc57506001546002906101008110156100025701546000145b156108f057600180546000190190556108ba565b600154811080156109135750600154600290610100811015610002570154600014155b801561092d57506002816101008110156100025701546000145b1561098e57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61058156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "gasLimit" : "0x04661a", "gasPrice" : "1", "nonce" : "1", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", @@ -799,7 +799,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d9811461007b5780632f54bf6e146100cd5780635c52c2f5146100fe5780637065cb4814610118578063b20d30a914610135578063b75c7dc614610152578063ba51a6df1461018f578063f00d4b5d146101ac57005b6101ce60043560006040600036808284379091209050610472815b73ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054818080838114156105bc5761071e565b6101d46004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b6101ce60406000368082843790912090506105ae81610096565b6101ce60043560406000368082843790912090506103c981610096565b6101ce60043560406000368082843790912090506105a281610096565b6101ce60043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156101de57610260565b6101ce600435604060003680828437909120905061055181610096565b6101ce600435602435600060406000368082843790912090506102d381610096565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561026057815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b156102cc576102e1836100d4565b156102ec57506102ce565b73ffffffffffffffffffffffffffffffffffffffff841660009081526101026020526040812054925082141561032257506102ce565b6103445b6101045460005b81811015610873576101048054829081106108bb57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061026757005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103c4576103d7826100d4565b156103e257506103c6565b6103ea610326565b60015460fa90101515610401576103ff610418565b505b60015460fa9010151561044257506103c6565b6105095b600060015b60015481101561075e575b600154811080156107ba575060028161010081106107b357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061036957005b156102ce5773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104ad57506103c4565b60016001600050540360006000505411156104c857506103c4565b600060028361010081106104d857005b015573ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812055610414610326565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156103c45760015482111561056657506103c6565b6000829055610573610326565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b156103c4575061010655565b156103c65760006101055550565b60008681526101036020526040812080549094509092508214156106475781548355600183810183905561010480549182018082558280158290116106d3578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106d15760008155600101610626565b6000918252602090912001555b506001820154600284900a9081166000141561071e5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156106ed57600086815261010360205261010480546040909220600201549091811061072757005b505b505050600284018190556101048054889290811061063a57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600091825260208083209091018290558782526101039052604081208181556001818101839055600290910191909155945061071e565b5090565b01546000145b156107c757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b600180541180156107685750600154600290610100811061076257005b0154600014155b1561079657600101610428565b600154811080156107eb575060015460029061010081106107e457005b0154600014155b80156108065750600281610100811061080057005b01546000145b1561081f57600154600290610100811061082457005b01555b61041d565b0154600282610100811061083457005b0155806101026000600283610100811061084a57005b015481526020810191909152604001600090812091909155600154600290610100811061081c57005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156102cc57600081556001016108a7565b600091825260208220015414151561090d57610104805461010391600091849081106108e357005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b60010161032d56", + "code" : "0x606060405236156100985760e060020a6000350463173825d9811461009a5780632f54bf6e146100f65780634123cb6b1461011a5780635c52c2f5146101235780637065cb4814610154578063746c917114610188578063b20d30a914610191578063b75c7dc6146101c5578063ba51a6df146101f5578063c2cf732614610229578063f00d4b5d14610269578063f1736d86146102a2575b005b6100986004356000600036436040518084848082843750505090910190815260405190819003602001902090506105b9815b600160a060020a0333166000908152610102602052604081205481808083811415610719576108b0565b6102ac6004355b600160a060020a0316600090815261010260205260408120541190565b6102ac60015481565b6100986000364360405180848480828437505050909101908152604051908190036020019020905061070b816100cc565b61009860043560003643604051808484808284375050509091019081526040519081900360200190209050610531816100cc565b6102ac60005481565b610098600435600036436040518084848082843750505090910190815260405190819003602001902090506106ff816100cc565b610098600435600160a060020a03331660009081526101026020526040812054908080838114156102be57610340565b61009860043560003643604051808484808284375050509091019081526040519081900360200190209050610678816100cc565b6102ac600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156106d1576106f5565b6100986004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506103ca816100cc565b6102ac6101055481565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156103405781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156103c3576103d8836100fd565b156103e357506103c5565b600160a060020a03841660009081526101026020526040812054925082141561040c57506103c5565b6103475b6101045460005b8181101561085f576101048054829081101561000257600091825260008051602061099483398151915201541461048a5761010480546101039160009184908110156100025760008051602061099483398151915201548252506020919091526040812081815560018101829055600201555b600101610417565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561052c5761053f826100fd565b1561054a575061052e565b610552610410565b60015460fa90106105675761056561057c565b505b60015460fa9010610492575061052e565b6106365b600060015b600154811015610899575b600154811080156105ac5750600281610100811015610002570154600014155b156108b95760010161058c565b156103c557600160a060020a0383166000908152610102602052604081205492508214156105e7575061052c565b6001600160005054036000600050541115610602575061052c565b600060028361010081101561000257508301819055600160a060020a03841681526101026020526040812055610578610410565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561052c5760015482111561068d575061052e565b600082905561069a610410565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106f057600094506106f5565b600194505b5050505092915050565b1561052c575061010555565b1561052e5760006101065550565b60008681526101036020526040812080549094509092508214156107a2578154835560018381018390556101048054918201808255828015829011610771578183600052602060002091820191016107719190610885565b5050506002840181905561010480548892908110156100025760009190915260008051602061099483398151915201555b506001820154600284900a908116600014156108b05760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a182546001901161089d57600086815261010360205260409020600201546101048054909190811015610002576040600090812060008051602061099483398151915292909201819055808255600180830182905560029092015595506108b09050565b61010480546000808355919091526103c590600080516020610994833981519152908101905b808211156108995760008155600101610885565b5090565b8254600019018355600183018054821790555b50505050919050565b5b600180541180156108dc57506001546002906101008110156100025701546000145b156108f057600180546000190190556108ba565b600154811080156109135750600154600290610100811015610002570154600014155b801561092d57506002816101008110156100025701546000145b1561098e57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61058156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -839,7 +839,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d9811461007b5780632f54bf6e146100cd5780635c52c2f5146100fe5780637065cb4814610118578063b20d30a914610135578063b75c7dc614610152578063ba51a6df1461018f578063f00d4b5d146101ac57005b6101ce60043560006040600036808284379091209050610472815b73ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054818080838114156105bc5761071e565b6101d46004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b6101ce60406000368082843790912090506105ae81610096565b6101ce60043560406000368082843790912090506103c981610096565b6101ce60043560406000368082843790912090506105a281610096565b6101ce60043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156101de57610260565b6101ce600435604060003680828437909120905061055181610096565b6101ce600435602435600060406000368082843790912090506102d381610096565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561026057815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b156102cc576102e1836100d4565b156102ec57506102ce565b73ffffffffffffffffffffffffffffffffffffffff841660009081526101026020526040812054925082141561032257506102ce565b6103445b6101045460005b81811015610873576101048054829081106108bb57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061026757005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103c4576103d7826100d4565b156103e257506103c6565b6103ea610326565b60015460fa90101515610401576103ff610418565b505b60015460fa9010151561044257506103c6565b6105095b600060015b60015481101561075e575b600154811080156107ba575060028161010081106107b357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061036957005b156102ce5773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104ad57506103c4565b60016001600050540360006000505411156104c857506103c4565b600060028361010081106104d857005b015573ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812055610414610326565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156103c45760015482111561056657506103c6565b6000829055610573610326565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b156103c4575061010655565b156103c65760006101055550565b60008681526101036020526040812080549094509092508214156106475781548355600183810183905561010480549182018082558280158290116106d3578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106d15760008155600101610626565b6000918252602090912001555b506001820154600284900a9081166000141561071e5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156106ed57600086815261010360205261010480546040909220600201549091811061072757005b505b505050600284018190556101048054889290811061063a57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600091825260208083209091018290558782526101039052604081208181556001818101839055600290910191909155945061071e565b5090565b01546000145b156107c757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b600180541180156107685750600154600290610100811061076257005b0154600014155b1561079657600101610428565b600154811080156107eb575060015460029061010081106107e457005b0154600014155b80156108065750600281610100811061080057005b01546000145b1561081f57600154600290610100811061082457005b01555b61041d565b0154600282610100811061083457005b0155806101026000600283610100811061084a57005b015481526020810191909152604001600090812091909155600154600290610100811061081c57005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156102cc57600081556001016108a7565b600091825260208220015414151561090d57610104805461010391600091849081106108e357005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b60010161032d56", + "code" : "0x606060405236156100985760e060020a6000350463173825d9811461009a5780632f54bf6e146100f65780634123cb6b1461011a5780635c52c2f5146101235780637065cb4814610154578063746c917114610188578063b20d30a914610191578063b75c7dc6146101c5578063ba51a6df146101f5578063c2cf732614610229578063f00d4b5d14610269578063f1736d86146102a2575b005b6100986004356000600036436040518084848082843750505090910190815260405190819003602001902090506105b9815b600160a060020a0333166000908152610102602052604081205481808083811415610719576108b0565b6102ac6004355b600160a060020a0316600090815261010260205260408120541190565b6102ac60015481565b6100986000364360405180848480828437505050909101908152604051908190036020019020905061070b816100cc565b61009860043560003643604051808484808284375050509091019081526040519081900360200190209050610531816100cc565b6102ac60005481565b610098600435600036436040518084848082843750505090910190815260405190819003602001902090506106ff816100cc565b610098600435600160a060020a03331660009081526101026020526040812054908080838114156102be57610340565b61009860043560003643604051808484808284375050509091019081526040519081900360200190209050610678816100cc565b6102ac600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156106d1576106f5565b6100986004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506103ca816100cc565b6102ac6101055481565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156103405781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156103c3576103d8836100fd565b156103e357506103c5565b600160a060020a03841660009081526101026020526040812054925082141561040c57506103c5565b6103475b6101045460005b8181101561085f576101048054829081101561000257600091825260008051602061099483398151915201541461048a5761010480546101039160009184908110156100025760008051602061099483398151915201548252506020919091526040812081815560018101829055600201555b600101610417565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561052c5761053f826100fd565b1561054a575061052e565b610552610410565b60015460fa90106105675761056561057c565b505b60015460fa9010610492575061052e565b6106365b600060015b600154811015610899575b600154811080156105ac5750600281610100811015610002570154600014155b156108b95760010161058c565b156103c557600160a060020a0383166000908152610102602052604081205492508214156105e7575061052c565b6001600160005054036000600050541115610602575061052c565b600060028361010081101561000257508301819055600160a060020a03841681526101026020526040812055610578610410565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561052c5760015482111561068d575061052e565b600082905561069a610410565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106f057600094506106f5565b600194505b5050505092915050565b1561052c575061010555565b1561052e5760006101065550565b60008681526101036020526040812080549094509092508214156107a2578154835560018381018390556101048054918201808255828015829011610771578183600052602060002091820191016107719190610885565b5050506002840181905561010480548892908110156100025760009190915260008051602061099483398151915201555b506001820154600284900a908116600014156108b05760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a182546001901161089d57600086815261010360205260409020600201546101048054909190811015610002576040600090812060008051602061099483398151915292909201819055808255600180830182905560029092015595506108b09050565b61010480546000808355919091526103c590600080516020610994833981519152908101905b808211156108995760008155600101610885565b5090565b8254600019018355600183018054821790555b50505050919050565b5b600180541180156108dc57506001546002906101008110156100025701546000145b156108f057600180546000190190556108ba565b600154811080156109135750600154600290610100811015610002570154600014155b801561092d57506002816101008110156100025701546000145b1561098e57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61058156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -879,7 +879,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d9811461007b5780632f54bf6e146100cd5780635c52c2f5146100fe5780637065cb4814610118578063b20d30a914610135578063b75c7dc614610152578063ba51a6df1461018f578063f00d4b5d146101ac57005b6101ce60043560006040600036808284379091209050610472815b73ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054818080838114156105bc5761071e565b6101d46004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b6101ce60406000368082843790912090506105ae81610096565b6101ce60043560406000368082843790912090506103c981610096565b6101ce60043560406000368082843790912090506105a281610096565b6101ce60043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156101de57610260565b6101ce600435604060003680828437909120905061055181610096565b6101ce600435602435600060406000368082843790912090506102d381610096565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561026057815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b156102cc576102e1836100d4565b156102ec57506102ce565b73ffffffffffffffffffffffffffffffffffffffff841660009081526101026020526040812054925082141561032257506102ce565b6103445b6101045460005b81811015610873576101048054829081106108bb57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061026757005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103c4576103d7826100d4565b156103e257506103c6565b6103ea610326565b60015460fa90101515610401576103ff610418565b505b60015460fa9010151561044257506103c6565b6105095b600060015b60015481101561075e575b600154811080156107ba575060028161010081106107b357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061036957005b156102ce5773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104ad57506103c4565b60016001600050540360006000505411156104c857506103c4565b600060028361010081106104d857005b015573ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812055610414610326565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156103c45760015482111561056657506103c6565b6000829055610573610326565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b156103c4575061010655565b156103c65760006101055550565b60008681526101036020526040812080549094509092508214156106475781548355600183810183905561010480549182018082558280158290116106d3578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106d15760008155600101610626565b6000918252602090912001555b506001820154600284900a9081166000141561071e5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156106ed57600086815261010360205261010480546040909220600201549091811061072757005b505b505050600284018190556101048054889290811061063a57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600091825260208083209091018290558782526101039052604081208181556001818101839055600290910191909155945061071e565b5090565b01546000145b156107c757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b600180541180156107685750600154600290610100811061076257005b0154600014155b1561079657600101610428565b600154811080156107eb575060015460029061010081106107e457005b0154600014155b80156108065750600281610100811061080057005b01546000145b1561081f57600154600290610100811061082457005b01555b61041d565b0154600282610100811061083457005b0155806101026000600283610100811061084a57005b015481526020810191909152604001600090812091909155600154600290610100811061081c57005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156102cc57600081556001016108a7565b600091825260208220015414151561090d57610104805461010391600091849081106108e357005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b60010161032d56", + "code" : "0x606060405236156100985760e060020a6000350463173825d9811461009a5780632f54bf6e146100f65780634123cb6b1461011a5780635c52c2f5146101235780637065cb4814610154578063746c917114610188578063b20d30a914610191578063b75c7dc6146101c5578063ba51a6df146101f5578063c2cf732614610229578063f00d4b5d14610269578063f1736d86146102a2575b005b6100986004356000600036436040518084848082843750505090910190815260405190819003602001902090506105b9815b600160a060020a0333166000908152610102602052604081205481808083811415610719576108b0565b6102ac6004355b600160a060020a0316600090815261010260205260408120541190565b6102ac60015481565b6100986000364360405180848480828437505050909101908152604051908190036020019020905061070b816100cc565b61009860043560003643604051808484808284375050509091019081526040519081900360200190209050610531816100cc565b6102ac60005481565b610098600435600036436040518084848082843750505090910190815260405190819003602001902090506106ff816100cc565b610098600435600160a060020a03331660009081526101026020526040812054908080838114156102be57610340565b61009860043560003643604051808484808284375050509091019081526040519081900360200190209050610678816100cc565b6102ac600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156106d1576106f5565b6100986004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506103ca816100cc565b6102ac6101055481565b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a92908316819011156103405781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a038316600283610100811015610002570155600160a060020a0384811660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156103c3576103d8836100fd565b156103e357506103c5565b600160a060020a03841660009081526101026020526040812054925082141561040c57506103c5565b6103475b6101045460005b8181101561085f576101048054829081101561000257600091825260008051602061099483398151915201541461048a5761010480546101039160009184908110156100025760008051602061099483398151915201548252506020919091526040812081815560018101829055600201555b600101610417565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561052c5761053f826100fd565b1561054a575061052e565b610552610410565b60015460fa90106105675761056561057c565b505b60015460fa9010610492575061052e565b6106365b600060015b600154811015610899575b600154811080156105ac5750600281610100811015610002570154600014155b156108b95760010161058c565b156103c557600160a060020a0383166000908152610102602052604081205492508214156105e7575061052c565b6001600160005054036000600050541115610602575061052c565b600060028361010081101561000257508301819055600160a060020a03841681526101026020526040812055610578610410565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561052c5760015482111561068d575061052e565b600082905561069a610410565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156106f057600094506106f5565b600194505b5050505092915050565b1561052c575061010555565b1561052e5760006101065550565b60008681526101036020526040812080549094509092508214156107a2578154835560018381018390556101048054918201808255828015829011610771578183600052602060002091820191016107719190610885565b5050506002840181905561010480548892908110156100025760009190915260008051602061099483398151915201555b506001820154600284900a908116600014156108b05760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a182546001901161089d57600086815261010360205260409020600201546101048054909190811015610002576040600090812060008051602061099483398151915292909201819055808255600180830182905560029092015595506108b09050565b61010480546000808355919091526103c590600080516020610994833981519152908101905b808211156108995760008155600101610885565b5090565b8254600019018355600183018054821790555b50505050919050565b5b600180541180156108dc57506001546002906101008110156100025701546000145b156108f057600180546000190190556108ba565b600154811080156109135750600154600290610100811015610002570154600014155b801561092d57506002816101008110156100025701546000145b1561098e57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61058156004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -921,8 +921,8 @@ } }, "transaction" : { - "data" : "600160008181558180553373ffffffffffffffffffffffffffffffffffffffff16600381905581526101026020526040902055620151804204610107557f9adeddf84386b336eb7b3e18e7a6099be08fd81ea5d5142f4d2b630f8d20cf0160006040a1610ee9806100716000396000f3007c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", - "gasLimit" : "10000000", + "data" : "6060604052604051602080611014833960806040818152925160016000818155818055600160a060020a03331660038190558152610102909452938320939093556201518042046101075582917f102d25c49d33fcdb8976a3f2744e0785c98d9e43b88364859e6aec4ae82eff5c91a250610f958061007f6000396000f300606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "gasLimit" : "0x12343f", "gasPrice" : "1", "nonce" : "1", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", @@ -950,8 +950,8 @@ } }, "transaction" : { - "data" : "600160008181558180553373ffffffffffffffffffffffffffffffffffffffff16600381905581526101026020526040902055620151804204610107557f9adeddf84386b336eb7b3e18e7a6099be08fd81ea5d5142f4d2b630f8d20cf0160006040a1610ee9806100716000396000f3007c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", - "gasLimit" : "0x1165fb", + "data" : "6060604052604051602080611014833960806040818152925160016000818155818055600160a060020a03331660038190558152610102909452938320939093556201518042046101075582917f102d25c49d33fcdb8976a3f2744e0785c98d9e43b88364859e6aec4ae82eff5c91a250610f958061007f6000396000f300606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "gasLimit" : "0x12343e", "gasPrice" : "1", "nonce" : "1", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", @@ -979,8 +979,8 @@ } }, "transaction" : { - "data" : "600160008181558180553373ffffffffffffffffffffffffffffffffffffffff16600381905581526101026020526040902055620151804204610107557f9adeddf84386b336eb7b3e18e7a6099be08fd81ea5d5142f4d2b630f8d20cf0160006040a1610ee9806100716000396000f3007c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", - "gasLimit" : "0x05bff3", + "data" : "6060604052604051602080611014833960806040818152925160016000818155818055600160a060020a03331660038190558152610102909452938320939093556201518042046101075582917f102d25c49d33fcdb8976a3f2744e0785c98d9e43b88364859e6aec4ae82eff5c91a250610f958061007f6000396000f300606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "gasLimit" : "0x0607d6", "gasPrice" : "1", "nonce" : "1", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", @@ -1008,7 +1008,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", + "code" : "0x606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -1056,7 +1056,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", + "code" : "0x606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -1097,7 +1097,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", + "code" : "0x606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -1138,7 +1138,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", + "code" : "0x606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -1179,7 +1179,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", + "code" : "0x606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -1220,7 +1220,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", + "code" : "0x606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -1261,7 +1261,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", + "code" : "0x606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x02", @@ -1310,7 +1310,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", + "code" : "0x606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x02", @@ -1359,7 +1359,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", + "code" : "0x606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -1408,7 +1408,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", + "code" : "0x606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -1464,7 +1464,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", + "code" : "0x606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -1520,7 +1520,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", + "code" : "0x606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", @@ -1576,7 +1576,7 @@ }, "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { "balance" : "0x64", - "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", + "code" : "0x606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "nonce" : "0x00", "storage" : { "0x00" : "0x01", From 06030dc20c1b4cd173227dd07a9622412557b27d Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 9 Jul 2015 14:36:34 -0700 Subject: [PATCH 273/290] Avoid crash on rescue. --- libethereum/Client.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/Client.h b/libethereum/Client.h index d433ecb6d..5124f3778 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -220,7 +220,7 @@ public: /// Rewind to a prior head. void rewind(unsigned _n) { m_bc.rewind(_n); } /// Rescue the chain. - void rescue() { m_bc.rescue(m_stateDB); } + void rescue() { stopWorking(); m_bc.rescue(m_stateDB); } protected: /// InterfaceStub methods From 743315b38ca40791c86590d5d8dd8f5876ecdaa6 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Fri, 10 Jul 2015 01:30:03 +0200 Subject: [PATCH 274/290] add multiOwnedRemoveOwner test --- .../StateTestsFiller/stWalletTestFiller.json | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/test/libethereum/StateTestsFiller/stWalletTestFiller.json b/test/libethereum/StateTestsFiller/stWalletTestFiller.json index 93f898a4a..6058b354b 100644 --- a/test/libethereum/StateTestsFiller/stWalletTestFiller.json +++ b/test/libethereum/StateTestsFiller/stWalletTestFiller.json @@ -326,7 +326,7 @@ } }, - "multiOwnedRemoveOwner" : { + "multiOwnedRemoveOwner_mySelf" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty" : "256", @@ -366,6 +366,48 @@ } }, + "multiOwnedRemoveOwner" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : { + "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { + "balance" : "0x64", + "code" : "0x7c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100655780632f54bf6e146100b75780637065cb48146100e8578063b75c7dc614610105578063ba51a6df14610142578063f00d4b5d1461015f57005b6101816004356000604060003680828437909120905061046d815b73ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120548180808381141561058f57610586565b6101876004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610181600435604060003680828437909120905061037c81610080565b61018160043573ffffffffffffffffffffffffffffffffffffffff3316600090815261010260205260408120549080808381141561019157610213565b610181600435604060003680828437909120905061053381610080565b6101816004356024356000604060003680828437909120905061028681610080565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561021357815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b1561027f57610294836100be565b1561029f5750610281565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156102d55750610281565b6102f75b6101045460005b8181101561080c5761010480548290811061085457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061021a57005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b156103775761038a826100be565b156103955750610379565b61039d6102d9565b60015460fa901015156103b4576103b26103cb565b505b60015460fa901015156103f55750610379565b6104255b600060015b6001548110156106f7575b600154811080156107535750600281610100811061074c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061031c57005b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b156102815773ffffffffffffffffffffffffffffffffffffffff83166000908152610102602052604081205492508214156104a85750610377565b60016001600050540360006000505411156104c35750610377565b600060028361010081106104d357005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556103c76102d9565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610377576001548211156105485750610379565b60008290556105046102d9565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b600086815261010360205260408120805490945090925082141561061a5781548355600183810183905561010480549182018082558280158290116106a6578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b808211156106a457600081556001016105f9565b6000918252602090912001555b506001820154600284900a908116600014156105865773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a182546001901115156105555760008681526101036020526101048054604090922060020154909181106106c057005b505b505050600284018190556101048054889290811061060d57005b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610586565b5090565b01546000145b1561076057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610701575060015460029061010081106106fb57005b0154600014155b1561072f576001016103db565b600154811080156107845750600154600290610100811061077d57005b0154600014155b801561079f5750600281610100811061079957005b01546000145b156107b85760015460029061010081106107bd57005b01555b6103d0565b015460028261010081106107cd57005b015580610102600060028361010081106107e357005b01548152602081019190915260400160009081209190915560015460029061010081106107b557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b8082111561027f5760008155600101610840565b60009182526020822001541415156108a6576101048054610103916000918490811061087c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016102e056", + "nonce" : "0x00", + "storage" : { + "0x00" : "0x01", + "0x01" : "0x02", + "0x03" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "0x04" : "0x3fb1cd2cd96c6d5c0b5eb3322d807b34482481d4", + "0x6e369836487c234b9e553ef3f787c2d8865520739d340c67b3d251a33986e58d" : "0x01", + "0xd3e69d8c7f41f7aeaf8130ddc53047aeee8cb46a73d6bae86b7e7d6bf8312e6b" : "0x02" + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x0de0b6b3a75ef08f", + "code" : "0x", + "nonce" : "0x01", + "storage" : { + } + } + }, + "transaction" : { + "data" : "0x173825d9000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "gasLimit" : "10000000", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f", + "value" : "100" + } + }, + "multiOwnedRemoveOwnerByNonOwner" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", @@ -804,6 +846,7 @@ "storage" : { "0x00" : "0x01", "0x01" : "0x01", + "0x0107" : "0x0c22e4", "0x03" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x6e369836487c234b9e553ef3f787c2d8865520739d340c67b3d251a33986e58d" : "0x01" } @@ -844,6 +887,7 @@ "storage" : { "0x00" : "0x01", "0x01" : "0x01", + "0x0107" : "0x0c22e4", "0x03" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x6e369836487c234b9e553ef3f787c2d8865520739d340c67b3d251a33986e58d" : "0x01" } @@ -884,8 +928,9 @@ "storage" : { "0x00" : "0x01", "0x01" : "0x01", - "0x0104" : "0x09", - "0x0105" : "0xff", + "0x0104" : "0x01", + "0x0105" : "0x02", + "0x0107" : "0x0c22e4", "0x03" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x6e369836487c234b9e553ef3f787c2d8865520739d340c67b3d251a33986e58d" : "0x01" } From 9267b7a036f459ca8234687126700dc92d2eb8ce Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Fri, 10 Jul 2015 01:39:27 +0200 Subject: [PATCH 275/290] set daily limit --- test/libethereum/StateTestsFiller/stWalletTestFiller.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libethereum/StateTestsFiller/stWalletTestFiller.json b/test/libethereum/StateTestsFiller/stWalletTestFiller.json index 6058b354b..5a835fa41 100644 --- a/test/libethereum/StateTestsFiller/stWalletTestFiller.json +++ b/test/libethereum/StateTestsFiller/stWalletTestFiller.json @@ -1270,7 +1270,7 @@ "storage" : { "0x00" : "0x01", "0x01" : "0x01", - "0x0106" : "0x0c22e4", + "0x0106" : "0x04", "0x03" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x6e369836487c234b9e553ef3f787c2d8865520739d340c67b3d251a33986e58d" : "0x01" } From cc57aed80e4d469ddf7c3ad744d1243df9068ead Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Fri, 10 Jul 2015 01:59:21 +0200 Subject: [PATCH 276/290] add new daily limit test --- .../StateTestsFiller/stWalletTestFiller.json | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/test/libethereum/StateTestsFiller/stWalletTestFiller.json b/test/libethereum/StateTestsFiller/stWalletTestFiller.json index 5a835fa41..952b073d3 100644 --- a/test/libethereum/StateTestsFiller/stWalletTestFiller.json +++ b/test/libethereum/StateTestsFiller/stWalletTestFiller.json @@ -1287,6 +1287,48 @@ } }, + "walletExecuteOverDailyLimitOnlyOneOwnerNew" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : "0xfffffffff", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x0de0b6b3a75ef08f", + "code" : "0x", + "nonce" : "0x01", + "storage" : { + } + }, + "ec0e71ad0a90ffe1909d27dac207f7680abba42d" : { + "balance" : "0x64", + "code" : "0x606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "nonce" : "0x00", + "storage" : { + "0x00" : "0x01", + "0x01" : "0x01", + "0x0106" : "0x04", + "0x0107" : "0x0c22e4", + "0x03" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "0x6e369836487c234b9e553ef3f787c2d8865520739d340c67b3d251a33986e58d" : "0x01" + } + } + }, + "transaction" : { + "data" : "0xb61d27f6000000000000000000000000aaaf5374fce5edbc8e2a8697c15331677e6ebaaa00000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000060", + "gasLimit" : "10000000", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "ec0e71ad0a90ffe1909d27dac207f7680abba42d", + "value" : "0" + } + }, + "walletExecuteOverDailyLimitMultiOwner" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", From 245fd187b21a4010b226dc7e49e6446cdfc0b5ba Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Fri, 10 Jul 2015 04:37:36 +0200 Subject: [PATCH 277/290] update bcWalletTest --- .../bcWalletTestFiller.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/libethereum/BlockchainTestsFiller/bcWalletTestFiller.json b/test/libethereum/BlockchainTestsFiller/bcWalletTestFiller.json index a946ed724..cc869b967 100644 --- a/test/libethereum/BlockchainTestsFiller/bcWalletTestFiller.json +++ b/test/libethereum/BlockchainTestsFiller/bcWalletTestFiller.json @@ -41,8 +41,8 @@ { "transactions" : [ { - "data" : "600160008181558180553373ffffffffffffffffffffffffffffffffffffffff16600381905581526101026020526040902055620151804204610107557f9adeddf84386b336eb7b3e18e7a6099be08fd81ea5d5142f4d2b630f8d20cf0160006040a1610ee9806100716000396000f3007c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", - "gasLimit" : "0x116ffc", + "data" : "606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "gasLimit" : "0x12343f", "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", @@ -173,8 +173,8 @@ { "transactions" : [ { - "data" : "600160008181558180553373ffffffffffffffffffffffffffffffffffffffff16600381905581526101026020526040902055620151804204610107557f9adeddf84386b336eb7b3e18e7a6099be08fd81ea5d5142f4d2b630f8d20cf0160006040a1610ee9806100716000396000f3007c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", - "gasLimit" : "0x116ffc", + "data" : "606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "gasLimit" : "0x12343f", "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", @@ -319,8 +319,8 @@ { "transactions" : [ { - "data" : "600160008181558180553373ffffffffffffffffffffffffffffffffffffffff16600381905581526101026020526040902055620151804204610107557f9adeddf84386b336eb7b3e18e7a6099be08fd81ea5d5142f4d2b630f8d20cf0160006040a1610ee9806100716000396000f3007c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b61029760043560006040600036808284379091209050610542815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7c57610bde565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067e81610108565b610297600435604060003680828437909120905061049981610108565b61029d6004355b6000816108bb81610108565b610297600435604060003680828437909120905061067281610108565b61029d6004803590602480359160443591820191013560006106aa846000610d3333610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061062181610108565b610297600435604060003680828437909120905061068c81610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b6104145b6101045460005b81811015610d9e5761010480546101089160009184908110610dbf57005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b15610494576104a782610146565b156104b25750610496565b6104ba6103ef565b60015460fa901015156104d1576104cf6104e8565b505b60015460fa901015156105125750610496565b6105d95b600060015b600154811015610c1e575b60015481108015610c7a57506002816101008110610c7357005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043957005b156103975773ffffffffffffffffffffffffffffffffffffffff831660009081526101026020526040812054925082141561057d5750610494565b60016001600050540360006000505411156105985750610494565b600060028361010081106105a857005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104e46103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b15610494576001548211156106365750610496565b60008290556106436103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b15610494575061010655565b156104965760006101055550565b15610494578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107485773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161076157005b604060003680828437909120915061076d9050816101ae565b50600091506108949050565b15801561079d57506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561089457600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f0191909104810190849086821561089c579182015b8281111561089c57823582600050559160200191906001019061080a565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b8082111561082857600081556001016108a0565b505b919050565b156108b4576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108b45760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561094357915260208220825b81548152906001019060200180831161092f575b5050600084866185025a03f161095557005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109f357820191906000526020600020905b8154815290600101906020018083116109df575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a6e5760008155600101610a5a565b5050505060019150506108b6565b6000868152610103602052604081208054909450909250821415610b07578154835560018381018390556101048054918201808255828015829011610b93578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b915760008155600101610ae6565b6000918252602090912001555b506001820154600284900a90811660001415610bde5773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610bad576000868152610103602052610104805460409092206002015490918110610be757005b505b5050506002840181905561010480548892908110610afa57005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bde565b5090565b01546000145b15610c8757600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2857506001546002906101008110610c2257005b0154600014155b15610c56576001016104f8565b60015481108015610cab57506001546002906101008110610ca457005b0154600014155b8015610cc657506002816101008110610cc057005b01546000145b15610cdf576001546002906101008110610ce457005b01555b6104ed565b01546002826101008110610cf457005b01558061010260006002836101008110610d0a57005b0154815260208101919091526040016000908120919091556001546002906101008110610cdc57005b156108b65761010754610d495b62015180420490565b1115610d6257600061010555610d5d610d40565b610107555b6101055480830110158015610d805750610105546101065490830111155b15610d96575061010580548201905560016108b6565b5060006108b6565b6104946101045460005b81811015610e4757610104805482908110610e8f57005b6000918252602080832090910154835282810193909352604091909101812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600181018290556002810180548382559083528383209193601f91909101048101905b80821115610e3b5760008155600101610e27565b505050506001016103f6565b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610e7b565b6000918252602082200154141515610ee15761010480546101039160009184908110610eb757005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b600101610da856", - "gasLimit" : "0x116ffc", + "data" : "606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "gasLimit" : "0x12343f", "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", @@ -481,8 +481,8 @@ { "transactions" : [ { - "data" : "600160008181558180553373ffffffffffffffffffffffffffffffffffffffff16600381905581526101026020526040902055620151804204610107557f9adeddf84386b336eb7b3e18e7a6099be08fd81ea5d5142f4d2b630f8d20cf0160006040a1610e39806100716000396000f3007c01000000000000000000000000000000000000000000000000000000006000350463173825d981146100ed5780632f54bf6e1461013f5780635c52c2f5146101705780637065cb481461018a578063797af627146101a7578063b20d30a9146101ba578063b61d27f6146101d7578063b75c7dc6146101fe578063ba51a6df1461023b578063cbf0b0c014610258578063f00d4b5d146102755761029760003411156100eb5773ffffffffffffffffffffffffffffffffffffffff33166040908152346060527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9080a15b565b6102976004356000604060003680828437909120905061053b815b73ffffffffffffffffffffffffffffffffffffffff33166000908152610102602052604081205481808083811415610a7557610bd7565b61029d6004355b73ffffffffffffffffffffffffffffffffffffffff16600090815261010260205260408120541190565b610297604060003680828437909120905061067781610108565b610297600435604060003680828437909120905061049281610108565b61029d6004355b6000816108b481610108565b610297600435604060003680828437909120905061066b81610108565b61029d6004803590602480359160443591820191013560006106a3846000610dce33610146565b61029760043573ffffffffffffffffffffffffffffffffffffffff331660009081526101026020526040812054908080838114156102a757610329565b610297600435604060003680828437909120905061061a81610108565b610297600435604060003680828437909120905061068581610108565b6102976004356024356000604060003680828437909120905061039c81610108565b60006000f35b8060005260206000f35b5050506000828152610103602052604081206001810154600284900a929083168190111561032957815460018084018054919092018455849003905573ffffffffffffffffffffffffffffffffffffffff3316604090815260608690527fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b9080a15b5050505050565b015573ffffffffffffffffffffffffffffffffffffffff84811660008181526101026020526040808220829055928616808252908390208590559082526060527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9080a15b505b505050565b15610395576103aa83610146565b156103b55750610397565b73ffffffffffffffffffffffffffffffffffffffff84166000908152610102602052604081205492508214156103eb5750610397565b61040d5b6101045460005b81811015610d2c57610104805482908110610d7457005b73ffffffffffffffffffffffffffffffffffffffff8316600283610100811061033057005b015560015473ffffffffffffffffffffffffffffffffffffffff831660008181526101026020908152604091829020939093559081527f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c39190a15b505b50565b1561048d576104a082610146565b156104ab575061048f565b6104b36103ef565b60015460fa901015156104ca576104c86104e1565b505b60015460fa9010151561050b575061048f565b6105d25b600060015b600154811015610c17575b60015481108015610c7357506002816101008110610c6c57005b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff831690600290610100811061043257005b156103975773ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120549250821415610576575061048d565b6001600160005054036000600050541115610591575061048d565b600060028361010081106105a157005b015573ffffffffffffffffffffffffffffffffffffffff8316600090815261010260205260408120556104dd6103ef565b5073ffffffffffffffffffffffffffffffffffffffff831660409081527f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da90602090a1505050565b1561048d5760015482101561062f575061048f565b600082905561063c6103ef565b60408281527facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da90602090a15050565b1561048d575061010655565b1561048f5760006101055550565b1561048d578173ffffffffffffffffffffffffffffffffffffffff16ff5b156107415773ffffffffffffffffffffffffffffffffffffffff3381166040526060859052851660805260a08290527f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004838360c082828082843750505060800190506040a18473ffffffffffffffffffffffffffffffffffffffff16846000600060008787808284378201915050600084866185025a03f161075a57005b60406000368082843790912091506107669050816101ae565b506000915061088d9050565b15801561079657506000818152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff16145b1561088d57600081815261010860209081526040822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610895579182015b82811115610895578235826000505591602001919060010190610803565b505050604081905273ffffffffffffffffffffffffffffffffffffffff3381166060526080859052851660a05260c08290527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32838360e0828280828437505060a0909101915060409050a15b949350505050565b5090505b808211156108215760008155600101610899565b505b919050565b156108ad576000838152610108602052604081205473ffffffffffffffffffffffffffffffffffffffff161415156108ad5760406000908120805460018201546002909201805473ffffffffffffffffffffffffffffffffffffffff92909216939182918291801561093c57915260208220825b815481529060010190602001808311610928575b5050600084866185025a03f161094e57005b505073ffffffffffffffffffffffffffffffffffffffff3381166040908152606085905260008581526101086020529081206001810154608052805490921660a0526002909101805460c08190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a929060e090839080156109ec57820191906000526020600020905b8154815290600101906020018083116109d8575b5050915050604090036040a1600083815261010860209081526040822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560018101839055600281018054848255908452828420919392601f91909101048101905b80821115610a675760008155600101610a53565b5050505060019150506108af565b6000868152610103602052604081208054909450909250821415610b00578154835560018381018390556101048054918201808255828015829011610b8c578286527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019082015b80821115610b8a5760008155600101610adf565b6000918252602090912001555b506001820154600284900a90811660001415610bd75773ffffffffffffffffffffffffffffffffffffffff3316604090815260608790527fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda9080a18254600190111515610ba6576000868152610103602052610104805460409092206002015490918110610be057005b505b5050506002840181905561010480548892908110610af357005b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018355600183018054821790555b50505050919050565b6000918252602080832090910182905587825261010390526040812081815560018181018390556002909101919091559450610bd7565b5090565b01546000145b15610c8057600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b60018054118015610c2157506001546002906101008110610c1b57005b0154600014155b15610c4f576001016104f1565b60015481108015610ca457506001546002906101008110610c9d57005b0154600014155b8015610cbf57506002816101008110610cb957005b01546000145b15610cd8576001546002906101008110610cdd57005b01555b6104e6565b01546002826101008110610ced57005b01558061010260006002836101008110610d0357005b0154815260208101919091526040016000908120919091556001546002906101008110610cd557005b61010480546000808355919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe908101905b808211156103955760008155600101610d60565b6000918252602082200154141515610dc65761010480546101039160009184908110610d9c57005b60009182526020808320909101548352820192909252604001812081815560018101829055600201555b6001016103f6565b156108af5761010754610de45b62015180420490565b1115610dfd57600061010555610df8610ddb565b610107555b6101055480830110158015610e1b5750610105546101065490830111155b15610e31575061010580548201905560016108af565b5060006108af56", - "gasLimit" : "0x116ffc", + "data" : "606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "gasLimit" : "0x12343f", "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", From 6c0e682ffc3f3e26e16110447c2665f204029e08 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 10 Jul 2015 13:45:41 +0200 Subject: [PATCH 278/290] Add minelog, a verbosity 1 logger for ethminer --- ethminer/MinerAux.h | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 80886cd7a..ff28132b1 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -81,6 +81,12 @@ inline std::string credits() } class BadArgument: public Exception {}; +struct MiningChannel: public LogChannel +{ + static const char* name() { return EthGreen "miner"; } + static const int verbosity = 2; +}; +#define minelog clog(MiningChannel) class MinerCLI { @@ -484,14 +490,14 @@ private: for (unsigned i = 0; !completed; ++i) { if (current) - cnote << "Mining on PoWhash" << current.headerHash << ": " << f.miningProgress(); + minelog << "Mining on PoWhash" << current.headerHash << ": " << f.miningProgress(); else - cnote << "Getting work package..."; + minelog << "Getting work package..."; Json::Value v = rpc.eth_getWork(); h256 hh(v[0].asString()); h256 newSeedHash(v[1].asString()); if (current.seedHash != newSeedHash) - cnote << "Grabbing DAG for" << newSeedHash; + minelog << "Grabbing DAG for" << newSeedHash; if (!(dag = EthashAux::full(newSeedHash, true, [&](unsigned _pc){ cout << "\rCreating DAG. " << _pc << "% done..." << flush; return 0; }))) BOOST_THROW_EXCEPTION(DAGCreationFailure()); if (m_precompute) @@ -501,10 +507,10 @@ private: current.headerHash = hh; current.seedHash = newSeedHash; current.boundary = h256(fromHex(v[2].asString()), h256::AlignRight); - cnote << "Got work package:"; - cnote << " Header-hash:" << current.headerHash.hex(); - cnote << " Seedhash:" << current.seedHash.hex(); - cnote << " Target: " << h256(current.boundary).hex(); + minelog << "Got work package:"; + minelog << " Header-hash:" << current.headerHash.hex(); + minelog << " Seedhash:" << current.seedHash.hex(); + minelog << " Target: " << h256(current.boundary).hex(); f.setWork(current); } this_thread::sleep_for(chrono::milliseconds(_recheckPeriod)); From 359c4082b0cd235a396ae63e96f74ad4642928fb Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Fri, 10 Jul 2015 14:06:24 +0200 Subject: [PATCH 279/290] update wallet test --- .../bcWalletTestFiller.json | 21 +++++++++---------- .../StateTestsFiller/stWalletTestFiller.json | 2 +- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/test/libethereum/BlockchainTestsFiller/bcWalletTestFiller.json b/test/libethereum/BlockchainTestsFiller/bcWalletTestFiller.json index cc869b967..ed4574cb0 100644 --- a/test/libethereum/BlockchainTestsFiller/bcWalletTestFiller.json +++ b/test/libethereum/BlockchainTestsFiller/bcWalletTestFiller.json @@ -41,7 +41,7 @@ { "transactions" : [ { - "data" : "606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "data" : "6060604052604051602080611014833960806040818152925160016000818155818055600160a060020a03331660038190558152610102909452938320939093556201518042046101075582917f102d25c49d33fcdb8976a3f2744e0785c98d9e43b88364859e6aec4ae82eff5c91a250610f958061007f6000396000f300606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "gasLimit" : "0x12343f", "gasPrice" : "1", "nonce" : "0", @@ -116,7 +116,7 @@ { "transactions" : [ { - "data" : "0x797af6276877e4536b661640954061cdbc3a9761fb5245c340fcb1721307cd9d5f285c96", + "data" : "0x797af62745cdc51a93c670e2712bcef060b979e79bd8c4c25fb303229debad0010481f16", "gasLimit" : "20141591", "gasPrice" : "1", "nonce" : "0", @@ -130,7 +130,6 @@ } ] }, - "wallet2outOf3txsRevoke" : { "genesisBlockHeader" : { "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", @@ -173,7 +172,7 @@ { "transactions" : [ { - "data" : "606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "data" : "6060604052604051602080611014833960806040818152925160016000818155818055600160a060020a03331660038190558152610102909452938320939093556201518042046101075582917f102d25c49d33fcdb8976a3f2744e0785c98d9e43b88364859e6aec4ae82eff5c91a250610f958061007f6000396000f300606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "gasLimit" : "0x12343f", "gasPrice" : "1", "nonce" : "0", @@ -248,7 +247,7 @@ { "transactions" : [ { - "data" : "0xb75c7dc66877e4536b661640954061cdbc3a9761fb5245c340fcb1721307cd9d5f285c96", + "data" : "0xb75c7dc645cdc51a93c670e2712bcef060b979e79bd8c4c25fb303229debad0010481f16", "gasLimit" : "20141591", "gasPrice" : "1", "nonce" : "5", @@ -263,7 +262,7 @@ { "transactions" : [ { - "data" : "0x797af6276877e4536b661640954061cdbc3a9761fb5245c340fcb1721307cd9d5f285c96", + "data" : "0x797af62745cdc51a93c670e2712bcef060b979e79bd8c4c25fb303229debad0010481f16", "gasLimit" : "20141591", "gasPrice" : "1", "nonce" : "0", @@ -319,7 +318,7 @@ { "transactions" : [ { - "data" : "606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "data" : "6060604052604051602080611014833960806040818152925160016000818155818055600160a060020a03331660038190558152610102909452938320939093556201518042046101075582917f102d25c49d33fcdb8976a3f2744e0785c98d9e43b88364859e6aec4ae82eff5c91a250610f958061007f6000396000f300606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "gasLimit" : "0x12343f", "gasPrice" : "1", "nonce" : "0", @@ -394,7 +393,7 @@ { "transactions" : [ { - "data" : "0xb75c7dc66877e4536b661640954061cdbc3a9761fb5245c340fcb1721307cd9d5f285c96", + "data" : "0xb75c7dc645cdc51a93c670e2712bcef060b979e79bd8c4c25fb303229debad0010481f16", "gasLimit" : "20141591", "gasPrice" : "1", "nonce" : "5", @@ -409,7 +408,7 @@ { "transactions" : [ { - "data" : "0x797af6276877e4536b661640954061cdbc3a9761fb5245c340fcb1721307cd9d5f285c96", + "data" : "0x797af62745cdc51a93c670e2712bcef060b979e79bd8c4c25fb303229debad0010481f16", "gasLimit" : "20141591", "gasPrice" : "1", "nonce" : "6", @@ -424,7 +423,7 @@ { "transactions" : [ { - "data" : "0x797af6276877e4536b661640954061cdbc3a9761fb5245c340fcb1721307cd9d5f285c96", + "data" : "0x797af62745cdc51a93c670e2712bcef060b979e79bd8c4c25fb303229debad0010481f16", "gasLimit" : "20141591", "gasPrice" : "1", "nonce" : "0", @@ -481,7 +480,7 @@ { "transactions" : [ { - "data" : "606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", + "data" : "6060604052604051602080611014833960806040818152925160016000818155818055600160a060020a03331660038190558152610102909452938320939093556201518042046101075582917f102d25c49d33fcdb8976a3f2744e0785c98d9e43b88364859e6aec4ae82eff5c91a250610f958061007f6000396000f300606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e146101675780634123cb6b1461018f5780635c52c2f5146101985780637065cb48146101c9578063746c9171146101fd578063797af62714610206578063b20d30a914610219578063b61d27f61461024d578063b75c7dc61461026e578063ba51a6df1461029e578063c2cf7326146102d2578063cbf0b0c014610312578063f00d4b5d14610346578063f1736d861461037f575b61038960003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610389600435600060003643604051808484808284375050509091019081526040519081900360200190209050610693815b600160a060020a0333166000908152610102602052604081205481808083811415610c1357610d6c565b61038b6004355b600160a060020a03811660009081526101026020526040812054115b919050565b61038b60015481565b610389600036436040518084848082843750505090910190815260405190819003602001902090506107e58161013d565b6103896004356000364360405180848480828437505050909101908152604051908190036020019020905061060b8161013d565b61038b60005481565b61038b6004355b600081610a4b8161013d565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107d98161013d565b61038b6004803590602480359160443591820191013560006108043361016e565b610389600435600160a060020a033316600090815261010260205260408120549080808381141561039d5761041f565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107528161013d565b61038b600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054829081818114156107ab576107cf565b610389600435600036436040518084848082843750505090910190815260405190819003602001902090506107f38161013d565b6103896004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104ac8161013d565b61038b6101055481565b005b60408051918252519081900360200190f35b5050506000828152610103602052604081206001810154600284900a929083168190111561041f5781546001838101805492909101845590849003905560408051600160a060020a03331681526020810187905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5050505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b505b505050565b156104a5576104ba8361016e565b156104c557506104a7565b600160a060020a0384166000908152610102602052604081205492508214156104ee57506104a7565b6104265b6101045460005b81811015610eba57610104805461010891600091849081101561000257600080516020610f7583398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f3f92601f9290920104810190610a33565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b15610606576106198261016e565b156106245750610608565b61062c6104f2565b60015460fa90106106415761063f610656565b505b60015460fa901061056c5750610608565b6107105b600060015b600154811015610a47575b600154811080156106865750600281610100811015610002570154600014155b15610d7557600101610666565b156104a757600160a060020a0383166000908152610102602052604081205492508214156106c15750610606565b60016001600050540360006000505411156106dc5750610606565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556106526104f2565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b15610606576001548211156107675750610608565b60008290556107746104f2565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001830154600282900a908116600014156107ca57600094506107cf565b600194505b5050505092915050565b15610606575061010555565b156106085760006101065550565b156106065781600160a060020a0316ff5b15610a2357610818846000610e4f3361016e565b156108d4577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a2392505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061090490508161020d565b158015610927575060008181526101086020526040812054600160a060020a0316145b15610a235760008181526101086020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a2b579182015b82811115610a2b57823582600050559160200191906001019061097c565b50600050507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b5061099a9291505b80821115610a475760008155600101610a33565b5090565b15610c005760008381526101086020526040812054600160a060020a031614610c0057604080516000918220805460018201546002929092018054600160a060020a0392909216949293909291819084908015610acd57820191906000526020600020905b815481529060010190602001808311610ab057829003601f168201915b50509250505060006040518083038185876185025a03f1505050600084815261010860209081526040805181842080546001820154600160a060020a033381811686529685018c905294840181905293166060830181905260a06080840181815260029390930180549185018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a985095968b969294929390929160c083019085908015610ba257820191906000526020600020905b815481529060010190602001808311610b8557829003601f168201915b505097505050505050505060405180910390a160008381526101086020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c0692601f9290920104810190610a33565b50919050565b505050600191505061018a565b6000868152610103602052604081208054909450909250821415610c9c578154835560018381018390556101048054918201808255828015829011610c6b57818360005260206000209182019101610c6b9190610a33565b50505060028401819055610104805488929081101561000257600091909152600080516020610f7583398151915201555b506001820154600284900a90811660001415610d6c5760408051600160a060020a03331681526020810188905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1825460019011610d59576000868152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f758339815191529290920181905580825560018083018290556002909201559550610d6c9050565b8254600019018355600183018054821790555b50505050919050565b5b60018054118015610d9857506001546002906101008110156100025701546000145b15610dac5760018054600019019055610d76565b60015481108015610dcf5750600154600290610100811015610002570154600014155b8015610de957506002816101008110156100025701546000145b15610e4a57600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b61065b565b1561018a5761010754610e655b62015180420490565b1115610e7e57600061010655610e79610e5c565b610107555b6101065480830110801590610e9c5750610106546101055490830111155b15610eb25750610106805482019055600161018a565b50600061018a565b6106066101045460005b81811015610f4a5761010480548290811015610002576000918252600080516020610f75833981519152015414610f3757610104805461010391600091849081101561000257600080516020610f7583398151915201548252506020919091526040812081815560018101829055600201555b600101610ec4565b5050506001016104f9565b61010480546000808355919091526104a790600080516020610f7583398151915290810190610a3356004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", "gasLimit" : "0x12343f", "gasPrice" : "1", "nonce" : "0", diff --git a/test/libethereum/StateTestsFiller/stWalletTestFiller.json b/test/libethereum/StateTestsFiller/stWalletTestFiller.json index 952b073d3..51c3daec7 100644 --- a/test/libethereum/StateTestsFiller/stWalletTestFiller.json +++ b/test/libethereum/StateTestsFiller/stWalletTestFiller.json @@ -1270,7 +1270,7 @@ "storage" : { "0x00" : "0x01", "0x01" : "0x01", - "0x0106" : "0x04", + "0x0105" : "0x04", "0x03" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x6e369836487c234b9e553ef3f787c2d8865520739d340c67b3d251a33986e58d" : "0x01" } From 68d785e7c3285794af82c2e2e2732b322618ed12 Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 10 Jul 2015 14:09:49 +0200 Subject: [PATCH 280/290] macro fail --- libethereum/EthereumHost.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 88f95f64f..f8ad742f8 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -118,7 +118,7 @@ void EthereumHost::doWork() if (m_syncStart) { - DEV_GUARDED(x_sync); + DEV_GUARDED(x_sync) if (!m_sync) { time_t now = std::chrono::system_clock::to_time_t(chrono::system_clock::now()); From cb438988b4916c883540407936357e3d6e4a7d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 10 Jul 2015 15:13:50 +0200 Subject: [PATCH 281/290] Fix some cmake problems. --- ethminer/CMakeLists.txt | 2 +- exp/CMakeLists.txt | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/ethminer/CMakeLists.txt b/ethminer/CMakeLists.txt index df828bc47..8b12530a5 100644 --- a/ethminer/CMakeLists.txt +++ b/ethminer/CMakeLists.txt @@ -9,6 +9,7 @@ if (JSONRPC) include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) endif() +include_directories(${OpenCL_INCLUDE_DIRS}) set(EXECUTABLE ethminer) @@ -40,4 +41,3 @@ if (APPLE) else() eth_install_executable(${EXECUTABLE}) endif() - diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index 823425598..203022655 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -6,6 +6,7 @@ aux_source_directory(. SRC_LIST) include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) include_directories(BEFORE ..) include_directories(${DB_INCLUDE_DIRS}) +include_directories(${OpenCL_INCLUDE_DIRS}) set(EXECUTABLE exp) @@ -27,11 +28,6 @@ target_link_libraries(${EXECUTABLE} p2p) if (ETHASHCL) target_link_libraries(${EXECUTABLE} ethash-cl) target_link_libraries(${EXECUTABLE} ethash) - target_link_libraries(${EXECUTABLE} OpenCL) + target_link_libraries(${EXECUTABLE} ${OpenCL_LIBRARIES}) endif() -install( TARGETS ${EXECUTABLE} DESTINATION bin) - - - - - +install( TARGETS ${EXECUTABLE} DESTINATION bin) From ab69d8a357d22f411c756459aaafb2936025042a Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 8 Jul 2015 19:42:52 +0200 Subject: [PATCH 282/290] check clang version before disabling warning --- alethzero/CMakeLists.txt | 2 +- mix/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 25bd3de59..8bc349fb2 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -7,7 +7,7 @@ if (${CMAKE_MAJOR_VERSION} GREATER 2) cmake_policy(SET CMP0043 OLD) endif() -if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") +if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "3.6") AND NOT APPLE) # Supress warnings for qt headers for clang+ccache set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override") endif () diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index 01102ee53..c239edd47 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -15,7 +15,7 @@ include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS}) include_directories(BEFORE ..) -if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") +if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "3.6") AND NOT APPLE) # Supress warnings for qt headers for clang+ccache set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override") endif () From 778e6ff6773535c1ef0ff28b281f7008856f6379 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 10 Jul 2015 14:34:02 -0700 Subject: [PATCH 283/290] Fix for invariant macro. Minor cleanups. Fix for rescue mode. --- eth/main.cpp | 19 ++++++------------- libdevcore/Common.h | 3 ++- libdevcore/FixedHash.h | 2 ++ libdevcore/Guards.h | 2 +- libethereum/Client.cpp | 3 +++ libethereum/Client.h | 2 -- 6 files changed, 14 insertions(+), 17 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 73adddf1e..24520d8c4 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -266,8 +266,7 @@ enum class OperationMode { Node, Import, - Export, - Rescue + Export }; enum class Format @@ -1085,7 +1084,7 @@ int main(int argc, char** argv) #endif string jsonAdmin; bool upnp = true; - WithExisting killChain = WithExisting::Trust; + WithExisting withExisting = WithExisting::Trust; bool jit = false; string sentinel; @@ -1252,11 +1251,11 @@ int main(int argc, char** argv) return -1; } else if (arg == "-K" || arg == "--kill-blockchain" || arg == "--kill") - killChain = WithExisting::Kill; + withExisting = WithExisting::Kill; else if (arg == "-R" || arg == "--rebuild") - killChain = WithExisting::Verify; + withExisting = WithExisting::Verify; else if (arg == "-R" || arg == "--rescue") - mode = OperationMode::Rescue; + withExisting = WithExisting::Rescue; else if ((arg == "-c" || arg == "--client-name") && i + 1 < argc) { if (arg == "-c") @@ -1534,7 +1533,7 @@ int main(int argc, char** argv) dev::WebThreeDirect web3( WebThreeDirect::composeClientVersion("++eth", clientName), dbPath, - killChain, + withExisting, nodeMode == NodeMode::Full ? set{"eth"/*, "shh"*/} : set(), netPrefs, &nodesState); @@ -1556,12 +1555,6 @@ int main(int argc, char** argv) } }; - if (mode == OperationMode::Rescue) - { - web3.ethereum()->rescue(); - exit(0); - } - if (mode == OperationMode::Export) { ofstream fout(filename, std::ofstream::binary); diff --git a/libdevcore/Common.h b/libdevcore/Common.h index edd14f4a5..303512e57 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -189,7 +189,7 @@ private: /// Scope guard for invariant check in a class derived from HasInvariants. #if ETH_DEBUG -#define DEV_INVARIANT_CHECK { ::dev::InvariantChecker __dev_invariantCheck(this, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__); } +#define DEV_INVARIANT_CHECK ::dev::InvariantChecker __dev_invariantCheck(this, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__) #else #define DEV_INVARIANT_CHECK (void)0; #endif @@ -240,6 +240,7 @@ enum class WithExisting: int { Trust = 0, Verify, + Rescue, Kill }; diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index a9922063a..3127b349a 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -106,6 +106,8 @@ public: FixedHash& operator&=(FixedHash const& _c) { for (unsigned i = 0; i < N; ++i) m_data[i] &= _c.m_data[i]; return *this; } FixedHash operator&(FixedHash const& _c) const { return FixedHash(*this) &= _c; } FixedHash operator~() const { FixedHash ret; for (unsigned i = 0; i < N; ++i) ret[i] = ~m_data[i]; return ret; } + + // Big-endian increment. FixedHash& operator++() { for (unsigned i = size; i > 0 && !++m_data[--i]; ) {} return *this; } /// @returns true if all one-bits in @a _c are set in this object. diff --git a/libdevcore/Guards.h b/libdevcore/Guards.h index 2d3eced32..44d5969e4 100644 --- a/libdevcore/Guards.h +++ b/libdevcore/Guards.h @@ -95,7 +95,7 @@ using SpinGuard = std::lock_guard; * Mutex m; * int d; * ... - * ETH_(m) + * ETH_GUARDED(m) * { * for (auto d = 50; d > 25; --d) * foo(d); diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 2295904cc..054cd1c9b 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -90,6 +90,9 @@ Client::Client(p2p::Host* _extNet, std::shared_ptr _gp, std::string c m_preMine(m_stateDB, BaseState::CanonGenesis), m_postMine(m_stateDB) { + if (_forceAction == WithExisting::Rescue) + m_bc.rescue(m_stateDB); + m_lastGetWork = std::chrono::system_clock::now() - chrono::seconds(30); m_tqReady = m_tq.onReady([=](){ this->onTransactionQueueReady(); }); // TODO: should read m_tq->onReady(thisThread, syncTransactionQueue); m_bqReady = m_bq.onReady([=](){ this->onBlockQueueReady(); }); // TODO: should read m_bq->onReady(thisThread, syncBlockQueue); diff --git a/libethereum/Client.h b/libethereum/Client.h index 5124f3778..fac54b010 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -219,8 +219,6 @@ public: void setExtraData(bytes const& _extraData) { m_extraData = _extraData; } /// Rewind to a prior head. void rewind(unsigned _n) { m_bc.rewind(_n); } - /// Rescue the chain. - void rescue() { stopWorking(); m_bc.rescue(m_stateDB); } protected: /// InterfaceStub methods From 4cfc62e199d0ecab3e3c452389690c589c9785e0 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 10 Jul 2015 15:01:22 -0700 Subject: [PATCH 284/290] Final fix for rescue. --- libethereum/BlockChain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 43b115c49..d9a54a1ee 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -842,7 +842,7 @@ void BlockChain::rescue(OverlayDB& _db) cout << "details..." << flush; BlockDetails bd = details(h); cout << "state..." << flush; - if (_db.exists(sha3(bi.stateRoot))) + if (_db.exists(bi.stateRoot)) break; } catch (...) {} From 829bcd01460a081bf1f48f597b5db7a041af2ebb Mon Sep 17 00:00:00 2001 From: Dimitry Khokhlov Date: Fri, 3 Jul 2015 18:02:18 +0400 Subject: [PATCH 285/290] RLPTests: refactoring --- test/TestHelper.h | 1 + test/libdevcore/rlp.cpp | 225 ++++++++++++++++++++++++---------------- 2 files changed, 139 insertions(+), 87 deletions(-) diff --git a/test/TestHelper.h b/test/TestHelper.h index 1c1dfb5f0..4ac59e917 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -188,6 +188,7 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin); void doStateTests(json_spirit::mValue& v, bool _fillin); void doVMTests(json_spirit::mValue& v, bool _fillin); void doBlockchainTests(json_spirit::mValue& _v, bool _fillin); +void doRlpTests(json_spirit::mValue& v, bool _fillin); template void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs) diff --git a/test/libdevcore/rlp.cpp b/test/libdevcore/rlp.cpp index 86780cfa6..04cb6f794 100644 --- a/test/libdevcore/rlp.cpp +++ b/test/libdevcore/rlp.cpp @@ -40,8 +40,86 @@ namespace js = json_spirit; namespace dev { namespace test - { - static void buildRLP(js::mValue& _v, RLPStream& _rlp) + { + void buildRLP(js::mValue& _v, RLPStream& _rlp); + void checkRLPAgainstJson(js::mValue& v, RLP& u); + + void doRlpTests(json_spirit::mValue& v, bool _fillin) + { + for (auto& i: v.get_obj()) + { + js::mObject& o = i.second.get_obj(); + if (test::Options::get().singleTest && test::Options::get().singleTestName != i.first) + { + o.clear(); + continue; + } + + std::cout << " " << i.first << std::endl; + TBOOST_REQUIRE((o.count("in") > 0)); + TBOOST_REQUIRE((o.count("out") > 0)); + TBOOST_REQUIRE(!o["out"].is_null()); + + if (!_fillin) + { + //Check Encode + bool skipEncode = false; + if (o["in"].type() == js::str_type) + if (o["in"].get_str() == "INVALID") + skipEncode = true; + + if (!skipEncode) + { + RLPStream s; + dev::test::buildRLP(o["in"], s); + string computedText = toHex(s.out()); + + std::string expectedText(o["out"].get_str()); + std::transform(expectedText.begin(), expectedText.end(), expectedText.begin(), ::tolower ); + + std::stringstream msg; + msg << "Encoding Failed: expected: " << expectedText << std::endl; + msg << " But Computed: " << computedText; + TBOOST_CHECK_MESSAGE( + (expectedText == computedText), + msg.str() + ); + } + + //Check Decode + // Uses the same test cases as encoding but in reverse. + // We read into the string of hex values, convert to bytes, + // and then compare the output structure to the json of the + // input object. + bool was_exception = false; + js::mValue& inputData = o["in"]; + try + { + bytes payloadToDecode = fromHex(o["out"].get_str()); + RLP payload(payloadToDecode); + dev::test::checkRLPAgainstJson(inputData, payload); + } + catch (Exception const& _e) + { + cnote << "Exception: " << diagnostic_information(_e); + was_exception = true; + } + catch (std::exception const& _e) + { + cnote << "rlp exception: " << _e.what(); + was_exception = true; + } + + if (skipEncode && was_exception) + continue; + + if (was_exception) + TBOOST_ERROR("Unexpected RLP Exception!"); + } + } + } + + void buildRLP(js::mValue& _v, RLPStream& _rlp) { if (_v.type() == js::array_type) { @@ -62,25 +140,7 @@ namespace dev } } - static void getRLPTestCases(js::mValue& v) - { - string testPath = getTestPath(); - testPath += "/BasicTests"; - - string s = contentsString(testPath + "/rlptest.json"); - BOOST_REQUIRE_MESSAGE( s.length() > 0, - "Contents of 'rlptest.json' is empty. Have you cloned the 'tests' repo branch develop?"); - js::read_string(s, v); - } - - static void checkRLPTestCase(js::mObject& o) - { - BOOST_REQUIRE( o.count("in") > 0 ); - BOOST_REQUIRE( o.count("out") > 0 ); - BOOST_REQUIRE(!o["out"].is_null()); - } - - static void checkRLPAgainstJson(js::mValue& v, RLP& u) + void checkRLPAgainstJson(js::mValue& v, RLP& u) { if ( v.type() == js::str_type ) { @@ -92,37 +152,37 @@ namespace dev std::stringstream bintStream(bigIntStr); bigint val; bintStream >> val; - BOOST_CHECK( !u.isList() ); - BOOST_CHECK( !u.isNull() ); - BOOST_CHECK( u ); // operator bool() - BOOST_CHECK(u == val); + TBOOST_CHECK( !u.isList() ); + TBOOST_CHECK( !u.isNull() ); + TBOOST_CHECK( u ); // operator bool() + TBOOST_CHECK(u == val); } else { - BOOST_CHECK( !u.isList() ); - BOOST_CHECK( !u.isNull() ); - BOOST_CHECK( u.isData() ); - BOOST_CHECK( u ); - BOOST_CHECK( u.size() == expectedText.length() ); - BOOST_CHECK(u == expectedText); + TBOOST_CHECK( !u.isList() ); + TBOOST_CHECK( !u.isNull() ); + TBOOST_CHECK( u.isData() ); + TBOOST_CHECK( u ); + TBOOST_CHECK( u.size() == expectedText.length() ); + TBOOST_CHECK(u == expectedText); } } else if ( v.type() == js::int_type ) { const int expectedValue = v.get_int(); - BOOST_CHECK( u.isInt() ); - BOOST_CHECK( !u.isList() ); - BOOST_CHECK( !u.isNull() ); - BOOST_CHECK( u ); // operator bool() - BOOST_CHECK(u == expectedValue); + TBOOST_CHECK( u.isInt() ); + TBOOST_CHECK( !u.isList() ); + TBOOST_CHECK( !u.isNull() ); + TBOOST_CHECK( u ); // operator bool() + TBOOST_CHECK(u == expectedValue); } else if ( v.type() == js::array_type ) { - BOOST_CHECK( u.isList() ); - BOOST_CHECK( !u.isInt() ); - BOOST_CHECK( !u.isData() ); + TBOOST_CHECK( u.isList() ); + TBOOST_CHECK( !u.isInt() ); + TBOOST_CHECK( !u.isData() ); js::mArray& arr = v.get_array(); - BOOST_CHECK( u.itemCount() == arr.size() ); + TBOOST_CHECK( u.itemCount() == arr.size() ); unsigned i; for( i = 0; i < arr.size(); i++ ) { @@ -132,71 +192,62 @@ namespace dev } else { - BOOST_ERROR("Invalid Javascript object!"); + TBOOST_ERROR("Invalid Javascript object!"); } - } } } -BOOST_AUTO_TEST_SUITE(BasicTests) +BOOST_AUTO_TEST_SUITE(RlpTests) -BOOST_AUTO_TEST_CASE(rlp_encoding_test) +BOOST_AUTO_TEST_CASE(invalidRLPtest) { - cnote << "Testing RLP Encoding..."; - js::mValue v; - dev::test::getRLPTestCases(v); - - for (auto& i: v.get_obj()) - { - js::mObject& o = i.second.get_obj(); - cnote << i.first; - dev::test::checkRLPTestCase(o); - - RLPStream s; - dev::test::buildRLP(o["in"], s); - - std::string expectedText(o["out"].get_str()); - std::transform(expectedText.begin(), expectedText.end(), expectedText.begin(), ::tolower ); - - const std::string& computedText = toHex(s.out()); + dev::test::executeTests("invalidRLPtest", "/BasicTests", dev::test::getFolder(__FILE__) + "/StateTestsFiller", dev::test::doRlpTests); +} - std::stringstream msg; - msg << "Encoding Failed: expected: " << expectedText << std::endl; - msg << " But Computed: " << computedText; - - BOOST_CHECK_MESSAGE( - expectedText == computedText, - msg.str() - ); - } +BOOST_AUTO_TEST_CASE(rlptest) +{ + dev::test::executeTests("rlptest", "/BasicTests", dev::test::getFolder(__FILE__) + "/StateTestsFiller", dev::test::doRlpTests); } -BOOST_AUTO_TEST_CASE(rlp_decoding_test) +BOOST_AUTO_TEST_CASE(rlpRandom) { - cnote << "Testing RLP decoding..."; - // Uses the same test cases as encoding but in reverse. - // We read into the string of hex values, convert to bytes, - // and then compare the output structure to the json of the - // input object. - js::mValue v; - dev::test::getRLPTestCases(v); - for (auto& i: v.get_obj()) - { - js::mObject& o = i.second.get_obj(); - cnote << i.first; - dev::test::checkRLPTestCase(o); + test::Options::get(); - js::mValue& inputData = o["in"]; - bytes payloadToDecode = fromHex(o["out"].get_str()); + string testPath = dev::test::getTestPath(); + testPath += "/BasicTests/RandomRLPTests"; - RLP payload(payloadToDecode); + vector testFiles; + boost::filesystem::directory_iterator iterator(testPath); + for(; iterator != boost::filesystem::directory_iterator(); ++iterator) + if (boost::filesystem::is_regular_file(iterator->path()) && iterator->path().extension() == ".json") + testFiles.push_back(iterator->path()); - dev::test::checkRLPAgainstJson(inputData, payload); + for (auto& path: testFiles) + { + try + { + cnote << "Testing ..." << path.filename(); + json_spirit::mValue v; + string s = asString(dev::contents(path.string())); + TBOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + path.string() + " is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); + json_spirit::read_string(s, v); + test::Listener::notifySuiteStarted(path.filename().string()); + dev::test::doRlpTests(v, false); + } + catch (Exception const& _e) + { + TBOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); + } + catch (std::exception const& _e) + { + TBOOST_ERROR("Failed test with Exception: " << _e.what()); + } } } + BOOST_AUTO_TEST_SUITE_END() From 04e257a8cbbe8273bd9a02db2734fffb28d9d532 Mon Sep 17 00:00:00 2001 From: Dimitry Khokhlov Date: Fri, 3 Jul 2015 18:28:07 +0400 Subject: [PATCH 286/290] RLPTests: fill rlp tests --- test/libdevcore/rlp.cpp | 45 +++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/test/libdevcore/rlp.cpp b/test/libdevcore/rlp.cpp index 04cb6f794..2cc744497 100644 --- a/test/libdevcore/rlp.cpp +++ b/test/libdevcore/rlp.cpp @@ -60,15 +60,41 @@ namespace dev TBOOST_REQUIRE((o.count("out") > 0)); TBOOST_REQUIRE(!o["out"].is_null()); - if (!_fillin) + if (_fillin) + { + try + { + bytes payloadToDecode = fromHex(o["out"].get_str()); + RLP payload(payloadToDecode); + if (payload.isEmpty()) + BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("Decoded Empty RLP!")); + o["in"] = "VALID"; + } + catch (Exception const& _e) + { + cnote << "Exception: " << diagnostic_information(_e); + o["in"] = "INVALID"; + } + catch (std::exception const& _e) + { + cnote << "rlp exception: " << _e.what(); + o["in"] = "INVALID"; + } + } + else { //Check Encode - bool skipEncode = false; + int skipEncode = 0; if (o["in"].type() == js::str_type) + { if (o["in"].get_str() == "INVALID") - skipEncode = true; + skipEncode = 1; + else + if (o["in"].get_str() == "VALID") + skipEncode = 2; + } - if (!skipEncode) + if (skipEncode == 0) { RLPStream s; dev::test::buildRLP(o["in"], s); @@ -97,7 +123,9 @@ namespace dev { bytes payloadToDecode = fromHex(o["out"].get_str()); RLP payload(payloadToDecode); - dev::test::checkRLPAgainstJson(inputData, payload); + + if (skipEncode == 0) + dev::test::checkRLPAgainstJson(inputData, payload); } catch (Exception const& _e) { @@ -110,9 +138,14 @@ namespace dev was_exception = true; } - if (skipEncode && was_exception) + //Expect exception as input is INVALID + if (skipEncode == 1 && was_exception) continue; + //Expect exception as input is INVALID + if (skipEncode == 1 && !was_exception) + TBOOST_ERROR("Expected RLP Exception as rlp should be invalid!"); + if (was_exception) TBOOST_ERROR("Unexpected RLP Exception!"); } From 5309905c2a019145dd4831e923b5baa20ff5a291 Mon Sep 17 00:00:00 2001 From: Dimitry Date: Mon, 6 Jul 2015 16:33:33 +0300 Subject: [PATCH 287/290] RLPTests Refactoring --- test/libdevcore/rlp.cpp | 50 ++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/test/libdevcore/rlp.cpp b/test/libdevcore/rlp.cpp index 2cc744497..b17dcc249 100644 --- a/test/libdevcore/rlp.cpp +++ b/test/libdevcore/rlp.cpp @@ -56,9 +56,8 @@ namespace dev } std::cout << " " << i.first << std::endl; - TBOOST_REQUIRE((o.count("in") > 0)); TBOOST_REQUIRE((o.count("out") > 0)); - TBOOST_REQUIRE(!o["out"].is_null()); + TBOOST_REQUIRE((!o["out"].is_null())); if (_fillin) { @@ -84,6 +83,7 @@ namespace dev else { //Check Encode + TBOOST_REQUIRE((o.count("in") > 0)); int skipEncode = 0; if (o["in"].type() == js::str_type) { @@ -185,37 +185,34 @@ namespace dev std::stringstream bintStream(bigIntStr); bigint val; bintStream >> val; - TBOOST_CHECK( !u.isList() ); - TBOOST_CHECK( !u.isNull() ); - TBOOST_CHECK( u ); // operator bool() - TBOOST_CHECK(u == val); + TBOOST_CHECK(( !u.isList() )); + TBOOST_CHECK(( !u.isNull() )); + TBOOST_CHECK(( u == val )); } else { - TBOOST_CHECK( !u.isList() ); - TBOOST_CHECK( !u.isNull() ); - TBOOST_CHECK( u.isData() ); - TBOOST_CHECK( u ); - TBOOST_CHECK( u.size() == expectedText.length() ); - TBOOST_CHECK(u == expectedText); + TBOOST_CHECK(( !u.isList() )); + TBOOST_CHECK(( !u.isNull() )); + TBOOST_CHECK(( u.isData() )); + TBOOST_CHECK(( u.size() == expectedText.length() )); + TBOOST_CHECK(( u == expectedText )); } } else if ( v.type() == js::int_type ) { const int expectedValue = v.get_int(); - TBOOST_CHECK( u.isInt() ); - TBOOST_CHECK( !u.isList() ); - TBOOST_CHECK( !u.isNull() ); - TBOOST_CHECK( u ); // operator bool() - TBOOST_CHECK(u == expectedValue); + TBOOST_CHECK(( u.isInt() )); + TBOOST_CHECK(( !u.isList() )); + TBOOST_CHECK(( !u.isNull() )); + TBOOST_CHECK(( u == expectedValue )); } else if ( v.type() == js::array_type ) { - TBOOST_CHECK( u.isList() ); - TBOOST_CHECK( !u.isInt() ); - TBOOST_CHECK( !u.isData() ); + TBOOST_CHECK(( u.isList() )); + TBOOST_CHECK(( !u.isInt() )); + TBOOST_CHECK(( !u.isData() )); js::mArray& arr = v.get_array(); - TBOOST_CHECK( u.itemCount() == arr.size() ); + TBOOST_CHECK(( u.itemCount() == arr.size() )); unsigned i; for( i = 0; i < arr.size(); i++ ) { @@ -235,13 +232,12 @@ BOOST_AUTO_TEST_SUITE(RlpTests) BOOST_AUTO_TEST_CASE(invalidRLPtest) { - dev::test::executeTests("invalidRLPtest", "/BasicTests", dev::test::getFolder(__FILE__) + "/StateTestsFiller", dev::test::doRlpTests); + dev::test::executeTests("invalidRLPTest", "/RLPTests", dev::test::getFolder(__FILE__) + "/RLPTestsFiller", dev::test::doRlpTests); } - BOOST_AUTO_TEST_CASE(rlptest) { - dev::test::executeTests("rlptest", "/BasicTests", dev::test::getFolder(__FILE__) + "/StateTestsFiller", dev::test::doRlpTests); + dev::test::executeTests("rlptest", "/RLPTests", dev::test::getFolder(__FILE__) + "/RLPTestsFiller", dev::test::doRlpTests); } BOOST_AUTO_TEST_CASE(rlpRandom) @@ -249,7 +245,7 @@ BOOST_AUTO_TEST_CASE(rlpRandom) test::Options::get(); string testPath = dev::test::getTestPath(); - testPath += "/BasicTests/RandomRLPTests"; + testPath += "/RLPTests/RandomRLPTests"; vector testFiles; boost::filesystem::directory_iterator iterator(testPath); @@ -264,7 +260,7 @@ BOOST_AUTO_TEST_CASE(rlpRandom) cnote << "Testing ..." << path.filename(); json_spirit::mValue v; string s = asString(dev::contents(path.string())); - TBOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + path.string() + " is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); + TBOOST_REQUIRE_MESSAGE((s.length() > 0), "Content of " + path.string() + " is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); json_spirit::read_string(s, v); test::Listener::notifySuiteStarted(path.filename().string()); dev::test::doRlpTests(v, false); @@ -281,6 +277,4 @@ BOOST_AUTO_TEST_CASE(rlpRandom) } } - BOOST_AUTO_TEST_SUITE_END() - From 532df9cfe5ea04234a5c79ad9d84354169e7dde0 Mon Sep 17 00:00:00 2001 From: Dimitry Khokhlov Date: Tue, 7 Jul 2015 16:27:26 +0400 Subject: [PATCH 288/290] newtests: style --- test/libdevcore/rlp.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/libdevcore/rlp.cpp b/test/libdevcore/rlp.cpp index b17dcc249..b338d0e69 100644 --- a/test/libdevcore/rlp.cpp +++ b/test/libdevcore/rlp.cpp @@ -89,8 +89,7 @@ namespace dev { if (o["in"].get_str() == "INVALID") skipEncode = 1; - else - if (o["in"].get_str() == "VALID") + else if (o["in"].get_str() == "VALID") skipEncode = 2; } From b0ec75d0bb4fb32fc8df60b950032245bb8d64d7 Mon Sep 17 00:00:00 2001 From: Dimitry Date: Fri, 10 Jul 2015 14:27:59 +0300 Subject: [PATCH 289/290] RLP test refactoring: style --- test/libdevcore/rlp.cpp | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/test/libdevcore/rlp.cpp b/test/libdevcore/rlp.cpp index b338d0e69..74e422b05 100644 --- a/test/libdevcore/rlp.cpp +++ b/test/libdevcore/rlp.cpp @@ -43,6 +43,12 @@ namespace dev { void buildRLP(js::mValue& _v, RLPStream& _rlp); void checkRLPAgainstJson(js::mValue& v, RLP& u); + enum class RlpType + { + Valid, + Invalid, + Test + }; void doRlpTests(json_spirit::mValue& v, bool _fillin) { @@ -55,7 +61,7 @@ namespace dev continue; } - std::cout << " " << i.first << std::endl; + cout << " " << i.first << endl; TBOOST_REQUIRE((o.count("out") > 0)); TBOOST_REQUIRE((!o["out"].is_null())); @@ -84,25 +90,25 @@ namespace dev { //Check Encode TBOOST_REQUIRE((o.count("in") > 0)); - int skipEncode = 0; + RlpType rlpType = RlpType::Test; if (o["in"].type() == js::str_type) { if (o["in"].get_str() == "INVALID") - skipEncode = 1; + rlpType = RlpType::Invalid; else if (o["in"].get_str() == "VALID") - skipEncode = 2; + rlpType = RlpType::Valid; } - if (skipEncode == 0) + if (rlpType == RlpType::Test) { RLPStream s; dev::test::buildRLP(o["in"], s); string computedText = toHex(s.out()); - std::string expectedText(o["out"].get_str()); - std::transform(expectedText.begin(), expectedText.end(), expectedText.begin(), ::tolower ); + string expectedText(o["out"].get_str()); + transform(expectedText.begin(), expectedText.end(), expectedText.begin(), ::tolower ); - std::stringstream msg; + stringstream msg; msg << "Encoding Failed: expected: " << expectedText << std::endl; msg << " But Computed: " << computedText; TBOOST_CHECK_MESSAGE( @@ -123,7 +129,7 @@ namespace dev bytes payloadToDecode = fromHex(o["out"].get_str()); RLP payload(payloadToDecode); - if (skipEncode == 0) + if (rlpType == RlpType::Test) dev::test::checkRLPAgainstJson(inputData, payload); } catch (Exception const& _e) @@ -131,20 +137,21 @@ namespace dev cnote << "Exception: " << diagnostic_information(_e); was_exception = true; } - catch (std::exception const& _e) + catch (exception const& _e) { cnote << "rlp exception: " << _e.what(); was_exception = true; } //Expect exception as input is INVALID - if (skipEncode == 1 && was_exception) + if (rlpType == RlpType::Invalid && was_exception) continue; - //Expect exception as input is INVALID - if (skipEncode == 1 && !was_exception) + //Check that there was an exception as input is INVALID + if (rlpType == RlpType::Invalid && !was_exception) TBOOST_ERROR("Expected RLP Exception as rlp should be invalid!"); + //input is VALID check that there was no exceptions if (was_exception) TBOOST_ERROR("Unexpected RLP Exception!"); } @@ -176,12 +183,12 @@ namespace dev { if ( v.type() == js::str_type ) { - const std::string& expectedText = v.get_str(); + const string& expectedText = v.get_str(); if ( !expectedText.empty() && expectedText.front() == '#' ) { // Deal with bigint instead of a raw string - std::string bigIntStr = expectedText.substr(1,expectedText.length()-1); - std::stringstream bintStream(bigIntStr); + string bigIntStr = expectedText.substr(1,expectedText.length()-1); + stringstream bintStream(bigIntStr); bigint val; bintStream >> val; TBOOST_CHECK(( !u.isList() )); From 4211a845b7277a7c9f0ec561badd26aece56f5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Jul 2015 11:08:51 +0200 Subject: [PATCH 290/290] Include OpenCL headers only in ETHASHCL builds. --- ethminer/CMakeLists.txt | 4 +++- exp/CMakeLists.txt | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ethminer/CMakeLists.txt b/ethminer/CMakeLists.txt index 8b12530a5..90889ae12 100644 --- a/ethminer/CMakeLists.txt +++ b/ethminer/CMakeLists.txt @@ -9,7 +9,9 @@ if (JSONRPC) include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) endif() -include_directories(${OpenCL_INCLUDE_DIRS}) +if (ETHASHCL) + include_directories(${OpenCL_INCLUDE_DIRS}) +endif () set(EXECUTABLE ethminer) diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index 203022655..e6360317f 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -6,7 +6,9 @@ aux_source_directory(. SRC_LIST) include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) include_directories(BEFORE ..) include_directories(${DB_INCLUDE_DIRS}) -include_directories(${OpenCL_INCLUDE_DIRS}) +if (ETHASHCL) + include_directories(${OpenCL_INCLUDE_DIRS}) +endif () set(EXECUTABLE exp)