Browse Source

Merge branch 'develop' of https://github.com/ethereum/cpp-ethereum into bc-test-fix

cl-refactor
arkpar 10 years ago
parent
commit
5f09617d75
  1. 3
      alethzero/MainWin.cpp
  2. 8
      eth/main.cpp
  3. 18
      evmjit/CMakeLists.txt
  4. 9
      evmjit/README.md
  5. 66
      evmjit/include/evmjit/JIT-c.h
  6. 2
      evmjit/include/evmjit/JIT.h
  7. 2
      evmjit/libevmjit-cpp/CMakeLists.txt
  8. 2
      evmjit/libevmjit/BuildInfo.h.in
  9. 88
      evmjit/libevmjit/CMakeLists.txt
  10. 17
      evmjit/libevmjit/Cache.cpp
  11. 48
      evmjit/libevmjit/JIT-c.cpp
  12. 8
      evmjit/libevmjit/JIT.cpp
  13. 2
      evmjit/libevmjit/RuntimeManager.cpp
  14. 34
      evmjit/libevmjit/interface.cpp
  15. 13
      evmjit/libevmjit/interface.h
  16. 2
      libdevcore/Common.cpp
  17. 2
      libdevcore/Exceptions.h
  18. 2
      libdevcore/TrieDB.h
  19. 10
      libdevcrypto/Common.cpp
  20. 2
      libdevcrypto/CryptoPP.cpp
  21. 4
      libethcore/EthashSealEngine.cpp
  22. 2
      libethcore/Miner.h
  23. 2
      libethcore/Params.cpp
  24. 2
      libethcore/Sealer.h
  25. 7
      libethereum/BlockChain.cpp
  26. 9
      libethereum/BlockChain.h
  27. 42
      libethereum/CanonBlockChain.cpp
  28. 7
      libethereum/CanonBlockChain.h
  29. 25
      libethereum/Client.cpp
  30. 47
      libethereum/Client.h
  31. 34
      libethereum/GenesisInfo.cpp
  32. 1
      libethereum/State.h
  33. 2
      libwebthree/WebThree.cpp
  34. 2
      mix/QBigInt.h
  35. 2
      mix/QFunctionDefinition.h
  36. 1
      mix/qml/Block.qml
  37. 54
      mix/qml/BlockChain.qml
  38. 198
      mix/qml/DeployContractStep.qml
  39. 21
      mix/qml/DeploymentDialog.qml
  40. 170
      mix/qml/DeploymentDialogSteps.qml
  41. 6
      mix/qml/DeploymentWorker.qml
  42. 55
      mix/qml/KeyValuePanel.qml
  43. 2
      mix/qml/PackagingStep.qml
  44. 20
      mix/qml/ProjectModel.qml
  45. 74
      mix/qml/RegisteringStep.qml
  46. 4
      mix/qml/ScenarioLoader.qml
  47. 2
      mix/qml/StatusPane.qml
  48. 3
      mix/qml/WebPreview.qml
  49. 39
      mix/qml/js/NetworkDeployment.js
  50. 3
      mix/qml/js/TransactionHelper.js
  51. 46
      test/libsolidity/SolidityWallet.cpp

3
alethzero/MainWin.cpp

@ -189,6 +189,9 @@ Main::Main(QWidget *parent) :
#endif
m_servers.append(QString::fromStdString(Host::pocHost() + ":30303"));
if (!dev::contents(getDataDir() + "/genesis.json").empty())
CanonBlockChain<Ethash>::setGenesis(contentsString(getDataDir() + "/genesis.json"));
cerr << "State root: " << CanonBlockChain<Ethash>::genesis().stateRoot() << endl;
auto block = CanonBlockChain<Ethash>::createGenesisBlock();
cerr << "Block Hash: " << CanonBlockChain<Ethash>::genesis().hash() << endl;

8
eth/main.cpp

@ -1148,6 +1148,10 @@ int main(int argc, char** argv)
beneficiary = config[1].toHash<Address>();
}
// do this here so that --genesis-json can actually override it.
if (!contents(getDataDir() + "/genesis.json").empty())
CanonBlockChain<Ethash>::setGenesis(contentsString(getDataDir() + "/genesis.json"));
MinerCLI m(MinerCLI::OperationMode::None);
for (int i = 1; i < argc; ++i)
@ -1306,11 +1310,11 @@ int main(int argc, char** argv)
}
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 (arg == "--genesis-json" && i + 1 < argc)
{
try
{
CanonBlockChain<Ethash>::setGenesisNonce(Nonce(argv[++i]));
CanonBlockChain<Ethash>::setGenesis(contentsString(argv[++i]));
}
catch (...)
{

18
evmjit/CMakeLists.txt

@ -1,6 +1,15 @@
cmake_minimum_required(VERSION 2.8.12)
project(evmjit)
if (${CMAKE_VERSION} VERSION_GREATER 3.0)
cmake_policy(SET CMP0048 NEW) # allow VERSION argument in project()
project(EVMJIT VERSION 0.9.0 LANGUAGES CXX)
else()
project(EVMJIT)
set(EVMJIT_VERSION "0.9.0")
set(EVMJIT_VERSION_MAJOR 0)
set(EVMJIT_VERSION_MINOR 9)
set(EVMJIT_VERSION_PATCH 0)
endif()
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_AUTOMOC OFF)
@ -19,10 +28,10 @@ endif()
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND NOT LLVM_DIR)
# 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)
execute_process(COMMAND llvm-config-3.7 --includedir OUTPUT_VARIABLE LLVM_INCLUDE_DIRS OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "LLVM include dirs: ${LLVM_INCLUDE_DIRS}")
set(LLVM_LIBS "-lLLVMipo -lLLVMVectorize -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMX86Desc -lLLVMX86Info -lLLVMMCDisassembler -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMCodeGen -lLLVMScalarOpts -lLLVMProfileData -lLLVMInstCombine -lLLVMInstrumentation -lLLVMTransformUtils -lLLVMipa -lLLVMMCJIT -lLLVMExecutionEngine -lLLVMTarget -lLLVMAnalysis -lLLVMRuntimeDyld -lLLVMObject -lLLVMMCParser -lLLVMBitReader -lLLVMMC -lLLVMCore -lLLVMSupport -lz -lpthread -lffi -ltinfo -ldl -lm")
add_definitions(-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS)
set(LLVM_DEFINITIONS "-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS")
link_directories(/usr/lib/llvm-3.7/lib)
else()
find_package(LLVM REQUIRED CONFIG)
@ -31,12 +40,9 @@ else()
endif()
message(STATUS "Found LLVM ${LLVM_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)
endif()
get_filename_component(EVMJIT_INCLUDE_DIR include ABSOLUTE)
add_subdirectory(libevmjit)
if(EVMJIT_CPP)

9
evmjit/README.md

@ -33,11 +33,4 @@ Ask me.
## Options
Options to evmjit library can be passed by environmental variables, e.g. `EVMJIT_CACHE=0 testeth --jit`.
Option | Default value | Description
------------- | ------------- | ----------------------------------------------
EVMJIT_CACHE | 1 | Enables on disk cache for compiled EVM objects
EVMJIT_DUMP | 0 | Dumps generated LLVM module to standard output
Options to evmjit library can be passed by environmental variable, e.g. `EVMJIT="-help" testeth --jit`.

66
evmjit/include/evmjit/JIT-c.h

@ -0,0 +1,66 @@
#include "stdint.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct evmjit_i256
{
uint64_t words[4];
} evmjit_i256;
typedef struct evmjit_runtime_data
{
int64_t gas;
int64_t gasPrice;
char const* callData;
uint64_t callDataSize;
evmjit_i256 address;
evmjit_i256 caller;
evmjit_i256 origin;
evmjit_i256 callValue;
evmjit_i256 coinBase;
evmjit_i256 difficulty;
evmjit_i256 gasLimit;
uint64_t number;
int64_t timestamp;
char const* code;
uint64_t codeSize;
evmjit_i256 codeHash;
} evmjit_runtime_data;
typedef enum evmjit_return_code
{
// 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
LLVMError = -101,
UnexpectedException = -111
} evmjit_return_code;
typedef struct evmjit_context evmjit_context;
evmjit_context* evmjit_create(evmjit_runtime_data* _data, void* _env);
evmjit_return_code evmjit_exec(evmjit_context* _context);
void evmjit_destroy(evmjit_context* _context);
inline char const* evmjit_get_output(evmjit_runtime_data* _data) { return _data->callData; }
inline uint64_t evmjit_get_output_size(evmjit_runtime_data* _data) { return _data->callDataSize; }
#ifdef __cplusplus
}
#endif

2
evmjit/include/evmjit/JIT.h

@ -121,7 +121,7 @@ public:
ExecutionContext(RuntimeData& _data, Env* _env) { init(_data, _env); }
ExecutionContext(ExecutionContext const&) = delete;
ExecutionContext& operator=(ExecutionContext const&) = delete;
EXPORT ~ExecutionContext();
EXPORT ~ExecutionContext() noexcept;
void init(RuntimeData& _data, Env* _env) { m_data = &_data; m_env = _env; }

2
evmjit/libevmjit-cpp/CMakeLists.txt

@ -19,8 +19,6 @@ add_library(${TARGET_NAME} STATIC ${SOURCES})
set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "libs")
include_directories(../..)
include_directories(${EVMJIT_INCLUDE_DIR})
include_directories(${LLVM_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME} evmjit)

2
evmjit/libevmjit/BuildInfo.h.in

@ -3,8 +3,6 @@
#define EVMJIT_VERSION_MAJOR ${EVMJIT_VERSION_MAJOR}
#define EVMJIT_VERSION_MINOR ${EVMJIT_VERSION_MINOR}
#define EVMJIT_VERSION_PATCH ${EVMJIT_VERSION_PATCH}
#define EVMJIT_VERSION_PRERELEASE "${EVMJIT_VERSION_PRERELEASE}"
#define EVMJIT_VERSION_FULL "${EVMJIT_VERSION_FULL}"
#define LLVM_VERSION "${LLVM_PACKAGE_VERSION}"
#define LLVM_ASSERTIONS "${LLVM_ENABLE_ASSERTIONS}"

88
evmjit/libevmjit/CMakeLists.txt

@ -1,26 +1,28 @@
set(TARGET_NAME evmjit)
get_filename_component(EVMJIT_INCLUDE_DIR ../include ABSOLUTE)
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
Compiler.cpp Compiler.h
CompilerHelper.cpp CompilerHelper.h
Endianness.cpp Endianness.h
ExecStats.cpp ExecStats.h
Ext.cpp Ext.h
GasMeter.cpp GasMeter.h
Instruction.cpp Instruction.h
interface.cpp interface.h
Memory.cpp Memory.h
Optimizer.cpp Optimizer.h
RuntimeManager.cpp RuntimeManager.h
Stack.cpp Stack.h
Type.cpp Type.h
Utils.cpp Utils.h
JIT.cpp ${EVMJIT_INCLUDE_DIR}/evmjit/JIT.h
JIT-c.cpp ${EVMJIT_INCLUDE_DIR}/evmjit/JIT-c.h
Arith256.cpp Arith256.h
Array.cpp Array.h
BasicBlock.cpp BasicBlock.h
Cache.cpp Cache.h
Common.h
Compiler.cpp Compiler.h
CompilerHelper.cpp CompilerHelper.h
Endianness.cpp Endianness.h
ExecStats.cpp ExecStats.h
Ext.cpp Ext.h
GasMeter.cpp GasMeter.h
Instruction.cpp Instruction.h
Memory.cpp Memory.h
Optimizer.cpp Optimizer.h
RuntimeManager.cpp RuntimeManager.h
Stack.cpp Stack.h
Type.cpp Type.h
Utils.cpp Utils.h
)
source_group("" FILES ${SOURCES})
@ -29,40 +31,9 @@ else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
endif()
set(EVMJIT_VERSION "0.0.0")
set(EVMJIT_VERSION_MAJOR 0)
set(EVMJIT_VERSION_MINOR 0)
set(EVMJIT_VERSION_PATCH 0)
set(EVMJIT_VERSION_FULL "v0.0.0-nogit")
find_package(Git)
if(GIT_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} -C ${CMAKE_CURRENT_SOURCE_DIR} describe --dirty --always --match v*
OUTPUT_VARIABLE EVMJIT_VERSION_FULL OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
if(${EVMJIT_VERSION_FULL} MATCHES "^v[0-9]+\\.[0-9]+")
string(SUBSTRING ${EVMJIT_VERSION_FULL} 1 -1 EVMJIT_VERSION_FULL) # skip "v"
string(REPLACE "-" ";" VERSION_COMPONENTS ${EVMJIT_VERSION_FULL})
list(LENGTH VERSION_COMPONENTS NUM_VERSION_COMPONENTS)
list(GET VERSION_COMPONENTS 0 EVMJIT_VERSION)
string(REPLACE "." ";" VERSION_NUMBERS ${EVMJIT_VERSION})
list(LENGTH VERSION_NUMBERS NUM_VERSION_NUMBERS)
list(GET VERSION_NUMBERS 0 EVMJIT_VERSION_MAJOR)
list(GET VERSION_NUMBERS 1 EVMJIT_VERSION_MINOR)
if(${NUM_VERSION_NUMBERS} GREATER 2)
list(GET VERSION_NUMBERS 2 EVMJIT_VERSION_PATCH) # patch number is optional
endif()
if(${NUM_VERSION_COMPONENTS} GREATER 1)
list(GET VERSION_COMPONENTS 1 VERSION_PRERELEASE_CANDIDATE)
string(REGEX MATCH "^[a-zA-Z]+.*" EVMJIT_VERSION_PRERELEASE ${VERSION_PRERELEASE_CANDIDATE}) # prerelease starts with letter
endif()
endif()
if(${EVMJIT_VERSION_MAJOR} EQUAL 0)
set(EVMJIT_SOVERSION "0.${EVMJIT_VERSION_MINOR}")
else()
else()
set(EVMJIT_SOVERSION ${EVMJIT_VERSION_MAJOR})
endif()
@ -70,17 +41,18 @@ endif()
string(COMPARE EQUAL "${LLVM_ENABLE_ASSERTIONS}" "ON" LLVM_DEBUG)
configure_file(BuildInfo.h.in ${CMAKE_CURRENT_BINARY_DIR}/gen/BuildInfo.gen.h)
message(STATUS "EVM JIT version: ${EVMJIT_VERSION_MAJOR}.${EVMJIT_VERSION_MINOR}.${EVMJIT_VERSION_PATCH} ${EVMJIT_VERSION_PRERELEASE} (${EVMJIT_VERSION_FULL})")
message(STATUS "EVM JIT version: ${EVMJIT_VERSION_MAJOR}.${EVMJIT_VERSION_MINOR}.${EVMJIT_VERSION_PATCH}")
add_library(${TARGET_NAME} SHARED ${SOURCES} gen/BuildInfo.gen.h)
set_target_properties(${TARGET_NAME} PROPERTIES
set_target_properties(${TARGET_NAME} PROPERTIES
VERSION ${EVMJIT_VERSION} SOVERSION ${EVMJIT_SOVERSION}
FOLDER "libs")
include_directories(${EVMJIT_INCLUDE_DIR})
include_directories(${LLVM_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR}/gen)
target_include_directories(${TARGET_NAME} PUBLIC ${EVMJIT_INCLUDE_DIR})
target_include_directories(${TARGET_NAME} PRIVATE ${LLVM_INCLUDE_DIRS})
target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/gen)
target_compile_definitions(${TARGET_NAME} PRIVATE ${LLVM_DEFINITIONS})
target_link_libraries(${TARGET_NAME} PRIVATE ${LLVM_LIBS})
install(TARGETS ${TARGET_NAME} LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin)
install(DIRECTORY ${EVMJIT_INCLUDE_DIR} DESTINATION include)

17
evmjit/libevmjit/Cache.cpp

@ -28,17 +28,10 @@ namespace
CacheMode g_mode;
std::unique_ptr<llvm::MemoryBuffer> g_lastObject;
JITListener* g_listener;
static const size_t c_versionStampLength = 32;
llvm::StringRef getLibVersionStamp()
{
static auto version = llvm::SmallString<c_versionStampLength>{};
if (version.empty())
{
version = EVMJIT_VERSION_FULL;
version.resize(c_versionStampLength);
}
return version;
return EVMJIT_VERSION;
}
}
@ -130,11 +123,13 @@ std::unique_ptr<llvm::Module> Cache::getObject(std::string const& id)
if (auto r = llvm::MemoryBuffer::getFile(cachePath.str(), -1, false))
{
auto& buf = r.get();
auto objVersionStamp = buf->getBufferSize() >= c_versionStampLength ? llvm::StringRef{buf->getBufferEnd() - c_versionStampLength, c_versionStampLength} : llvm::StringRef{};
if (objVersionStamp == getLibVersionStamp())
auto expectedStamp = getLibVersionStamp();
auto stampSize = expectedStamp.size();
auto objStamp = buf->getBufferSize() >= stampSize ? llvm::StringRef{buf->getBufferEnd() - stampSize, stampSize} : llvm::StringRef{};
if (objStamp == expectedStamp)
g_lastObject = llvm::MemoryBuffer::getMemBufferCopy(r.get()->getBuffer());
else
DLOG(cache) << "Unmatched version: " << objVersionStamp.str() << ", expected " << getLibVersionStamp().str() << "\n";
DLOG(cache) << "Unmatched version: " << objStamp.str() << ", expected " << expectedStamp.str() << "\n";
}
else if (r.getError() != std::make_error_code(std::errc::no_such_file_or_directory))
DLOG(cache) << r.getError().message(); // TODO: Add warning log

48
evmjit/libevmjit/JIT-c.cpp

@ -0,0 +1,48 @@
#include <evmjit/JIT-c.h>
#include <cassert>
#include <evmjit/JIT.h>
extern "C"
{
using namespace dev::evmjit;
EXPORT evmjit_context* evmjit_create(evmjit_runtime_data* _data, void* _env)
{
auto data = reinterpret_cast<RuntimeData*>(_data);
auto env = reinterpret_cast<Env*>(_env);
assert(!data && "Pointer to runtime data must not be null");
if (!data)
return nullptr;
// TODO: Make sure ExecutionEngine constructor does not throw + make JIT/ExecutionEngine interface all nothrow
auto context = new(std::nothrow) ExecutionContext{*data, env};
return reinterpret_cast<evmjit_context*>(context);
}
EXPORT void evmjit_destroy(evmjit_context* _context)
{
auto context = reinterpret_cast<ExecutionContext*>(_context);
delete context;
}
EXPORT evmjit_return_code evmjit_exec(evmjit_context* _context)
{
auto context = reinterpret_cast<ExecutionContext*>(_context);
assert(!context && "Invalid context");
if (!context)
return UnexpectedException;
try
{
auto returnCode = JIT::exec(*context);
return static_cast<evmjit_return_code>(returnCode);
}
catch(...)
{
return UnexpectedException;
}
}
}

8
evmjit/libevmjit/JIT.cpp

@ -51,11 +51,11 @@ void printVersion()
std::cout << "Ethereum EVM JIT Compiler (http://github.com/ethereum/evmjit):\n"
<< " EVMJIT version " << EVMJIT_VERSION << "\n"
#ifdef NDEBUG
<< " Optimized build, " EVMJIT_VERSION_FULL "\n"
<< " Optimized build, "
#else
<< " DEBUG build, " EVMJIT_VERSION_FULL "\n"
<< " DEBUG build, "
#endif
<< " Built " << __DATE__ << " (" << __TIME__ << ")\n"
<< __DATE__ << " (" << __TIME__ << ")\n"
<< std::endl;
}
@ -227,7 +227,7 @@ ReturnCode JIT::exec(ExecutionContext& _context)
extern "C" void ext_free(void* _data) noexcept;
ExecutionContext::~ExecutionContext()
ExecutionContext::~ExecutionContext() noexcept
{
if (m_memData)
ext_free(m_memData); // Use helper free to check memory leaks

2
evmjit/libevmjit/RuntimeManager.cpp

@ -77,7 +77,7 @@ llvm::Twine getName(RuntimeData::Index _index)
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::Timestamp: return "block.timestamp";
case RuntimeData::Code: return "code.ptr";
case RuntimeData::CodeSize: return "code.size";
}

34
evmjit/libevmjit/interface.cpp

@ -1,34 +0,0 @@
#include "evmjit/JIT.h"
extern "C"
{
using namespace dev::evmjit;
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{*_data, _env};
}
EXPORT void evmjit_destroy(ExecutionContext* _context) noexcept
{
delete _context;
}
EXPORT int evmjit_run(ExecutionContext* _context) noexcept
{
try
{
auto returnCode = JIT::exec(*_context);
return static_cast<int>(returnCode);
}
catch(...)
{
return static_cast<int>(ReturnCode::UnexpectedException);
}
}
}

13
evmjit/libevmjit/interface.h

@ -1,13 +0,0 @@
#ifdef __cplusplus
extern "C" {
#endif
void* evmjit_create();
int evmjit_run(void* _jit, void* _data, void* _env);
void evmjit_destroy(void* _jit);
#ifdef __cplusplus
}
#endif

2
libdevcore/Common.cpp

@ -28,7 +28,7 @@ using namespace dev;
namespace dev
{
char const* Version = "0.9.30";
char const* Version = "0.9.32";
const u256 UndefinedU256 = ~(u256)0;

2
libdevcore/Exceptions.h

@ -56,7 +56,7 @@ DEV_SIMPLE_EXCEPTION(BadHexCharacter);
DEV_SIMPLE_EXCEPTION(NoNetworking);
DEV_SIMPLE_EXCEPTION(NoUPnPDevice);
DEV_SIMPLE_EXCEPTION(RootNotFound);
DEV_SIMPLE_EXCEPTION(BadRoot);
struct BadRoot: virtual Exception { public: BadRoot(h256 const& _root): Exception("BadRoot " + _root.hex()), root(_root) {} h256 root; };
DEV_SIMPLE_EXCEPTION(FileError);
DEV_SIMPLE_EXCEPTION(Overflow);
DEV_SIMPLE_EXCEPTION(FailedInvariant);

2
libdevcore/TrieDB.h

@ -96,7 +96,7 @@ 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).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.
h256 const& root() const { if (node(m_root).empty()) BOOST_THROW_EXCEPTION(BadRoot(m_root)); /*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;

10
libdevcrypto/Common.cpp

@ -193,17 +193,23 @@ bytes dev::decryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _ci
}
}
static const Public c_zeroKey = toPublic(Secret());
Public dev::recover(Signature const& _sig, h256 const& _message)
{
Public ret;
#ifdef ETH_HAVE_SECP256K1
bytes o(65);
int pubkeylen;
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);
ret = FixedHash<64>(o.data()+1, Public::ConstructFromPointer);
#else
return s_secp256k1pp.recover(_sig, _message.ref());
ret = s_secp256k1pp.recover(_sig, _message.ref());
#endif
if (ret == c_zeroKey)
return Public();
return ret;
}
Signature dev::sign(Secret const& _k, h256 const& _hash)

2
libdevcrypto/CryptoPP.cpp

@ -287,6 +287,8 @@ Public Secp256k1PP::recover(Signature _signature, bytesConstRef _message)
{
// todo: make generator member
p = m_curve.CascadeMultiply(u2, x, u1, m_params.GetSubgroupGenerator());
if (p.identity)
return Public();
m_curve.EncodePoint(recoveredbytes, p, false);
}
memcpy(recovered.data(), &recoveredbytes[1], 64);

4
libethcore/EthashSealEngine.cpp

@ -63,9 +63,11 @@ void EthashSealEngine::onSealGenerated(std::function<void(bytes const&)> const&
{
m_farm.onSolutionFound([=](EthashProofOfWork::Solution const& sol)
{
cdebug << m_farm.work().seedHash << m_farm.work().headerHash << sol.nonce << EthashAux::eval(m_farm.work().seedHash, m_farm.work().headerHash, sol.nonce).value;
// cdebug << m_farm.work().seedHash << m_farm.work().headerHash << sol.nonce << EthashAux::eval(m_farm.work().seedHash, m_farm.work().headerHash, sol.nonce).value;
m_sealing.m_mixHash = sol.mixHash;
m_sealing.m_nonce = sol.nonce;
if (!m_sealing.preVerify())
return false;
RLPStream ret;
m_sealing.streamRLP(ret);
_f(ret.out());

2
libethcore/Miner.h

@ -58,6 +58,8 @@ public:
using Solution = typename PoW::Solution;
using Miner = GenericMiner<PoW>;
virtual ~GenericFarmFace() {}
/**
* @brief Called from a Miner to note a WorkPackage has a solution.
* @param _p The solution.

2
libethcore/Params.cpp

@ -30,7 +30,7 @@ namespace eth
//--- BEGIN: AUTOGENERATED FROM github.com/ethereum/common/params.json
u256 const c_genesisDifficulty = 131072;
u256 const c_maximumExtraDataSize = 1024;
u256 const c_maximumExtraDataSize = 32;
u256 const c_genesisGasLimit = c_network == Network::Turbo ? 100000000 : 3141592;
u256 const c_minGasLimit = c_network == Network::Turbo ? 100000000 : 125000;
u256 const c_gasLimitBoundDivisor = 1024;

2
libethcore/Sealer.h

@ -38,6 +38,8 @@ class BlockInfo;
class SealEngineFace
{
public:
virtual ~SealEngineFace() {}
virtual std::string name() const = 0;
virtual unsigned revision() const = 0;
virtual unsigned sealFields() const = 0;

7
libethereum/BlockChain.cpp

@ -586,9 +586,11 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const&
#endif
}
#if ETH_CATCH
catch (BadRoot&)
catch (BadRoot& ex)
{
cwarn << "BadRoot error. Retrying import later.";
cwarn << "*** BadRoot error! Trying to import" << _block.info.hash() << "needed root" << ex.root;
cwarn << _block.info;
// Attempt in import later.
BOOST_THROW_EXCEPTION(FutureTime());
}
catch (Exception& ex)
@ -1245,6 +1247,7 @@ State BlockChain::genesisState(OverlayDB const& _db)
dev::eth::commit(m_genesisState, ret.m_state); // bit horrible. maybe consider a better way of constructing it?
ret.m_state.db()->commit(); // have to use this db() since it's the one that has been altered with the above commit.
ret.m_previousBlock = BlockInfo(&m_genesisBlock);
ret.resetCurrent();
return ret;
}

9
libethereum/BlockChain.h

@ -393,10 +393,10 @@ public:
virtual VerifiedBlockRef verifyBlock(bytesConstRef _block, std::function<void(Exception&)> const& _onBad, ImportRequirements::value _ir) const override
{
VerifiedBlockRef res;
BlockHeader h;
try
{
BlockHeader h(_block, (_ir & ImportRequirements::ValidSeal) ? Strictness::CheckEverything : Strictness::QuickNonce);
h = BlockHeader(_block, (_ir & ImportRequirements::ValidSeal) ? Strictness::CheckEverything : Strictness::QuickNonce);
h.verifyInternals(_block);
if ((_ir & ImportRequirements::Parent) != 0)
{
@ -412,6 +412,7 @@ public:
ex << errinfo_phase(1);
ex << errinfo_now(time(0));
ex << errinfo_block(_block.toBytes());
ex << errinfo_extraData(h.extraData());
if (_onBad)
_onBad(ex);
throw;
@ -422,9 +423,10 @@ public:
if (_ir && ImportRequirements::UncleBasic)
for (auto const& uncle: r[2])
{
BlockHeader h;
try
{
BlockHeader().populateFromHeader(RLP(uncle.data()), (_ir & ImportRequirements::UncleSeals) ? Strictness::CheckEverything : Strictness::IgnoreSeal);
h.populateFromHeader(RLP(uncle.data()), (_ir & ImportRequirements::UncleSeals) ? Strictness::CheckEverything : Strictness::IgnoreSeal);
}
catch (Exception& ex)
{
@ -432,6 +434,7 @@ public:
ex << errinfo_uncleIndex(i);
ex << errinfo_now(time(0));
ex << errinfo_block(_block.toBytes());
ex << errinfo_extraData(h.extraData());
if (_onBad)
_onBad(ex);
throw;

42
libethereum/CanonBlockChain.cpp

@ -38,8 +38,6 @@ using namespace dev;
using namespace dev::eth;
namespace js = json_spirit;
#define ETH_CATCH 1
std::unique_ptr<Ethash::BlockHeader> CanonBlockChain<Ethash>::s_genesis;
boost::shared_mutex CanonBlockChain<Ethash>::x_genesis;
Nonce CanonBlockChain<Ethash>::s_nonce(u64(42));
@ -63,8 +61,35 @@ bytes CanonBlockChain<Ethash>::createGenesisBlock()
stateRoot = state.root();
}
js::mValue val;
json_spirit::read_string(s_genesisStateJSON.empty() ? c_genesisInfo : s_genesisStateJSON, val);
js::mObject genesis = val.get_obj();
h256 mixHash(genesis["mixhash"].get_str());
h256 parentHash(genesis["parentHash"].get_str());
h160 beneficiary(genesis["coinbase"].get_str());
u256 difficulty = fromBigEndian<u256>(fromHex(genesis["difficulty"].get_str()));
u256 gasLimit = fromBigEndian<u256>(fromHex(genesis["gasLimit"].get_str()));
u256 timestamp = fromBigEndian<u256>(fromHex(genesis["timestamp"].get_str()));
bytes extraData = fromHex(genesis["extraData"].get_str());
h64 nonce(genesis["nonce"].get_str());
block.appendList(15)
<< h256() << EmptyListSHA3 << h160() << stateRoot << EmptyTrie << EmptyTrie << LogBloom() << c_genesisDifficulty << 0 << c_genesisGasLimit << 0 << (unsigned)0 << string() << h256() << s_nonce;
<< parentHash
<< EmptyListSHA3 // sha3(uncles)
<< beneficiary
<< stateRoot
<< EmptyTrie // transactions
<< EmptyTrie // receipts
<< LogBloom()
<< difficulty
<< 0 // number
<< gasLimit
<< 0 // gasUsed
<< timestamp
<< extraData
<< mixHash
<< nonce;
block.appendRaw(RLPEmptyList);
block.appendRaw(RLPEmptyList);
return block.out();
@ -78,7 +103,7 @@ unordered_map<Address, Account> CanonBlockChain<Ethash>::createGenesisState()
{
js::mValue val;
json_spirit::read_string(s_genesisStateJSON.empty() ? c_genesisInfo : s_genesisStateJSON, val);
for (auto account: val.get_obj())
for (auto account: val.get_obj()["alloc"].get_obj())
{
u256 balance;
if (account.second.get_obj().count("wei"))
@ -97,20 +122,13 @@ unordered_map<Address, Account> CanonBlockChain<Ethash>::createGenesisState()
return s_ret;
}
void CanonBlockChain<Ethash>::setGenesisState(std::string const& _json)
void CanonBlockChain<Ethash>::setGenesis(std::string const& _json)
{
WriteGuard l(x_genesis);
s_genesisStateJSON = _json;
s_genesis.reset();
}
void CanonBlockChain<Ethash>::setGenesisNonce(Nonce const& _n)
{
WriteGuard l(x_genesis);
s_nonce = _n;
s_genesis.reset();
}
Ethash::BlockHeader const& CanonBlockChain<Ethash>::genesis()
{
UpgradableGuard l(x_genesis);

7
libethereum/CanonBlockChain.h

@ -89,16 +89,11 @@ public:
/// @note This is slow as it's constructed anew each call. Consider genesis() instead.
static std::unordered_map<Address, Account> createGenesisState();
/// Alter the value of the genesis block's nonce.
/// @warning Unless you're very careful, make sure you call this right at the start of the
/// program, before anything has had the chance to use this class at all.
static void setGenesisNonce(Nonce const& _n);
/// Alter all the genesis block's state by giving a JSON string with account details.
/// @TODO implement.
/// @warning Unless you're very careful, make sure you call this right at the start of the
/// program, before anything has had the chance to use this class at all.
static void setGenesisState(std::string const&);
static void setGenesis(std::string const& _genesisInfoJSON);
// TODO: setGenesisTimestamp, ...ExtraData, ...Difficulty, ...GasLimit,

25
libethereum/Client.cpp

@ -217,6 +217,17 @@ void Client::onBadBlock(Exception& _ex) const
report["hints"]["ethashResult"]["value"] = get<0>(*r).hex();
report["hints"]["ethashResult"]["mixHash"] = get<1>(*r).hex();
}
if (bytes const* ed = boost::get_error_info<errinfo_extraData>(_ex))
{
RLP r(*ed);
report["hints"]["extraData"] = toHex(*ed);
try
{
if (r[0].toInt<int>() == 0)
report["hints"]["minerVersion"] = r[1].toString();
}
catch (...) {}
}
DEV_HINT_ERRINFO(required);
DEV_HINT_ERRINFO(got);
DEV_HINT_ERRINFO_HASH(required_LogBloom);
@ -341,7 +352,7 @@ void Client::killChain()
bc().reopen(Defaults::dbPath(), WithExisting::Kill);
m_preMine = bc().genesisState(m_stateDB);
m_postMine = State(m_stateDB);
m_postMine = m_preMine;
}
if (auto h = m_host.lock())
@ -450,6 +461,14 @@ void Client::setShouldPrecomputeDAG(bool _precompute)
sealEngine()->setOption("precomputeDAG", _precompute ? trueBytes: falseBytes);
}
void Client::setTurboMining(bool _enable)
{
m_turboMining = _enable;
sealEngine()->setSealer("opencl");
if (isMining())
startMining();
}
bool Client::isMining() const
{
return Ethash::isWorking(m_sealEngine.get());
@ -586,7 +605,7 @@ void Client::onNewBlocks(h256s const& _blocks, h256Hash& io_changed)
appendFromBlock(h, BlockPolarity::Live, io_changed);
}
void Client::restartMining()
void Client::resyncStateFromChain()
{
// RESTART MINING
@ -639,7 +658,7 @@ void Client::onChainChanged(ImportRoute const& _ir)
m_tq.dropGood(t);
}
onNewBlocks(_ir.liveBlocks, changeds);
restartMining();
resyncStateFromChain();
noteChanged(changeds);
}

47
libethereum/Client.h

@ -79,10 +79,6 @@ std::ostream& operator<<(std::ostream& _out, ActivityReport const& _r);
class Client: public ClientBase, protected Worker
{
public:
/// New-style Constructor.
/// Any final derived class's constructor should make sure they call init().
explicit Client(std::shared_ptr<GasPricer> _gpForAdoption);
/// Destructor.
virtual ~Client();
@ -139,7 +135,7 @@ public:
/// Are we allowed to GPU mine?
bool turboMining() const { return m_turboMining; }
/// Enable/disable GPU mining.
void setTurboMining(bool _enable = true) { m_turboMining = _enable; if (isMining()) startMining(); }
void setTurboMining(bool _enable = true);
/// Enable/disable precomputing of the DAG for next epoch
void setShouldPrecomputeDAG(bool _precompute);
@ -199,6 +195,10 @@ public:
SealEngineFace* sealEngine() const { return m_sealEngine.get(); }
protected:
/// New-style Constructor.
/// Any final derived class's constructor should make sure they call init().
explicit Client(std::shared_ptr<GasPricer> _gpForAdoption);
/// Perform critical setup functions.
/// Must be called in the constructor of the finally derived class.
void init(p2p::Host* _extNet, std::string const& _dbPath, WithExisting _forceAction, u256 _networkId);
@ -250,7 +250,7 @@ protected:
void onNewBlocks(h256s const& _blocks, h256Hash& io_changed);
/// Called after processing blocks by onChainChanged(_ir)
void restartMining();
void resyncStateFromChain();
/// Magically called when the chain has changed. An import route is provided.
/// Called by either submitWork() or in our main thread through syncBlockQueue().
@ -342,13 +342,8 @@ public:
WithExisting _forceAction = WithExisting::Trust,
u256 _networkId = 0
):
Client(_gpForAdoption),
m_bc(_dbPath, _forceAction, [](unsigned d, unsigned t){ std::cerr << "REVISING BLOCKCHAIN: Processed " << d << " of " << t << "...\r"; })
SpecialisedClient(_gpForAdoption, _dbPath, _forceAction)
{
m_sealEngine = std::shared_ptr<SealEngineFace>(Ethash::createSealEngine());
m_sealEngine->onSealGenerated([=](bytes const& header){
this->submitSealed(header);
});
init(_host, _dbPath, _forceAction, _networkId);
}
@ -358,10 +353,24 @@ public:
CanonBlockChain<Sealer> const& blockChain() const { return m_bc; }
protected:
explicit SpecialisedClient(
std::shared_ptr<GasPricer> _gpForAdoption,
std::string const& _dbPath = std::string(),
WithExisting _forceAction = WithExisting::Trust
):
Client(_gpForAdoption),
m_bc(_dbPath, _forceAction, [](unsigned d, unsigned t){ std::cerr << "REVISING BLOCKCHAIN: Processed " << d << " of " << t << "...\r"; })
{
m_sealEngine = std::shared_ptr<SealEngineFace>(Ethash::createSealEngine());
m_sealEngine->onSealGenerated([=](bytes const& header){
this->submitSealed(header);
});
}
virtual BlockChain& bc() override { return m_bc; }
virtual BlockChain const& bc() const override { return m_bc; }
protected:
private:
CanonBlockChain<Sealer> m_bc; ///< Maintains block database.
};
@ -375,9 +384,11 @@ public:
std::string const& _dbPath = std::string(),
WithExisting _forceAction = WithExisting::Trust,
u256 _networkId = 0
): SpecialisedClient<Ethash>(_host, _gpForAdoption, _dbPath, _forceAction, _networkId) {}
virtual ~EthashClient() { stopWorking(); }
):
SpecialisedClient<Ethash>(_gpForAdoption, _dbPath, _forceAction)
{
init(_host, _dbPath, _forceAction, _networkId);
}
/// Update to the latest transactions and get hash of the current block to be mined minus the
/// nonce (the 'work hash') and the difficulty to be met.
@ -389,10 +400,6 @@ public:
* @return true if the solution was indeed valid and accepted.
*/
virtual bool submitEthashWork(h256 const& _mixHash, h64 const& _nonce) override;
protected:
virtual BlockChain& bc() override { return m_bc; }
virtual BlockChain const& bc() const override { return m_bc; }
};
}

34
libethereum/GenesisInfo.cpp

@ -24,17 +24,27 @@
std::string const dev::eth::c_genesisInfo =
R"ETHEREUM(
{
"0000000000000000000000000000000000000001": { "wei": "1" },
"0000000000000000000000000000000000000002": { "wei": "1" },
"0000000000000000000000000000000000000003": { "wei": "1" },
"0000000000000000000000000000000000000004": { "wei": "1" },
"dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6": { "wei": "1606938044258990275541962092341162602522202993782792835301376" },
"e6716f9544a56c530d868e4bfbacb172315bdead": { "wei": "1606938044258990275541962092341162602522202993782792835301376" },
"b9c015918bdaba24b4ff057a92a3873d6eb201be": { "wei": "1606938044258990275541962092341162602522202993782792835301376" },
"1a26338f0d905e295fccb71fa9ea849ffa12aaf4": { "wei": "1606938044258990275541962092341162602522202993782792835301376" },
"2ef47100e0787b915105fd5e3f4ff6752079d5cb": { "wei": "1606938044258990275541962092341162602522202993782792835301376" },
"cd2a3d9f938e13cd947ec05abc7fe734df8dd826": { "wei": "1606938044258990275541962092341162602522202993782792835301376" },
"6c386a4b26f73c802f34673f7248bb118f97424a": { "wei": "1606938044258990275541962092341162602522202993782792835301376" },
"e4157b34ea9615cfbde6b4fda419828124b70c78": { "wei": "1606938044258990275541962092341162602522202993782792835301376" },
"nonce": "0x000000000000002a",
"difficulty": "0x20000",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x2FEFD8",
"alloc": {
"0000000000000000000000000000000000000001": { "wei": "1" },
"0000000000000000000000000000000000000002": { "wei": "1" },
"0000000000000000000000000000000000000003": { "wei": "1" },
"0000000000000000000000000000000000000004": { "wei": "1" },
"dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6": { "wei": "1606938044258990275541962092341162602522202993782792835301376" },
"e6716f9544a56c530d868e4bfbacb172315bdead": { "wei": "1606938044258990275541962092341162602522202993782792835301376" },
"b9c015918bdaba24b4ff057a92a3873d6eb201be": { "wei": "1606938044258990275541962092341162602522202993782792835301376" },
"1a26338f0d905e295fccb71fa9ea849ffa12aaf4": { "wei": "1606938044258990275541962092341162602522202993782792835301376" },
"2ef47100e0787b915105fd5e3f4ff6752079d5cb": { "wei": "1606938044258990275541962092341162602522202993782792835301376" },
"cd2a3d9f938e13cd947ec05abc7fe734df8dd826": { "wei": "1606938044258990275541962092341162602522202993782792835301376" },
"6c386a4b26f73c802f34673f7248bb118f97424a": { "wei": "1606938044258990275541962092341162602522202993782792835301376" },
"e4157b34ea9615cfbde6b4fda419828124b70c78": { "wei": "1606938044258990275541962092341162602522202993782792835301376" }
}
}
)ETHEREUM";

1
libethereum/State.h

@ -52,6 +52,7 @@ using errinfo_uncleNumber = boost::error_info<struct tag_uncleNumber, u256>;
using errinfo_unclesExcluded = boost::error_info<struct tag_unclesExcluded, h256Hash>;
using errinfo_block = boost::error_info<struct tag_block, bytes>;
using errinfo_now = boost::error_info<struct tag_now, unsigned>;
using errinfo_extraData = boost::error_info<struct tag_extraData, bytes>;
using errinfo_transactionIndex = boost::error_info<struct tag_transactionIndex, unsigned>;

2
libwebthree/WebThree.cpp

@ -53,7 +53,7 @@ WebThreeDirect::WebThreeDirect(
if (_interfaces.count("eth"))
{
m_ethereum.reset(new eth::EthashClient(&m_net, shared_ptr<GasPricer>(), _dbPath, _we, 0));
m_ethereum->setExtraData(rlpList(0, _clientVersion, m_net.id()));
m_ethereum->setExtraData(rlpList(0, _clientVersion));
}
if (_interfaces.count("shh"))

2
mix/QBigInt.h

@ -82,6 +82,8 @@ public:
BigIntVariant internalValue() const { return m_internalValue; }
/// @returns a string representation of the big integer used. Invokable from QML.
Q_INVOKABLE QString value() const;
/// hex value.
Q_INVOKABLE QString hexValue() const { return QString::fromStdString(dev::toHex(dev::u256(value().toStdString()))); }
/// Set the value of the BigInteger used. Will use u256 type. Invokable from QML.
Q_INVOKABLE void setValue(QString const& _value) { m_internalValue = dev::jsToU256(_value.toStdString()); }
Q_INVOKABLE void setBigInt(QString const& _value) { m_internalValue = bigint(_value.toStdString()); }

2
mix/QFunctionDefinition.h

@ -55,6 +55,8 @@ public:
FixedHash<4> hash() const { return m_hash; }
/// Get the full hash of this function declaration on the contract ABI.
FixedHash<32> fullHash() const { return m_fullHash; }
/// Get the hash of this function declaration on the contract ABI. returns QString
Q_INVOKABLE QString qhash() const { return QString::fromStdString(m_hash.hex()); }
private:
int m_index;

1
mix/qml/Block.qml

@ -105,6 +105,7 @@ ColumnLayout
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 14
visible: false
MouseArea
{
anchors.fill: parent

54
mix/qml/BlockChain.qml

@ -117,47 +117,7 @@ ColumnLayout {
RowLayout
{
id: header
spacing: 0
Layout.preferredHeight: 24
Rectangle
{
Layout.preferredWidth: statusWidth
Layout.preferredHeight: parent.height
color: "transparent"
Image {
id: debugImage
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
source: "qrc:/qml/img/recycleicon@2x.png"
width: statusWidth + 10
fillMode: Image.PreserveAspectFit
}
}
Rectangle
{
anchors.verticalCenter: parent.verticalCenter
Layout.preferredWidth: fromWidth
Label
{
anchors.verticalCenter: parent.verticalCenter
text: "From"
anchors.left: parent.left
anchors.leftMargin: horizontalMargin
}
}
Label
{
text: "To"
anchors.verticalCenter: parent.verticalCenter
Layout.preferredWidth: toWidth + cellSpacing
}
Label
{
text: ""
anchors.verticalCenter: parent.verticalCenter
Layout.preferredWidth: debugActionWidth
}
Layout.preferredHeight: 10
}
Rectangle
@ -178,18 +138,6 @@ ColumnLayout {
width: parent.width
spacing: 20
Block
{
scenario: blockChainPanel.model
Layout.preferredWidth: blockChainScrollView.width
Layout.preferredHeight: 60
blockIndex: -1
transactions: []
status: ""
number: -2
trHeight: 60
}
Repeater // List of blocks
{
id: blockChainRepeater

198
mix/qml/DeployContractStep.qml

@ -12,12 +12,15 @@ Rectangle {
property variant paramsModel: []
property variant worker
property variant gas: []
property alias gasPrice: gasPriceInput
color: "#E3E3E3E3"
signal deployed
anchors.fill: parent
id: root
property int labelWidth: 150
function show()
{
visible = true
@ -25,12 +28,13 @@ Rectangle {
contractList.change()
accountsModel.clear()
for (var k in worker.accounts)
{
accountsModel.append(worker.accounts[k])
}
if (worker.accounts.length > 0)
if (worker.currentAccount === "" && worker.accounts.length > 0)
{
worker.currentAccount = worker.accounts[0].id
accountsList.currentIndex = 0
}
if (projectModel.deployBlockNumber !== -1)
{
@ -45,13 +49,28 @@ Rectangle {
function updateVerification(blockNumber, trLost)
{
verificationLabel.text = blockNumber - projectModel.deployBlockNumber
if (trLost.length > 0)
var nb = parseInt(blockNumber - projectModel.deployBlockNumber)
verificationTextArea.visible = false
verificationLabel.visible = true
if (nb >= 10)
{
verificationLabel.text += "\n" + qsTr("Transactions lost") + "\n"
for (var k in trLost)
verificationLabel.text = qsTr("contracts deployment verified")
verificationLabel.color = "green"
}
else
{
verificationLabel.text = nb
if (trLost.length > 0)
{
verificationLabel.text += trLost[k] + "\n"
verificationTextArea.visible = true
verificationLabel.visible = false
deploymentStepChanged("following transactions are invalidated:")
verificationTextArea.text += "\n" + qsTr("Transactions lost") + "\n"
for (var k in trLost)
{
deploymentStepChanged(trLost[k])
verificationTextArea.text += trLost[k] + "\n"
}
}
}
}
@ -250,7 +269,6 @@ Rectangle {
{
worker.currentAccount = currentText
accountBalance.text = worker.balance(currentText).format()
console.log(worker.balance(currentText).format())
}
}
@ -280,6 +298,11 @@ Rectangle {
displayUnitSelection: true
displayFormattedValue: true
edit: true
function toHexWei()
{
return "0x" + gasPriceInput.value.toWei().hexValue()
}
}
Connections
@ -329,9 +352,7 @@ Rectangle {
root.gas = gas
cost = 0
for (var k in gas)
{
cost += gas[k]
}
setCost()
}
});
@ -349,7 +370,7 @@ Rectangle {
width: labelWidth
Label
{
text: qsTr("Cost Estimate")
text: qsTr("Deployment Cost")
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
}
@ -365,92 +386,87 @@ Rectangle {
}
}
RowLayout
Rectangle
{
id: deployedRow
border.color: "#cccccc"
border.width: 2
Layout.fillWidth: true
Rectangle
Layout.preferredHeight: parent.height + 25
color: "transparent"
id: rectDeploymentVariable
ScrollView
{
width: labelWidth
Label
anchors.fill: parent
anchors.topMargin: 4
anchors.bottomMargin: 4
ColumnLayout
{
id: labelAddresses
text: qsTr("Deployed Contracts")
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
}
}
ColumnLayout
{
anchors.top: parent.top
anchors.topMargin: 1
ListModel
{
id: deployedAddrModel
}
Repeater
{
id: deployedAddresses
model: deployedAddrModel
function refresh()
RowLayout
{
deployedAddrModel.clear()
deployedRow.visible = Object.keys(projectModel.deploymentAddresses).length > 0
for (var k in projectModel.deploymentAddresses)
id: deployedRow
Layout.fillWidth: true
Rectangle
{
if (k.indexOf("-") !== -1) // this is an contract instance. ctr without - are the last deployed (to support old project)
deployedAddrModel.append({ id: k, value: projectModel.deploymentAddresses[k]})
width: labelWidth
Label
{
id: labelAddresses
text: qsTr("Deployed Contracts")
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
}
}
ColumnLayout
{
anchors.top: parent.top
anchors.topMargin: 1
width: parent.width
id: deployedAddresses
function refresh()
{
textAddresses.text = ""
deployedRow.visible = Object.keys(projectModel.deploymentAddresses).length > 0
textAddresses.text = JSON.stringify(projectModel.deploymentAddresses, null, ' ')
}
TextArea
{
anchors.fill: parent
id: textAddresses
}
}
}
Rectangle
RowLayout
{
Layout.preferredHeight: 20
Layout.preferredWidth: 235
color: "transparent"
Label
id: verificationRow
Layout.fillWidth: true
visible: Object.keys(projectModel.deploymentAddresses).length > 0
Rectangle
{
id: labelContract
width: 112
elide: Text.ElideRight
text: index > -1 ? deployedAddrModel.get(index).id : ""
width: labelWidth
Label
{
text: qsTr("Verifications")
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
}
}
TextField
TextArea
{
width: 123
anchors.verticalCenter: parent.verticalCenter
anchors.left: labelContract.right
text: index > - 1 ? deployedAddrModel.get(index).value : ""
id: verificationTextArea
visible: false
}
}
}
}
}
RowLayout
{
id: verificationRow
Layout.fillWidth: true
visible: Object.keys(projectModel.deploymentAddresses).length > 0
Rectangle
{
width: labelWidth
Label
{
text: qsTr("Verifications")
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
Label
{
id: verificationLabel
visible: true
}
}
}
}
Label
{
id: verificationLabel
maximumLineCount: 20
}
}
}
@ -460,12 +476,31 @@ Rectangle {
Layout.alignment: Qt.BottomEdge
Button
{
Layout.preferredHeight: 22
anchors.right: deployBtn.left
text: qsTr("Reset")
action: clearDeployAction
}
Action {
id: clearDeployAction
onTriggered: {
worker.forceStopPooling()
fileIo.deleteDir(projectModel.deploymentDir)
projectModel.cleanDeploymentStatus()
deploymentDialog.steps.reset()
}
}
Button
{
id: deployBtn
anchors.right: parent.right
text: qsTr("Deploy Contracts")
onClicked:
{
projectModel.deployedScenarioIndex = contractList.currentIndex
NetworkDeploymentCode.deployContracts(root.gas, function(addresses, trHashes)
NetworkDeploymentCode.deployContracts(root.gas, gasPriceInput.toHexWei(), function(addresses, trHashes)
{
projectModel.deploymentTrHashes = trHashes
worker.verifyHashes(trHashes, function (nb, trLost)
@ -473,6 +508,7 @@ Rectangle {
projectModel.deployBlockNumber = nb
projectModel.saveProject()
root.updateVerification(nb, trLost)
root.deployed()
})
projectModel.deploymentAddresses = addresses
projectModel.saveProject()

21
mix/qml/DeploymentDialog.qml

@ -22,6 +22,7 @@ Dialog {
property alias packageStep: packageStep
property alias registerStep: registerStep
property alias worker: worker
property alias steps: steps
function close()
{
@ -52,15 +53,31 @@ Dialog {
anchors.fill: parent
anchors.margins: 10
RowLayout
Rectangle
{
id: explanation
Layout.preferredWidth: parent.width - 50
Layout.preferredHeight: 50
color: "transparent"
Label
{
id: info
anchors.centerIn: parent
text: qsTr("Putting your dapp live is a multi step process. You can read more about it on the 'guide to uploading'.")
text: qsTr("Putting your dapp live is a multi step process. You can read more about it on the")
}
Text {
anchors.left: info.right
anchors.leftMargin: 7
id: linkText
text: '<html><style type="text/css"></style><a href="https://github.com/ethereum/wiki/wiki/Mix:-The-DApp-IDE#deployment-to-network">guide to uploading</a></html>'
onLinkActivated: Qt.openUrlExternally("https://github.com/ethereum/wiki/wiki/Mix:-The-DApp-IDE#deployment-to-network")
anchors.verticalCenter: parent.verticalCenter
MouseArea
{
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
}
}
}

170
mix/qml/DeploymentDialogSteps.qml

@ -26,13 +26,55 @@ Rectangle {
selected(step)
}
function reset()
{
for (var k in deployLogs.logs)
{
deployLogs.logs[k] = ""
}
deployLogs.switchLogs()
refreshCurrent()
}
border.color: "#cccccc"
border.width: 1
Connections
{
id: deployStatus
target: deploymentDialog.deployStep
onDeployed:
{
console.log("deployed")
}
}
Connections
{
id: packagedStatus
target: deploymentDialog.packageStep
onPackaged:
{
console.log("packaged")
}
}
Connections
{
id: registerStatus
target: deploymentDialog.registerStep
onRegistered:
{
console.log("registered")
}
}
ColumnLayout
{
anchors.fill: parent
anchors.margins: 1
spacing: 0
Repeater
{
id: menu
@ -45,7 +87,7 @@ Rectangle {
{
step: 2,
type:"package",
label: qsTr("Package files")
label: qsTr("Package Dapp")
},
{
step: 3,
@ -70,6 +112,7 @@ Rectangle {
labelContainer.state = "selected"
sel = index
itemClicked(menu.model[index].type)
deployLogs.switchLogs()
}
function unselect()
@ -136,62 +179,60 @@ Rectangle {
}
Connections {
target: projectModel
onDeploymentStarted: log.text = log.text + qsTr("Running deployment...") + "\n"
onDeploymentError: log.text = log.text + error + "\n"
onDeploymentComplete: log.text = log.text + qsTr("Deployment complete") + "\n"
onDeploymentStepChanged: log.text = log.text + message + "\n"
}
property var logs: ({})
id: deployLogs
Rectangle
{
Layout.fillWidth: true
Layout.preferredHeight: 1
color: "#cccccc"
}
function switchLogs()
{
if (root.sel)
{
if (!logs[root.sel])
logs[root.sel] = ""
log.text = logs[root.sel]
}
}
RowLayout
{
anchors.horizontalCenter: parent.horizontalCenter
Layout.preferredHeight: 20
anchors.left: parent.left
anchors.leftMargin: 2
Button
target: projectModel
onDeploymentStarted:
{
Layout.preferredHeight: 22
Layout.preferredWidth: 22
action: clearAction
iconSource: "qrc:/qml/img/cleariconactive.png"
if (!logs[root.sel])
logs[root.sel] = ""
logs[root.sel] = logs[root.sel] + qsTr("Running deployment...") + "\n"
log.text = logs[root.sel]
}
Action {
id: clearAction
enabled: log.text !== ""
tooltip: qsTr("Clear")
onTriggered: {
log.text = ""
}
onDeploymentError:
{
if (!logs[root.sel])
logs[root.sel] = ""
logs[root.sel] = logs[root.sel] + error + "\n"
log.text = logs[root.sel]
}
Button
onDeploymentComplete:
{
Layout.preferredHeight: 22
text: qsTr("Clear Deployment")
action: clearDeployAction
if (!logs[root.sel])
logs[root.sel] = ""
logs[root.sel] = logs[root.sel] + qsTr("Deployment complete") + "\n"
log.text = logs[root.sel]
}
Action {
id: clearDeployAction
onTriggered: {
worker.forceStopPooling()
fileIo.deleteDir(projectModel.deploymentDir)
projectModel.cleanDeploymentStatus()
root.refreshCurrent()
log.text = ""
}
onDeploymentStepChanged:
{
if (!logs[root.sel])
logs[root.sel] = ""
logs[root.sel] = logs[root.sel] + message + "\n"
log.text = logs[root.sel]
}
}
Rectangle
{
Layout.fillWidth: true
Layout.preferredHeight: 2
color: "#cccccc"
}
ScrollView
{
Layout.fillHeight: true
@ -205,6 +246,47 @@ Rectangle {
id: log
}
}
Rectangle
{
Layout.preferredHeight: 20
Layout.fillWidth: true
color: "#cccccc"
LogsPaneStyle
{
id: style
}
Label
{
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Logs")
font.italic: true
font.pointSize: style.absoluteSize(-1)
}
Button
{
height: 20
width: 20
anchors.right: parent.right
action: clearAction
iconSource: "qrc:/qml/img/cleariconactive.png"
tooltip: qsTr("Clear Messages")
}
Action {
id: clearAction
enabled: log.text !== ""
tooltip: qsTr("Clear")
onTriggered: {
deployLogs.logs[root.sel] = ""
log.text = deployLogs.logs[root.sel]
}
}
}
}
}

6
mix/qml/DeploymentWorker.qml

@ -38,6 +38,7 @@ Item
var ids = JSON.parse(arg2)[0].result;
requests = [];
accounts = []
for (var k in ids)
{
requests.push({
@ -52,6 +53,7 @@ Item
TransactionHelper.rpcCall(requests, function (request, response){
var balanceRet = JSON.parse(response);
balances = {}
for (var k in balanceRet)
{
var ether = QEtherHelper.createEther(balanceRet[k].result, QEther.Wei);
@ -206,7 +208,7 @@ Item
property var callBack
property int elapsed
property string hash
interval: 500
interval: 2000
running: false
repeat: true
onTriggered: {
@ -227,7 +229,7 @@ Item
stop();
callBack(1, receipt);
}
else if (elapsed > 250000)
else if (elapsed > 2500000)
{
stop();
callBack(-1, null);

55
mix/qml/KeyValuePanel.qml

@ -82,45 +82,44 @@ ColumnLayout {
clip: true
ColumnLayout
{
anchors.margins: 10
spacing: 0
id: colValue
anchors.top: parent.top
anchors.topMargin: 5
Repeater
{
id: repeaterKeyValue
model: modelKeyValue
RowLayout
Row
{
Layout.fillWidth: true
Layout.preferredHeight: 30
spacing: 0
Rectangle
spacing: 5
anchors.left: colValue.left
anchors.leftMargin: 5
Label
{
Layout.preferredWidth: columnValues.width / 2
Label
{
anchors.left: parent.left
anchors.leftMargin: 10
text: {
if (index >= 0 && repeaterKeyValue.model.get(index).key !== undefined)
return repeaterKeyValue.model.get(index).key
else
return ""
}
maximumLineCount: 1
text: {
if (index >= 0 && repeaterKeyValue.model.get(index).key !== undefined)
return repeaterKeyValue.model.get(index).key
else
return ""
}
}
Rectangle
Label
{
Layout.preferredWidth: columnValues.width / 2 - 10
Label
{
anchors.right: parent.right
anchors.rightMargin: 10
text: {
if (index >= 0 && repeaterKeyValue.model.get(index).value !== undefined)
return repeaterKeyValue.model.get(index).value
else
return ""
}
text: "="
}
Label
{
maximumLineCount: 1
text: {
if (index >= 0 && repeaterKeyValue.model.get(index).value !== undefined)
return repeaterKeyValue.model.get(index).value
else
return ""
}
}
}

2
mix/qml/PackagingStep.qml

@ -20,6 +20,7 @@ Rectangle {
property alias lastDeployDate: lastDeployLabel.text
property string deploymentId
property string packageDir
signal packaged
function show()
{
@ -107,6 +108,7 @@ Rectangle {
{
NetworkDeploymentCode.packageDapp(projectModel.deploymentAddresses);
projectModel.saveProject()
root.packaged()
}
}

20
mix/qml/ProjectModel.qml

@ -80,20 +80,14 @@ Item {
function getDocumentIndex(documentId) { return ProjectModelCode.getDocumentIndex(documentId); }
function addExistingFiles(paths) { ProjectModelCode.doAddExistingFiles(paths); }
function deployProject() { NetworkDeploymentCode.deployProject(false); }
function registerToUrlHint(url, callback) { NetworkDeploymentCode.registerToUrlHint(url, callback); }
function registerToUrlHint(url, gasPrice, callback) { NetworkDeploymentCode.registerToUrlHint(url, gasPrice, callback); }
function formatAppUrl() { NetworkDeploymentCode.formatAppUrl(url); }
function cleanDeploymentStatus()
{
deployedScenarioIndex = 0
applicationUrlEth = ""
applicationUrlHttp = ""
deployBlockNumber = ""
deploymentTrHashes = {}
registerContentHashTrHash = ""
registerUrlTrHash = ""
registerContentHashBlockNumber = -1
registerUrlBlockNumber = -1
deploymentAddresses = {}
deploymentDir = ""
deploymentDialog.packageStep.packageHash = ""
@ -102,6 +96,18 @@ Item {
deploymentDialog.packageStep.lastDeployDate = ""
deploymentDialog.packageStep.localPackageUrl = ""
saveProject()
cleanRegisteringStatus()
}
function cleanRegisteringStatus()
{
applicationUrlEth = ""
applicationUrlHttp = ""
registerContentHashTrHash = ""
registerUrlTrHash = ""
registerContentHashBlockNumber = -1
registerUrlBlockNumber = -1
saveProject()
}
Connections {

74
mix/qml/RegisteringStep.qml

@ -19,42 +19,58 @@ Rectangle {
id: root
color: "#E3E3E3E3"
anchors.fill: parent
signal registered
function show()
{
ctrRegisterLabel.calculateRegisterGas()
applicationUrlEthCtrl.text = projectModel.applicationUrlEth
applicationUrlHttpCtrl.text = projectModel.applicationUrlHttp
if (applicationUrlHttpCtrl.text === "")
applicationUrlHttpCtrl.text = projectModel.applicationUrlHttp
if (applicationUrlEthCtrl.text === "")
applicationUrlEthCtrl.text = projectModel.applicationUrlEth
visible = true
verificationEthUrl.text = ""
if (projectModel.registerContentHashTrHash !== "")
if (projectModel.registerContentHashTrHash !== "" && projectModel.registerContentHashBlockNumber !== -1)
{
worker.verifyHash("registerHash", projectModel.registerContentHashTrHash, function(bn, trLost)
{
updateVerification(projectModel.registerContentHashBlockNumber, bn, trLost, verificationEthUrl)
updateVerification(projectModel.registerContentHashBlockNumber, bn, trLost, verificationEthUrl, "registerHash")
});
}
else if (projectModel.registerContentHashTrHash !== "" && projectModel.registerContentHashBlockNumber === -1)
verificationEthUrl.text = qsTr("waiting verifications")
verificationUrl.text = ""
if (projectModel.registerUrlTrHash !== "")
if (projectModel.registerUrlTrHash !== "" && projectModel.registerUrlBlockNumber !== -1)
{
worker.verifyHash("registerUrl", projectModel.registerUrlTrHash, function(bn, trLost)
{
updateVerification(projectModel.registerUrlBlockNumber, bn, trLost, verificationUrl)
updateVerification(projectModel.registerUrlBlockNumber, bn, trLost, verificationUrl, "registerUrl")
});
}
else if (projectModel.registerUrlTrHash !== "" && projectModel.registerUrlBlockNumber === -1)
verificationUrl.text = qsTr("waiting verifications")
}
function updateVerification(originbn, bn, trLost, ctrl)
function updateVerification(originbn, bn, trLost, ctrl, trContext)
{
if (trLost.length === 0)
{
ctrl.text = bn - originbn
ctrl.text += qsTr(" verifications")
if (parseInt(bn - originbn) >= 10)
{
ctrl.color= "green"
ctrl.text= qsTr("verified")
}
else
ctrl.text += qsTr(" verifications")
}
else
{
deploymentStepChanged(trContext + qsTr(" has been invalidated.") + trLost[0] + " " + qsTr("no longer present") )
ctrl.text = qsTr("invalidated")
}
}
@ -124,6 +140,7 @@ Rectangle {
{
id: verificationUrl
anchors.verticalCenter: parent.verticalCenter
font.italic: true
}
}
@ -136,7 +153,7 @@ Rectangle {
Layout.preferredWidth: col.width / 2
Label
{
text: qsTr("Gas to use for dapp registration")
text: qsTr("Registration Cost")
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
id: ctrRegisterLabel
@ -148,9 +165,12 @@ Rectangle {
NetworkDeploymentCode.checkPathCreationCost(applicationUrlEthCtrl.text, function(pathCreationCost)
{
var ether = QEtherHelper.createBigInt(pathCreationCost);
var gasTotal = ether.multiply(worker.gasPriceInt);
gasToUseDeployInput.value = QEtherHelper.createEther(gasTotal.value(), QEther.Wei, parent);
gasToUseDeployInput.update();
if (deploymentDialog.deployStep.gasPrice.value)
{
var gasTotal = ether.multiply(deploymentDialog.deployStep.gasPrice.value.toWei());
gasToUseDeployInput.value = QEtherHelper.createEther(gasTotal.value(), QEther.Wei, parent);
gasToUseDeployInput.update();
}
});
}
}
@ -159,9 +179,9 @@ Rectangle {
Ether
{
id: gasToUseDeployInput
displayUnitSelection: true
displayUnitSelection: false
displayFormattedValue: true
edit: true
edit: false
Layout.preferredWidth: 235
}
}
@ -224,6 +244,10 @@ Rectangle {
Label
{
id: verificationEthUrl
anchors.verticalCenter: parent.verticalCenter;
anchors.topMargin: 10
font.italic: true
font.pointSize: appStyle.absoluteSize(-1)
}
}
}
@ -234,7 +258,7 @@ Rectangle {
anchors.bottomMargin: 10
width: parent.width
function registerHash(callback)
function registerHash(gasPrice, callback)
{
var inError = [];
var ethUrl = NetworkDeploymentCode.formatAppUrl(applicationUrlEthCtrl.text);
@ -244,10 +268,11 @@ Rectangle {
inError.push(qsTr("Member too long: " + ethUrl[k]) + "\n");
}
if (!worker.stopForInputError(inError))
{
NetworkDeploymentCode.registerDapp(ethUrl, function(){
{
NetworkDeploymentCode.registerDapp(ethUrl, gasPrice, function(){
projectModel.applicationUrlEth = applicationUrlEthCtrl.text
projectModel.saveProject()
verificationEthUrl.text = qsTr("waiting verifications")
worker.waitForTrReceipt(projectModel.registerContentHashTrHash, function(status, receipt)
{
worker.verifyHash("registerHash", projectModel.registerContentHashTrHash, function(bn, trLost)
@ -262,7 +287,7 @@ Rectangle {
}
}
function registerUrl()
function registerUrl(gasPrice, callback)
{
if (applicationUrlHttp.text === "" || deploymentDialog.packageHash === "")
{
@ -276,9 +301,10 @@ Rectangle {
inError.push(qsTr(applicationUrlHttpCtrl.text));
if (!worker.stopForInputError(inError))
{
registerToUrlHint(applicationUrlHttpCtrl.text, function(){
registerToUrlHint(applicationUrlHttpCtrl.text, gasPrice, function(){
projectModel.applicationUrlHttp = applicationUrlHttpCtrl.text
projectModel.saveProject()
verificationUrl.text = qsTr("waiting verifications")
worker.waitForTrReceipt(projectModel.registerUrlTrHash, function(status, receipt)
{
worker.verifyHash("registerUrl", projectModel.registerUrlTrHash, function(bn, trLost)
@ -286,6 +312,8 @@ Rectangle {
projectModel.registerUrlBlockNumber = bn
projectModel.saveProject()
root.updateVerification(bn, bn, trLost, verificationUrl)
root.registered()
callback()
});
})
})
@ -300,8 +328,12 @@ Rectangle {
width: 30
onClicked:
{
parent.registerHash(function(){
parent.registerUrl()
verificationEthUrl.text = ""
verificationUrl.text = ""
projectModel.cleanRegisteringStatus()
var gasPrice = deploymentDialog.deployStep.gasPrice.toHexWei()
parent.registerHash(gasPrice, function(){
parent.registerUrl(gasPrice, function(){})
})
}
}

4
mix/qml/ScenarioLoader.qml

@ -35,7 +35,7 @@ ColumnLayout
{
Layout.preferredWidth: 560
anchors.horizontalCenter: parent.horizontalCenter
Layout.preferredHeight: 60
Layout.preferredHeight: 75
spacing: 0
anchors.top: parent.top
anchors.topMargin: 10
@ -88,7 +88,7 @@ ColumnLayout
color: "#cccccc"
id: deleteImg
anchors.top: parent.top
anchors.topMargin: 6
anchors.topMargin: 7
visible: projectModel.stateListModel.count > 1
MouseArea
{

2
mix/qml/StatusPane.qml

@ -179,7 +179,7 @@ Rectangle {
function updateWidth()
{
if (text.length > 80)
if (text.length > 100)
width = parent.width - 10
else
width = undefined

3
mix/qml/WebPreview.qml

@ -272,7 +272,8 @@ Item {
Button
{
height: 28
height: 22
width: 22
anchors.verticalCenter: parent.verticalCenter
action: expressionAction
iconSource: "qrc:/qml/img/console.png"

39
mix/qml/js/NetworkDeployment.js

@ -32,11 +32,10 @@ function deployProject(force) {
deploymentDialog.open();
}
function deployContracts(gas, callback)
function deployContracts(gas, gasPrice, callback)
{
deploymentGas = gas;
var jsonRpcUrl = "http://127.0.0.1:8080";
console.log("Deploying to " + jsonRpcUrl);
deploymentGasPrice = gasPrice
deploymentStarted();
var ctrAddresses = {};
@ -79,10 +78,7 @@ function checkPathCreationCost(ethUrl, callBack)
}
}
else
{
deploymentStepChanged(qsTr("Your Dapp can be registered here."));
callBack((dappUrl.length - 1) * (deploymentDialog.registerStep.ownedRegistrarDeployGas + deploymentDialog.registerStep.ownedRegistrarSetSubRegistrarGas) + deploymentDialog.registerStep.ownedRegistrarSetContentHashGas);
}
});
}
@ -140,6 +136,7 @@ function getFunction(ctrName, functionId)
}
var deploymentGas
var deploymentGasPrice
var trRealIndex = -1
function executeTr(blockIndex, trIndex, state, ctrAddresses, trHashes, callBack)
{
@ -153,14 +150,14 @@ function executeTr(blockIndex, trIndex, state, ctrAddresses, trHashes, callBack)
else
{
var gasCost = clientModel.toHex(deploymentGas[trRealIndex]);
var rpcParams = { "from": deploymentDialog.worker.currentAccount, "gas": "0x" + gasCost };
var rpcParams = { "from": deploymentDialog.worker.currentAccount, "gas": "0x" + gasCost, "gasPrice": deploymentGasPrice };
var params = replaceParamToken(func.parameters, tr.parameters, ctrAddresses);
var encodedParams = clientModel.encodeParams(params, contractFromToken(tr.contractId), tr.functionId);
if (tr.contractId === tr.functionId)
rpcParams.code = codeModel.contracts[tr.contractId].codeHex + encodedParams.join("");
else
rpcParams.data = func.hash + encodedParams.join("");
rpcParams.data = "0x" + func.qhash() + encodedParams.join("");
var requests = [{
jsonrpc: "2.0",
@ -214,13 +211,9 @@ function executeTrNextStep(blockIndex, trIndex, state, ctrAddresses, trHashes, c
{
blockIndex++
if (blockIndex < state.blocks.count)
{
executeTr(blockIndex, 0, state, ctrAddresses, trHashes, callBack);
}
else
{
callBack();
}
}
}
@ -298,16 +291,17 @@ function packageDapp(addresses)
deploymentDialog.packageStep.packageBase64 = packageRet[1];
deploymentDialog.packageStep.localPackageUrl = packageRet[2] + "?hash=" + packageRet[0];
deploymentDialog.packageStep.lastDeployDate = date
deploymentComplete()
deploymentStepChanged(qsTr("Dapp is Packaged"))
}
function registerDapp(url, callback)
function registerDapp(url, gasPrice, callback)
{
deploymentGasPrice = gasPrice
deploymentStepChanged(qsTr("Registering application on the Ethereum network ..."));
checkEthPath(url, false, function (success) {
if (!success)
return;
deploymentComplete();
deploymentStepChanged(qsTr("Dapp has been registered. Please wait for verifications."));
if (callback)
callback()
});
@ -446,7 +440,7 @@ function continueRegistration(dappUrl, addr, callBack, checkOnly)
requests.push({
jsonrpc: "2.0",
method: "eth_sendTransaction",
params: [ { "from": deploymentDialog.worker.currentAccount, "gas": "0x" + gasCost, "code": "0x600080547fffffffffffffffffffffffff000000000000000000000000000000000000000016331781556105cd90819061003990396000f3007c010000000000000000000000000000000000000000000000000000000060003504630198489281146100b257806321f8a721146100e45780632dff6941146100ee5780633b3b57de1461010e5780635a3a05bd1461013e5780635fd4b08a146101715780637dd564111461017d57806389a69c0e14610187578063b387ef92146101bb578063b5c645bd146101f4578063be99a98014610270578063c3d014d6146102a8578063d93e7573146102dc57005b73ffffffffffffffffffffffffffffffffffffffff600435166000908152600160205260409020548060005260206000f35b6000808052602081f35b600435600090815260026020819052604090912001548060005260206000f35b600435600090815260026020908152604082205473ffffffffffffffffffffffffffffffffffffffff1680835291f35b600435600090815260026020908152604082206001015473ffffffffffffffffffffffffffffffffffffffff1680835291f35b60008060005260206000f35b6000808052602081f35b60005461030c9060043590602435903373ffffffffffffffffffffffffffffffffffffffff908116911614610569576105c9565b60005473ffffffffffffffffffffffffffffffffffffffff168073ffffffffffffffffffffffffffffffffffffffff1660005260206000f35b600435600090815260026020819052604090912080546001820154919092015473ffffffffffffffffffffffffffffffffffffffff9283169291909116908273ffffffffffffffffffffffffffffffffffffffff166000528173ffffffffffffffffffffffffffffffffffffffff166020528060405260606000f35b600054610312906004359060243590604435903373ffffffffffffffffffffffffffffffffffffffff90811691161461045457610523565b6000546103189060043590602435903373ffffffffffffffffffffffffffffffffffffffff90811691161461052857610565565b60005461031e90600435903373ffffffffffffffffffffffffffffffffffffffff90811691161461032457610451565b60006000f35b60006000f35b60006000f35b60006000f35b60008181526002602090815260408083205473ffffffffffffffffffffffffffffffffffffffff16835260019091529020548114610361576103e1565b6000818152600260205260408082205473ffffffffffffffffffffffffffffffffffffffff169183917ff63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a85459190a360008181526002602090815260408083205473ffffffffffffffffffffffffffffffffffffffff16835260019091528120555b600081815260026020819052604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168255600182018054909116905590910182905582917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b50565b600083815260026020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001683179055806104bb57827fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc60006040a2610522565b73ffffffffffffffffffffffffffffffffffffffff8216837ff63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a854560006040a373ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090208390555b5b505050565b600082815260026020819052604080832090910183905583917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b5050565b60008281526002602052604080822060010180547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905583917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b505056" } ],
params: [ { "from": deploymentDialog.worker.currentAccount, "gasPrice": deploymentGasPrice, "gas": "0x" + gasCost, "code": "0x600080547fffffffffffffffffffffffff000000000000000000000000000000000000000016331781556105cd90819061003990396000f3007c010000000000000000000000000000000000000000000000000000000060003504630198489281146100b257806321f8a721146100e45780632dff6941146100ee5780633b3b57de1461010e5780635a3a05bd1461013e5780635fd4b08a146101715780637dd564111461017d57806389a69c0e14610187578063b387ef92146101bb578063b5c645bd146101f4578063be99a98014610270578063c3d014d6146102a8578063d93e7573146102dc57005b73ffffffffffffffffffffffffffffffffffffffff600435166000908152600160205260409020548060005260206000f35b6000808052602081f35b600435600090815260026020819052604090912001548060005260206000f35b600435600090815260026020908152604082205473ffffffffffffffffffffffffffffffffffffffff1680835291f35b600435600090815260026020908152604082206001015473ffffffffffffffffffffffffffffffffffffffff1680835291f35b60008060005260206000f35b6000808052602081f35b60005461030c9060043590602435903373ffffffffffffffffffffffffffffffffffffffff908116911614610569576105c9565b60005473ffffffffffffffffffffffffffffffffffffffff168073ffffffffffffffffffffffffffffffffffffffff1660005260206000f35b600435600090815260026020819052604090912080546001820154919092015473ffffffffffffffffffffffffffffffffffffffff9283169291909116908273ffffffffffffffffffffffffffffffffffffffff166000528173ffffffffffffffffffffffffffffffffffffffff166020528060405260606000f35b600054610312906004359060243590604435903373ffffffffffffffffffffffffffffffffffffffff90811691161461045457610523565b6000546103189060043590602435903373ffffffffffffffffffffffffffffffffffffffff90811691161461052857610565565b60005461031e90600435903373ffffffffffffffffffffffffffffffffffffffff90811691161461032457610451565b60006000f35b60006000f35b60006000f35b60006000f35b60008181526002602090815260408083205473ffffffffffffffffffffffffffffffffffffffff16835260019091529020548114610361576103e1565b6000818152600260205260408082205473ffffffffffffffffffffffffffffffffffffffff169183917ff63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a85459190a360008181526002602090815260408083205473ffffffffffffffffffffffffffffffffffffffff16835260019091528120555b600081815260026020819052604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168255600182018054909116905590910182905582917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b50565b600083815260026020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001683179055806104bb57827fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc60006040a2610522565b73ffffffffffffffffffffffffffffffffffffffff8216837ff63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a854560006040a373ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090208390555b5b505050565b600082815260026020819052604080832090910183905583917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b5050565b60008281526002602052604080822060010180547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905583917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b505056" } ],
id: jsonRpcRequestId++
});
@ -468,7 +462,7 @@ function continueRegistration(dappUrl, addr, callBack, checkOnly)
//setRegister()
jsonrpc: "2.0",
method: "eth_sendTransaction",
params: [ { "from": deploymentDialog.worker.currentAccount, "gas": "0x" + gasCost, "to": '0x' + addr, "data": "0x89a69c0e" + crLevel + newCtrAddress } ],
params: [ { "from": deploymentDialog.worker.currentAccount, "gasPrice": deploymentGasPrice, "gas": "0x" + gasCost, "to": '0x' + addr, "data": "0x89a69c0e" + crLevel + newCtrAddress } ],
id: jsonRpcRequestId++
});
@ -501,7 +495,7 @@ function reserve(registrar, callBack)
//reserve()
jsonrpc: "2.0",
method: "eth_sendTransaction",
params: [ { "from": deploymentDialog.worker.currentAccount, "gas": "0xfffff", "to": '0x' + registrar, "data": "0x432ced04" + paramTitle } ],
params: [ { "from": deploymentDialog.worker.currentAccount, "gasPrice": deploymentGasPrice, "gas": "0xfffff", "to": '0x' + registrar, "data": "0x432ced04" + paramTitle } ],
id: jsonRpcRequestId++
});
rpcCall(requests, function (httpRequest, response) {
@ -524,7 +518,7 @@ function registerContentHash(registrar, callBack)
//setContent()
jsonrpc: "2.0",
method: "eth_sendTransaction",
params: [ { "from": deploymentDialog.worker.currentAccount, "gas": "0x" + gasCost, "to": '0x' + registrar, "data": "0xc3d014d6" + paramTitle + deploymentDialog.packageStep.packageHash } ],
params: [ { "from": deploymentDialog.worker.currentAccount, "gasPrice": deploymentGasPrice, "gas": "0x" + gasCost, "to": '0x' + registrar, "data": "0xc3d014d6" + paramTitle + deploymentDialog.packageStep.packageHash } ],
id: jsonRpcRequestId++
});
rpcCall(requests, function (httpRequest, response) {
@ -533,9 +527,10 @@ function registerContentHash(registrar, callBack)
});
}
function registerToUrlHint(url, callback)
function registerToUrlHint(url, gasPrice, callback)
{
console.log("register url " + deploymentDialog.packageStep.packageHash + " " + url)
deploymentGasPrice = gasPrice
deploymentStepChanged(qsTr("Registering application Resources..."))
urlHintAddress(function(urlHint){
var requests = [];
@ -545,13 +540,13 @@ function registerToUrlHint(url, callback)
//urlHint => suggestUrl
jsonrpc: "2.0",
method: "eth_sendTransaction",
params: [ { "to": '0x' + urlHint, "from": deploymentDialog.worker.currentAccount, "gas": "0x" + gasCost, "data": "0x584e86ad" + deploymentDialog.packageStep.packageHash + paramUrlHttp } ],
params: [ { "to": '0x' + urlHint, "gasPrice": deploymentGasPrice, "from": deploymentDialog.worker.currentAccount, "gas": "0x" + gasCost, "data": "0x584e86ad" + deploymentDialog.packageStep.packageHash + paramUrlHttp } ],
id: jsonRpcRequestId++
});
rpcCall(requests, function (httpRequest, response) {
projectModel.registerUrlTrHash = JSON.parse(response)[0].result
deploymentComplete();
deploymentStepChanged(qsTr("Dapp resources has been registered. Please wait for verifications."));
if (callback)
callback()
});

3
mix/qml/js/TransactionHelper.js

@ -33,7 +33,8 @@ function rpcCall(requests, callBack, error)
{
var errorText = qsTr("Unable to initiate request to the live network. Please verify your ethereum node is up.") + qsTr(" Error status: ") + httpRequest.status;
console.log(errorText);
error(errorText);
if (error)
error(errorText);
}
else
{

46
test/libsolidity/SolidityWallet.cpp

@ -116,7 +116,7 @@ contract multiowned {
}
// Replaces an owner `_from` with another `_to`.
function changeOwner(address _from, address _to) onlymanyowners(sha3(msg.data, block.number)) external {
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;
@ -128,7 +128,7 @@ contract multiowned {
OwnerChanged(_from, _to);
}
function addOwner(address _owner) onlymanyowners(sha3(msg.data, block.number)) external {
function addOwner(address _owner) onlymanyowners(sha3(msg.data)) external {
if (isOwner(_owner)) return;
clearPending();
@ -142,7 +142,7 @@ contract multiowned {
OwnerAdded(_owner);
}
function removeOwner(address _owner) onlymanyowners(sha3(msg.data, block.number)) external {
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;
@ -154,7 +154,7 @@ contract multiowned {
OwnerRemoved(_owner);
}
function changeRequirement(uint _newRequired) onlymanyowners(sha3(msg.data, block.number)) external {
function changeRequirement(uint _newRequired) onlymanyowners(sha3(msg.data)) external {
if (_newRequired > m_numOwners) return;
m_required = _newRequired;
clearPending();
@ -275,16 +275,17 @@ contract daylimit is multiowned {
// METHODS
// constructor - just records the present day's index.
function daylimit() {
// constructor - stores initial daily limit and records the present day's index.
function daylimit(uint _limit) {
m_dailyLimit = _limit;
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, block.number)) external {
function setDailyLimit(uint _newLimit) onlymanyowners(sha3(msg.data)) 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, block.number)) external {
function resetSpentToday() onlymanyowners(sha3(msg.data)) external {
m_spentToday = 0;
}
@ -354,12 +355,14 @@ contract Wallet is multisig, multiowned, daylimit {
// METHODS
// constructor - just pass on the owner array to the multiowned.
function Wallet(address[] _owners, uint _required) multiowned(_owners, _required) {
// constructor - just pass on the owner array to the multiowned and
// the limit to daylimit
function Wallet(address[] _owners, uint _required, uint _daylimit)
multiowned(_owners, _required) daylimit(_daylimit) {
}
// kills the contract sending everything to `_to`.
function kill(address _to) onlymanyowners(sha3(msg.data, block.number)) external {
function kill(address _to) onlymanyowners(sha3(msg.data)) external {
suicide(_to);
}
@ -424,7 +427,12 @@ static unique_ptr<bytes> s_compiledWallet;
class WalletTestFramework: public ExecutionFramework
{
protected:
void deployWallet(u256 const& _value = 0, vector<u256> const& _owners = vector<u256>{}, u256 _required = 1)
void deployWallet(
u256 const& _value = 0,
vector<u256> const& _owners = vector<u256>{},
u256 _required = 1,
u256 _dailyLimit = 0
)
{
if (!s_compiledWallet)
{
@ -434,7 +442,7 @@ protected:
ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize, m_optimizeRuns), "Compiling contract failed");
s_compiledWallet.reset(new bytes(m_compiler.getBytecode("Wallet")));
}
bytes args = encodeArgs(u256(0x40), _required, u256(_owners.size()), _owners);
bytes args = encodeArgs(u256(0x60), _required, _dailyLimit, u256(_owners.size()), _owners);
sendMessage(*s_compiledWallet + args, true, _value);
BOOST_REQUIRE(!m_output.empty());
}
@ -519,7 +527,7 @@ BOOST_AUTO_TEST_CASE(initial_owners)
u256("0x0000000000000000000000004c9113886af165b2de069d6e99430647e94a9fff"),
u256("0x0000000000000000000000003fb1cd2cd96c6d5c0b5eb3322d807b34482481d4")
};
deployWallet(0, owners, 4);
deployWallet(0, owners, 4, 2);
BOOST_CHECK(callContractFunction("m_numOwners()") == encodeArgs(u256(8)));
BOOST_CHECK(callContractFunction("isOwner(address)", h256(m_sender, h256::AlignRight)) == encodeArgs(true));
for (u256 const& owner: owners)
@ -554,7 +562,9 @@ BOOST_AUTO_TEST_CASE(multisig_value_transfer)
BOOST_AUTO_TEST_CASE(daylimit)
{
deployWallet(200);
BOOST_REQUIRE(callContractFunction("m_dailyLimit()") == encodeArgs(u256(0)));
BOOST_REQUIRE(callContractFunction("setDailyLimit(uint256)", h256(100)) == encodeArgs());
BOOST_REQUIRE(callContractFunction("m_dailyLimit()") == encodeArgs(u256(100)));
BOOST_REQUIRE(callContractFunction("addOwner(address)", h256(0x12)) == encodeArgs());
BOOST_REQUIRE(callContractFunction("addOwner(address)", h256(0x13)) == encodeArgs());
BOOST_REQUIRE(callContractFunction("addOwner(address)", h256(0x14)) == encodeArgs());
@ -585,6 +595,14 @@ BOOST_AUTO_TEST_CASE(daylimit)
BOOST_CHECK_EQUAL(m_state.balance(Address(0x05)), 90);
}
BOOST_AUTO_TEST_CASE(daylimit_constructor)
{
deployWallet(200, {}, 1, 20);
BOOST_REQUIRE(callContractFunction("m_dailyLimit()") == encodeArgs(u256(20)));
BOOST_REQUIRE(callContractFunction("setDailyLimit(uint256)", h256(30)) == encodeArgs());
BOOST_REQUIRE(callContractFunction("m_dailyLimit()") == encodeArgs(u256(30)));
}
//@todo test data calls
BOOST_AUTO_TEST_SUITE_END()

Loading…
Cancel
Save