47
Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/CMakeLists.txt
generated
vendored
@ -1,47 +0,0 @@ |
||||
cmake_minimum_required(VERSION 2.8) |
||||
|
||||
set(LIBRARY ethash-cl) |
||||
set(CMAKE_BUILD_TYPE Release) |
||||
|
||||
include(bin2h.cmake) |
||||
bin2h(SOURCE_FILE ethash_cl_miner_kernel.cl |
||||
VARIABLE_NAME ethash_cl_miner_kernel |
||||
HEADER_FILE ${CMAKE_CURRENT_BINARY_DIR}/ethash_cl_miner_kernel.h) |
||||
|
||||
if (NOT MSVC) |
||||
# Initialize CXXFLAGS for c++11 |
||||
set(CMAKE_CXX_FLAGS "-Wall -std=c++11") |
||||
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") |
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG") |
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") |
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") |
||||
|
||||
# Compiler-specific C++11 activation. |
||||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") |
||||
execute_process( |
||||
COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) |
||||
if (NOT (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)) |
||||
message(FATAL_ERROR "${PROJECT_NAME} requires g++ 4.7 or greater.") |
||||
endif () |
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") |
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") |
||||
else () |
||||
message(FATAL_ERROR "Your C++ compiler does not support C++11.") |
||||
endif () |
||||
endif() |
||||
|
||||
set(OpenCL_FOUND TRUE) |
||||
set(OpenCL_INCLUDE_DIRS /usr/include/CL) |
||||
set(OpenCL_LIBRARIES -lOpenCL) |
||||
|
||||
if (NOT OpenCL_FOUND) |
||||
find_package(OpenCL) |
||||
endif() |
||||
|
||||
if (OpenCL_FOUND) |
||||
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -Werror -pedantic -fPIC ${CMAKE_CXX_FLAGS}") |
||||
include_directories(${OpenCL_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) |
||||
include_directories(..) |
||||
add_library(${LIBRARY} ethash_cl_miner.cpp ethash_cl_miner.h cl.hpp) |
||||
TARGET_LINK_LIBRARIES(${LIBRARY} ${OpenCL_LIBRARIES} ethash) |
||||
endif() |
@ -1,86 +0,0 @@ |
||||
# https://gist.github.com/sivachandran/3a0de157dccef822a230 |
||||
include(CMakeParseArguments) |
||||
|
||||
# Function to wrap a given string into multiple lines at the given column position. |
||||
# Parameters: |
||||
# VARIABLE - The name of the CMake variable holding the string. |
||||
# AT_COLUMN - The column position at which string will be wrapped. |
||||
function(WRAP_STRING) |
||||
set(oneValueArgs VARIABLE AT_COLUMN) |
||||
cmake_parse_arguments(WRAP_STRING "${options}" "${oneValueArgs}" "" ${ARGN}) |
||||
|
||||
string(LENGTH ${${WRAP_STRING_VARIABLE}} stringLength) |
||||
math(EXPR offset "0") |
||||
|
||||
while(stringLength GREATER 0) |
||||
|
||||
if(stringLength GREATER ${WRAP_STRING_AT_COLUMN}) |
||||
math(EXPR length "${WRAP_STRING_AT_COLUMN}") |
||||
else() |
||||
math(EXPR length "${stringLength}") |
||||
endif() |
||||
|
||||
string(SUBSTRING ${${WRAP_STRING_VARIABLE}} ${offset} ${length} line) |
||||
set(lines "${lines}\n${line}") |
||||
|
||||
math(EXPR stringLength "${stringLength} - ${length}") |
||||
math(EXPR offset "${offset} + ${length}") |
||||
endwhile() |
||||
|
||||
set(${WRAP_STRING_VARIABLE} "${lines}" PARENT_SCOPE) |
||||
endfunction() |
||||
|
||||
# Function to embed contents of a file as byte array in C/C++ header file(.h). The header file |
||||
# will contain a byte array and integer variable holding the size of the array. |
||||
# Parameters |
||||
# SOURCE_FILE - The path of source file whose contents will be embedded in the header file. |
||||
# VARIABLE_NAME - The name of the variable for the byte array. The string "_SIZE" will be append |
||||
# to this name and will be used a variable name for size variable. |
||||
# HEADER_FILE - The path of header file. |
||||
# APPEND - If specified appends to the header file instead of overwriting it |
||||
# NULL_TERMINATE - If specified a null byte(zero) will be append to the byte array. This will be |
||||
# useful if the source file is a text file and we want to use the file contents |
||||
# as string. But the size variable holds size of the byte array without this |
||||
# null byte. |
||||
# Usage: |
||||
# bin2h(SOURCE_FILE "Logo.png" HEADER_FILE "Logo.h" VARIABLE_NAME "LOGO_PNG") |
||||
function(BIN2H) |
||||
set(options APPEND NULL_TERMINATE) |
||||
set(oneValueArgs SOURCE_FILE VARIABLE_NAME HEADER_FILE) |
||||
cmake_parse_arguments(BIN2H "${options}" "${oneValueArgs}" "" ${ARGN}) |
||||
|
||||
# reads source file contents as hex string |
||||
file(READ ${BIN2H_SOURCE_FILE} hexString HEX) |
||||
string(LENGTH ${hexString} hexStringLength) |
||||
|
||||
# appends null byte if asked |
||||
if(BIN2H_NULL_TERMINATE) |
||||
set(hexString "${hexString}00") |
||||
endif() |
||||
|
||||
# wraps the hex string into multiple lines at column 32(i.e. 16 bytes per line) |
||||
wrap_string(VARIABLE hexString AT_COLUMN 32) |
||||
math(EXPR arraySize "${hexStringLength} / 2") |
||||
|
||||
# adds '0x' prefix and comma suffix before and after every byte respectively |
||||
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1, " arrayValues ${hexString}) |
||||
# removes trailing comma |
||||
string(REGEX REPLACE ", $" "" arrayValues ${arrayValues}) |
||||
|
||||
# converts the variable name into proper C identifier |
||||
IF (${CMAKE_VERSION} GREATER 2.8.10) # fix for legacy cmake |
||||
string(MAKE_C_IDENTIFIER "${BIN2H_VARIABLE_NAME}" BIN2H_VARIABLE_NAME) |
||||
ENDIF() |
||||
string(TOUPPER "${BIN2H_VARIABLE_NAME}" BIN2H_VARIABLE_NAME) |
||||
|
||||
# declares byte array and the length variables |
||||
set(arrayDefinition "const unsigned char ${BIN2H_VARIABLE_NAME}[] = { ${arrayValues} };") |
||||
set(arraySizeDefinition "const size_t ${BIN2H_VARIABLE_NAME}_SIZE = ${arraySize};") |
||||
|
||||
set(declarations "${arrayDefinition}\n\n${arraySizeDefinition}\n\n") |
||||
if(BIN2H_APPEND) |
||||
file(APPEND ${BIN2H_HEADER_FILE} "${declarations}") |
||||
else() |
||||
file(WRITE ${BIN2H_HEADER_FILE} "${declarations}") |
||||
endif() |
||||
endfunction() |
384
Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner.cpp
generated
vendored
@ -1,384 +0,0 @@ |
||||
/*
|
||||
This file is part of c-ethash. |
||||
|
||||
c-ethash 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. |
||||
|
||||
c-ethash 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 <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
/** @file ethash_cl_miner.cpp
|
||||
* @author Tim Hughes <tim@twistedfury.com> |
||||
* @date 2015 |
||||
*/ |
||||
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS |
||||
|
||||
#include <cstdio> |
||||
#include <cstdlib> |
||||
#include <iostream> |
||||
#include <assert.h> |
||||
#include <queue> |
||||
#include <vector> |
||||
#include <libethash/util.h> |
||||
#include <libethash/ethash.h> |
||||
#include <libethash/internal.h> |
||||
#include "ethash_cl_miner.h" |
||||
#include "ethash_cl_miner_kernel.h" |
||||
|
||||
#define ETHASH_BYTES 32 |
||||
|
||||
// workaround lame platforms
|
||||
#if !CL_VERSION_1_2 |
||||
#define CL_MAP_WRITE_INVALIDATE_REGION CL_MAP_WRITE |
||||
#define CL_MEM_HOST_READ_ONLY 0 |
||||
#endif |
||||
|
||||
#undef min |
||||
#undef max |
||||
|
||||
using namespace std; |
||||
|
||||
static void add_definition(std::string& source, char const* id, unsigned value) |
||||
{ |
||||
char buf[256]; |
||||
sprintf(buf, "#define %s %uu\n", id, value); |
||||
source.insert(source.begin(), buf, buf + strlen(buf)); |
||||
} |
||||
|
||||
ethash_cl_miner::search_hook::~search_hook() {} |
||||
|
||||
ethash_cl_miner::ethash_cl_miner() |
||||
: m_opencl_1_1() |
||||
{ |
||||
} |
||||
|
||||
std::string ethash_cl_miner::platform_info(unsigned _platformId, unsigned _deviceId) |
||||
{ |
||||
std::vector<cl::Platform> platforms; |
||||
cl::Platform::get(&platforms); |
||||
if (platforms.empty()) |
||||
{ |
||||
cout << "No OpenCL platforms found." << endl; |
||||
return std::string(); |
||||
} |
||||
|
||||
// get GPU device of the selected platform
|
||||
std::vector<cl::Device> devices; |
||||
unsigned platform_num = std::min<unsigned>(_platformId, platforms.size() - 1); |
||||
platforms[platform_num].getDevices(CL_DEVICE_TYPE_ALL, &devices); |
||||
if (devices.empty()) |
||||
{ |
||||
cout << "No OpenCL devices found." << endl; |
||||
return std::string(); |
||||
} |
||||
|
||||
// use selected default device
|
||||
unsigned device_num = std::min<unsigned>(_deviceId, devices.size() - 1); |
||||
cl::Device& device = devices[device_num]; |
||||
std::string device_version = device.getInfo<CL_DEVICE_VERSION>(); |
||||
|
||||
return "{ \"platform\": \"" + platforms[platform_num].getInfo<CL_PLATFORM_NAME>() + "\", \"device\": \"" + device.getInfo<CL_DEVICE_NAME>() + "\", \"version\": \"" + device_version + "\" }"; |
||||
} |
||||
|
||||
unsigned ethash_cl_miner::get_num_devices(unsigned _platformId) |
||||
{ |
||||
std::vector<cl::Platform> platforms; |
||||
cl::Platform::get(&platforms); |
||||
if (platforms.empty()) |
||||
{ |
||||
cout << "No OpenCL platforms found." << endl; |
||||
return 0; |
||||
} |
||||
|
||||
std::vector<cl::Device> devices; |
||||
unsigned platform_num = std::min<unsigned>(_platformId, platforms.size() - 1); |
||||
platforms[platform_num].getDevices(CL_DEVICE_TYPE_ALL, &devices); |
||||
if (devices.empty()) |
||||
{ |
||||
cout << "No OpenCL devices found." << endl; |
||||
return 0; |
||||
} |
||||
return devices.size(); |
||||
} |
||||
|
||||
void ethash_cl_miner::finish() |
||||
{ |
||||
if (m_queue()) |
||||
m_queue.finish(); |
||||
} |
||||
|
||||
bool ethash_cl_miner::init(uint64_t block_number, std::function<void(void*)> _fillDAG, unsigned workgroup_size, unsigned _platformId, unsigned _deviceId) |
||||
{ |
||||
// store params
|
||||
m_fullSize = ethash_get_datasize(block_number); |
||||
|
||||
// get all platforms
|
||||
std::vector<cl::Platform> platforms; |
||||
cl::Platform::get(&platforms); |
||||
if (platforms.empty()) |
||||
{ |
||||
cout << "No OpenCL platforms found." << endl; |
||||
return false; |
||||
} |
||||
|
||||
// use selected platform
|
||||
_platformId = std::min<unsigned>(_platformId, platforms.size() - 1); |
||||
|
||||
cout << "Using platform: " << platforms[_platformId].getInfo<CL_PLATFORM_NAME>().c_str() << endl; |
||||
|
||||
// get GPU device of the default platform
|
||||
std::vector<cl::Device> devices; |
||||
platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices); |
||||
if (devices.empty()) |
||||
{ |
||||
cout << "No OpenCL devices found." << endl; |
||||
return false; |
||||
} |
||||
|
||||
// use selected device
|
||||
cl::Device& device = devices[std::min<unsigned>(_deviceId, devices.size() - 1)]; |
||||
std::string device_version = device.getInfo<CL_DEVICE_VERSION>(); |
||||
cout << "Using device: " << device.getInfo<CL_DEVICE_NAME>().c_str() << "(" << device_version.c_str() << ")" << endl; |
||||
|
||||
if (strncmp("OpenCL 1.0", device_version.c_str(), 10) == 0) |
||||
{ |
||||
cout << "OpenCL 1.0 is not supported." << endl; |
||||
return false; |
||||
} |
||||
if (strncmp("OpenCL 1.1", device_version.c_str(), 10) == 0) |
||||
m_opencl_1_1 = true; |
||||
|
||||
// create context
|
||||
m_context = cl::Context(std::vector<cl::Device>(&device, &device + 1)); |
||||
m_queue = cl::CommandQueue(m_context, device); |
||||
|
||||
// use requested workgroup size, but we require multiple of 8
|
||||
m_workgroup_size = ((workgroup_size + 7) / 8) * 8; |
||||
|
||||
// patch source code
|
||||
std::string code(ETHASH_CL_MINER_KERNEL, ETHASH_CL_MINER_KERNEL + ETHASH_CL_MINER_KERNEL_SIZE); |
||||
add_definition(code, "GROUP_SIZE", m_workgroup_size); |
||||
add_definition(code, "DAG_SIZE", (unsigned)(m_fullSize / ETHASH_MIX_BYTES)); |
||||
add_definition(code, "ACCESSES", ETHASH_ACCESSES); |
||||
add_definition(code, "MAX_OUTPUTS", c_max_search_results); |
||||
//debugf("%s", code.c_str());
|
||||
|
||||
// create miner OpenCL program
|
||||
cl::Program::Sources sources; |
||||
sources.push_back({code.c_str(), code.size()}); |
||||
|
||||
cl::Program program(m_context, sources); |
||||
try |
||||
{ |
||||
program.build({device}); |
||||
} |
||||
catch (cl::Error err) |
||||
{ |
||||
cout << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device).c_str(); |
||||
return false; |
||||
} |
||||
m_hash_kernel = cl::Kernel(program, "ethash_hash"); |
||||
m_search_kernel = cl::Kernel(program, "ethash_search"); |
||||
|
||||
// create buffer for dag
|
||||
m_dag = cl::Buffer(m_context, CL_MEM_READ_ONLY, m_fullSize); |
||||
|
||||
// create buffer for header
|
||||
m_header = cl::Buffer(m_context, CL_MEM_READ_ONLY, 32); |
||||
|
||||
// compute dag on CPU
|
||||
{ |
||||
// if this throws then it's because we probably need to subdivide the dag uploads for compatibility
|
||||
void* dag_ptr = m_queue.enqueueMapBuffer(m_dag, true, m_opencl_1_1 ? CL_MAP_WRITE : CL_MAP_WRITE_INVALIDATE_REGION, 0, m_fullSize); |
||||
// memcpying 1GB: horrible... really. horrible. but necessary since we can't mmap *and* gpumap.
|
||||
_fillDAG(dag_ptr); |
||||
m_queue.enqueueUnmapMemObject(m_dag, dag_ptr); |
||||
} |
||||
|
||||
// create mining buffers
|
||||
for (unsigned i = 0; i != c_num_buffers; ++i) |
||||
{ |
||||
m_hash_buf[i] = cl::Buffer(m_context, CL_MEM_WRITE_ONLY | (!m_opencl_1_1 ? CL_MEM_HOST_READ_ONLY : 0), 32*c_hash_batch_size); |
||||
m_search_buf[i] = cl::Buffer(m_context, CL_MEM_WRITE_ONLY, (c_max_search_results + 1) * sizeof(uint32_t)); |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
void ethash_cl_miner::hash(uint8_t* ret, uint8_t const* header, uint64_t nonce, unsigned count) |
||||
{ |
||||
struct pending_batch |
||||
{ |
||||
unsigned base; |
||||
unsigned count; |
||||
unsigned buf; |
||||
}; |
||||
std::queue<pending_batch> pending; |
||||
|
||||
// update header constant buffer
|
||||
m_queue.enqueueWriteBuffer(m_header, true, 0, 32, header); |
||||
|
||||
/*
|
||||
__kernel void ethash_combined_hash( |
||||
__global hash32_t* g_hashes, |
||||
__constant hash32_t const* g_header, |
||||
__global hash128_t const* g_dag, |
||||
ulong start_nonce, |
||||
uint isolate |
||||
) |
||||
*/ |
||||
m_hash_kernel.setArg(1, m_header); |
||||
m_hash_kernel.setArg(2, m_dag); |
||||
m_hash_kernel.setArg(3, nonce); |
||||
m_hash_kernel.setArg(4, ~0u); // have to pass this to stop the compile unrolling the loop
|
||||
|
||||
unsigned buf = 0; |
||||
for (unsigned i = 0; i < count || !pending.empty(); ) |
||||
{ |
||||
// how many this batch
|
||||
if (i < count) |
||||
{ |
||||
unsigned const this_count = std::min<unsigned>(count - i, c_hash_batch_size); |
||||
unsigned const batch_count = std::max<unsigned>(this_count, m_workgroup_size); |
||||
|
||||
// supply output hash buffer to kernel
|
||||
m_hash_kernel.setArg(0, m_hash_buf[buf]); |
||||
|
||||
// execute it!
|
||||
m_queue.enqueueNDRangeKernel( |
||||
m_hash_kernel, |
||||
cl::NullRange, |
||||
cl::NDRange(batch_count), |
||||
cl::NDRange(m_workgroup_size) |
||||
); |
||||
m_queue.flush(); |
||||
|
||||
pending.push({i, this_count, buf}); |
||||
i += this_count; |
||||
buf = (buf + 1) % c_num_buffers; |
||||
} |
||||
|
||||
// read results
|
||||
if (i == count || pending.size() == c_num_buffers) |
||||
{ |
||||
pending_batch const& batch = pending.front(); |
||||
|
||||
// could use pinned host pointer instead, but this path isn't that important.
|
||||
uint8_t* hashes = (uint8_t*)m_queue.enqueueMapBuffer(m_hash_buf[batch.buf], true, CL_MAP_READ, 0, batch.count * ETHASH_BYTES); |
||||
memcpy(ret + batch.base*ETHASH_BYTES, hashes, batch.count*ETHASH_BYTES); |
||||
m_queue.enqueueUnmapMemObject(m_hash_buf[batch.buf], hashes); |
||||
|
||||
pending.pop(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook& hook) |
||||
{ |
||||
struct pending_batch |
||||
{ |
||||
uint64_t start_nonce; |
||||
unsigned buf; |
||||
}; |
||||
std::queue<pending_batch> pending; |
||||
|
||||
static uint32_t const c_zero = 0; |
||||
|
||||
// update header constant buffer
|
||||
m_queue.enqueueWriteBuffer(m_header, false, 0, 32, header); |
||||
for (unsigned i = 0; i != c_num_buffers; ++i) |
||||
{ |
||||
m_queue.enqueueWriteBuffer(m_search_buf[i], false, 0, 4, &c_zero); |
||||
} |
||||
|
||||
#if CL_VERSION_1_2 && 0 |
||||
cl::Event pre_return_event; |
||||
if (!m_opencl_1_1) |
||||
{ |
||||
m_queue.enqueueBarrierWithWaitList(NULL, &pre_return_event); |
||||
} |
||||
else |
||||
#endif |
||||
{ |
||||
m_queue.finish(); |
||||
} |
||||
|
||||
/*
|
||||
__kernel void ethash_combined_search( |
||||
__global hash32_t* g_hashes, // 0
|
||||
__constant hash32_t const* g_header, // 1
|
||||
__global hash128_t const* g_dag, // 2
|
||||
ulong start_nonce, // 3
|
||||
ulong target, // 4
|
||||
uint isolate // 5
|
||||
) |
||||
*/ |
||||
m_search_kernel.setArg(1, m_header); |
||||
m_search_kernel.setArg(2, m_dag); |
||||
|
||||
// pass these to stop the compiler unrolling the loops
|
||||
m_search_kernel.setArg(4, target); |
||||
m_search_kernel.setArg(5, ~0u); |
||||
|
||||
|
||||
unsigned buf = 0; |
||||
for (uint64_t start_nonce = 0; ; start_nonce += c_search_batch_size) |
||||
{ |
||||
// supply output buffer to kernel
|
||||
m_search_kernel.setArg(0, m_search_buf[buf]); |
||||
m_search_kernel.setArg(3, start_nonce); |
||||
|
||||
// execute it!
|
||||
m_queue.enqueueNDRangeKernel(m_search_kernel, cl::NullRange, c_search_batch_size, m_workgroup_size); |
||||
|
||||
pending.push({start_nonce, buf}); |
||||
buf = (buf + 1) % c_num_buffers; |
||||
|
||||
// read results
|
||||
if (pending.size() == c_num_buffers) |
||||
{ |
||||
pending_batch const& batch = pending.front(); |
||||
|
||||
// could use pinned host pointer instead
|
||||
uint32_t* results = (uint32_t*)m_queue.enqueueMapBuffer(m_search_buf[batch.buf], true, CL_MAP_READ, 0, (1+c_max_search_results) * sizeof(uint32_t)); |
||||
unsigned num_found = std::min<unsigned>(results[0], c_max_search_results); |
||||
|
||||
uint64_t nonces[c_max_search_results]; |
||||
for (unsigned i = 0; i != num_found; ++i) |
||||
{ |
||||
nonces[i] = batch.start_nonce + results[i+1]; |
||||
} |
||||
|
||||
m_queue.enqueueUnmapMemObject(m_search_buf[batch.buf], results); |
||||
|
||||
bool exit = num_found && hook.found(nonces, num_found); |
||||
exit |= hook.searched(batch.start_nonce, c_search_batch_size); // always report searched before exit
|
||||
if (exit) |
||||
break; |
||||
|
||||
// reset search buffer if we're still going
|
||||
if (num_found) |
||||
m_queue.enqueueWriteBuffer(m_search_buf[batch.buf], true, 0, 4, &c_zero); |
||||
|
||||
pending.pop(); |
||||
} |
||||
} |
||||
|
||||
// not safe to return until this is ready
|
||||
#if CL_VERSION_1_2 && 0 |
||||
if (!m_opencl_1_1) |
||||
{ |
||||
pre_return_event.wait(); |
||||
} |
||||
#endif |
||||
} |
||||
|
57
Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner.h
generated
vendored
@ -1,57 +0,0 @@ |
||||
#pragma once |
||||
|
||||
#define __CL_ENABLE_EXCEPTIONS |
||||
#define CL_USE_DEPRECATED_OPENCL_2_0_APIS |
||||
|
||||
#if defined(__clang__) |
||||
#pragma clang diagnostic push |
||||
#pragma clang diagnostic ignored "-Wunused-parameter" |
||||
#include "cl.hpp" |
||||
#pragma clang diagnostic pop |
||||
#else |
||||
#include "cl.hpp" |
||||
#endif |
||||
|
||||
#include <time.h> |
||||
#include <functional> |
||||
#include <libethash/ethash.h> |
||||
|
||||
class ethash_cl_miner |
||||
{ |
||||
public: |
||||
struct search_hook |
||||
{ |
||||
virtual ~search_hook(); // always a virtual destructor for a class with virtuals.
|
||||
|
||||
// reports progress, return true to abort
|
||||
virtual bool found(uint64_t const* nonces, uint32_t count) = 0; |
||||
virtual bool searched(uint64_t start_nonce, uint32_t count) = 0; |
||||
}; |
||||
|
||||
public: |
||||
ethash_cl_miner(); |
||||
|
||||
bool init(uint64_t block_number, std::function<void(void*)> _fillDAG, unsigned workgroup_size = 64, unsigned _platformId = 0, unsigned _deviceId = 0); |
||||
static std::string platform_info(unsigned _platformId = 0, unsigned _deviceId = 0); |
||||
static unsigned get_num_devices(unsigned _platformId = 0); |
||||
|
||||
|
||||
void finish(); |
||||
void hash(uint8_t* ret, uint8_t const* header, uint64_t nonce, unsigned count); |
||||
void search(uint8_t const* header, uint64_t target, search_hook& hook); |
||||
|
||||
private: |
||||
enum { c_max_search_results = 63, c_num_buffers = 2, c_hash_batch_size = 1024, c_search_batch_size = 1024*256 }; |
||||
|
||||
uint64_t m_fullSize; |
||||
cl::Context m_context; |
||||
cl::CommandQueue m_queue; |
||||
cl::Kernel m_hash_kernel; |
||||
cl::Kernel m_search_kernel; |
||||
cl::Buffer m_dag; |
||||
cl::Buffer m_header; |
||||
cl::Buffer m_hash_buf[c_num_buffers]; |
||||
cl::Buffer m_search_buf[c_num_buffers]; |
||||
unsigned m_workgroup_size; |
||||
bool m_opencl_1_1; |
||||
}; |
460
Godeps/_workspace/src/github.com/ethereum/ethash/src/libethash-cl/ethash_cl_miner_kernel.cl
generated
vendored
@ -1,460 +0,0 @@ |
||||
// author Tim Hughes <tim@twistedfury.com> |
||||
// Tested on Radeon HD 7850 |
||||
// Hashrate: 15940347 hashes/s |
||||
// Bandwidth: 124533 MB/s |
||||
// search kernel should fit in <= 84 VGPRS (3 wavefronts) |
||||
|
||||
#define THREADS_PER_HASH (128 / 16) |
||||
#define HASHES_PER_LOOP (GROUP_SIZE / THREADS_PER_HASH) |
||||
|
||||
#define FNV_PRIME 0x01000193 |
||||
|
||||
__constant uint2 const Keccak_f1600_RC[24] = { |
||||
(uint2)(0x00000001, 0x00000000), |
||||
(uint2)(0x00008082, 0x00000000), |
||||
(uint2)(0x0000808a, 0x80000000), |
||||
(uint2)(0x80008000, 0x80000000), |
||||
(uint2)(0x0000808b, 0x00000000), |
||||
(uint2)(0x80000001, 0x00000000), |
||||
(uint2)(0x80008081, 0x80000000), |
||||
(uint2)(0x00008009, 0x80000000), |
||||
(uint2)(0x0000008a, 0x00000000), |
||||
(uint2)(0x00000088, 0x00000000), |
||||
(uint2)(0x80008009, 0x00000000), |
||||
(uint2)(0x8000000a, 0x00000000), |
||||
(uint2)(0x8000808b, 0x00000000), |
||||
(uint2)(0x0000008b, 0x80000000), |
||||
(uint2)(0x00008089, 0x80000000), |
||||
(uint2)(0x00008003, 0x80000000), |
||||
(uint2)(0x00008002, 0x80000000), |
||||
(uint2)(0x00000080, 0x80000000), |
||||
(uint2)(0x0000800a, 0x00000000), |
||||
(uint2)(0x8000000a, 0x80000000), |
||||
(uint2)(0x80008081, 0x80000000), |
||||
(uint2)(0x00008080, 0x80000000), |
||||
(uint2)(0x80000001, 0x00000000), |
||||
(uint2)(0x80008008, 0x80000000), |
||||
}; |
||||
|
||||
void keccak_f1600_round(uint2* a, uint r, uint out_size) |
||||
{ |
||||
#if !__ENDIAN_LITTLE__ |
||||
for (uint i = 0; i != 25; ++i) |
||||
a[i] = a[i].yx; |
||||
#endif |
||||
|
||||
uint2 b[25]; |
||||
uint2 t; |
||||
|
||||
// Theta |
||||
b[0] = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]; |
||||
b[1] = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]; |
||||
b[2] = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]; |
||||
b[3] = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]; |
||||
b[4] = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]; |
||||
t = b[4] ^ (uint2)(b[1].x << 1 | b[1].y >> 31, b[1].y << 1 | b[1].x >> 31); |
||||
a[0] ^= t; |
||||
a[5] ^= t; |
||||
a[10] ^= t; |
||||
a[15] ^= t; |
||||
a[20] ^= t; |
||||
t = b[0] ^ (uint2)(b[2].x << 1 | b[2].y >> 31, b[2].y << 1 | b[2].x >> 31); |
||||
a[1] ^= t; |
||||
a[6] ^= t; |
||||
a[11] ^= t; |
||||
a[16] ^= t; |
||||
a[21] ^= t; |
||||
t = b[1] ^ (uint2)(b[3].x << 1 | b[3].y >> 31, b[3].y << 1 | b[3].x >> 31); |
||||
a[2] ^= t; |
||||
a[7] ^= t; |
||||
a[12] ^= t; |
||||
a[17] ^= t; |
||||
a[22] ^= t; |
||||
t = b[2] ^ (uint2)(b[4].x << 1 | b[4].y >> 31, b[4].y << 1 | b[4].x >> 31); |
||||
a[3] ^= t; |
||||
a[8] ^= t; |
||||
a[13] ^= t; |
||||
a[18] ^= t; |
||||
a[23] ^= t; |
||||
t = b[3] ^ (uint2)(b[0].x << 1 | b[0].y >> 31, b[0].y << 1 | b[0].x >> 31); |
||||
a[4] ^= t; |
||||
a[9] ^= t; |
||||
a[14] ^= t; |
||||
a[19] ^= t; |
||||
a[24] ^= t; |
||||
|
||||
// Rho Pi |
||||
b[0] = a[0]; |
||||
b[10] = (uint2)(a[1].x << 1 | a[1].y >> 31, a[1].y << 1 | a[1].x >> 31); |
||||
b[7] = (uint2)(a[10].x << 3 | a[10].y >> 29, a[10].y << 3 | a[10].x >> 29); |
||||
b[11] = (uint2)(a[7].x << 6 | a[7].y >> 26, a[7].y << 6 | a[7].x >> 26); |
||||
b[17] = (uint2)(a[11].x << 10 | a[11].y >> 22, a[11].y << 10 | a[11].x >> 22); |
||||
b[18] = (uint2)(a[17].x << 15 | a[17].y >> 17, a[17].y << 15 | a[17].x >> 17); |
||||
b[3] = (uint2)(a[18].x << 21 | a[18].y >> 11, a[18].y << 21 | a[18].x >> 11); |
||||
b[5] = (uint2)(a[3].x << 28 | a[3].y >> 4, a[3].y << 28 | a[3].x >> 4); |
||||
b[16] = (uint2)(a[5].y << 4 | a[5].x >> 28, a[5].x << 4 | a[5].y >> 28); |
||||
b[8] = (uint2)(a[16].y << 13 | a[16].x >> 19, a[16].x << 13 | a[16].y >> 19); |
||||
b[21] = (uint2)(a[8].y << 23 | a[8].x >> 9, a[8].x << 23 | a[8].y >> 9); |
||||
b[24] = (uint2)(a[21].x << 2 | a[21].y >> 30, a[21].y << 2 | a[21].x >> 30); |
||||
b[4] = (uint2)(a[24].x << 14 | a[24].y >> 18, a[24].y << 14 | a[24].x >> 18); |
||||
b[15] = (uint2)(a[4].x << 27 | a[4].y >> 5, a[4].y << 27 | a[4].x >> 5); |
||||
b[23] = (uint2)(a[15].y << 9 | a[15].x >> 23, a[15].x << 9 | a[15].y >> 23); |
||||
b[19] = (uint2)(a[23].y << 24 | a[23].x >> 8, a[23].x << 24 | a[23].y >> 8); |
||||
b[13] = (uint2)(a[19].x << 8 | a[19].y >> 24, a[19].y << 8 | a[19].x >> 24); |
||||
b[12] = (uint2)(a[13].x << 25 | a[13].y >> 7, a[13].y << 25 | a[13].x >> 7); |
||||
b[2] = (uint2)(a[12].y << 11 | a[12].x >> 21, a[12].x << 11 | a[12].y >> 21); |
||||
b[20] = (uint2)(a[2].y << 30 | a[2].x >> 2, a[2].x << 30 | a[2].y >> 2); |
||||
b[14] = (uint2)(a[20].x << 18 | a[20].y >> 14, a[20].y << 18 | a[20].x >> 14); |
||||
b[22] = (uint2)(a[14].y << 7 | a[14].x >> 25, a[14].x << 7 | a[14].y >> 25); |
||||
b[9] = (uint2)(a[22].y << 29 | a[22].x >> 3, a[22].x << 29 | a[22].y >> 3); |
||||
b[6] = (uint2)(a[9].x << 20 | a[9].y >> 12, a[9].y << 20 | a[9].x >> 12); |
||||
b[1] = (uint2)(a[6].y << 12 | a[6].x >> 20, a[6].x << 12 | a[6].y >> 20); |
||||
|
||||
// Chi |
||||
a[0] = bitselect(b[0] ^ b[2], b[0], b[1]); |
||||
a[1] = bitselect(b[1] ^ b[3], b[1], b[2]); |
||||
a[2] = bitselect(b[2] ^ b[4], b[2], b[3]); |
||||
a[3] = bitselect(b[3] ^ b[0], b[3], b[4]); |
||||
if (out_size >= 4) |
||||
{ |
||||
a[4] = bitselect(b[4] ^ b[1], b[4], b[0]); |
||||
a[5] = bitselect(b[5] ^ b[7], b[5], b[6]); |
||||
a[6] = bitselect(b[6] ^ b[8], b[6], b[7]); |
||||
a[7] = bitselect(b[7] ^ b[9], b[7], b[8]); |
||||
a[8] = bitselect(b[8] ^ b[5], b[8], b[9]); |
||||
if (out_size >= 8) |
||||
{ |
||||
a[9] = bitselect(b[9] ^ b[6], b[9], b[5]); |
||||
a[10] = bitselect(b[10] ^ b[12], b[10], b[11]); |
||||
a[11] = bitselect(b[11] ^ b[13], b[11], b[12]); |
||||
a[12] = bitselect(b[12] ^ b[14], b[12], b[13]); |
||||
a[13] = bitselect(b[13] ^ b[10], b[13], b[14]); |
||||
a[14] = bitselect(b[14] ^ b[11], b[14], b[10]); |
||||
a[15] = bitselect(b[15] ^ b[17], b[15], b[16]); |
||||
a[16] = bitselect(b[16] ^ b[18], b[16], b[17]); |
||||
a[17] = bitselect(b[17] ^ b[19], b[17], b[18]); |
||||
a[18] = bitselect(b[18] ^ b[15], b[18], b[19]); |
||||
a[19] = bitselect(b[19] ^ b[16], b[19], b[15]); |
||||
a[20] = bitselect(b[20] ^ b[22], b[20], b[21]); |
||||
a[21] = bitselect(b[21] ^ b[23], b[21], b[22]); |
||||
a[22] = bitselect(b[22] ^ b[24], b[22], b[23]); |
||||
a[23] = bitselect(b[23] ^ b[20], b[23], b[24]); |
||||
a[24] = bitselect(b[24] ^ b[21], b[24], b[20]); |
||||
} |
||||
} |
||||
|
||||
// Iota |
||||
a[0] ^= Keccak_f1600_RC[r]; |
||||
|
||||
#if !__ENDIAN_LITTLE__ |
||||
for (uint i = 0; i != 25; ++i) |
||||
a[i] = a[i].yx; |
||||
#endif |
||||
} |
||||
|
||||
void keccak_f1600_no_absorb(ulong* a, uint in_size, uint out_size, uint isolate) |
||||
{ |
||||
for (uint i = in_size; i != 25; ++i) |
||||
{ |
||||
a[i] = 0; |
||||
} |
||||
#if __ENDIAN_LITTLE__ |
||||
a[in_size] ^= 0x0000000000000001; |
||||
a[24-out_size*2] ^= 0x8000000000000000; |
||||
#else |
||||
a[in_size] ^= 0x0100000000000000; |
||||
a[24-out_size*2] ^= 0x0000000000000080; |
||||
#endif |
||||
|
||||
// Originally I unrolled the first and last rounds to interface |
||||
// better with surrounding code, however I haven't done this |
||||
// without causing the AMD compiler to blow up the VGPR usage. |
||||
uint r = 0; |
||||
do |
||||
{ |
||||
// This dynamic branch stops the AMD compiler unrolling the loop |
||||
// and additionally saves about 33% of the VGPRs, enough to gain another |
||||
// wavefront. Ideally we'd get 4 in flight, but 3 is the best I can |
||||
// massage out of the compiler. It doesn't really seem to matter how |
||||
// much we try and help the compiler save VGPRs because it seems to throw |
||||
// that information away, hence the implementation of keccak here |
||||
// doesn't bother. |
||||
if (isolate) |
||||
{ |
||||
keccak_f1600_round((uint2*)a, r++, 25); |
||||
} |
||||
} |
||||
while (r < 23); |
||||
|
||||
// final round optimised for digest size |
||||
keccak_f1600_round((uint2*)a, r++, out_size); |
||||
} |
||||
|
||||
#define copy(dst, src, count) for (uint i = 0; i != count; ++i) { (dst)[i] = (src)[i]; } |
||||
|
||||
#define countof(x) (sizeof(x) / sizeof(x[0])) |
||||
|
||||
uint fnv(uint x, uint y) |
||||
{ |
||||
return x * FNV_PRIME ^ y; |
||||
} |
||||
|
||||
uint4 fnv4(uint4 x, uint4 y) |
||||
{ |
||||
return x * FNV_PRIME ^ y; |
||||
} |
||||
|
||||
uint fnv_reduce(uint4 v) |
||||
{ |
||||
return fnv(fnv(fnv(v.x, v.y), v.z), v.w); |
||||
} |
||||
|
||||
typedef union |
||||
{ |
||||
ulong ulongs[32 / sizeof(ulong)]; |
||||
uint uints[32 / sizeof(uint)]; |
||||
} hash32_t; |
||||
|
||||
typedef union |
||||
{ |
||||
ulong ulongs[64 / sizeof(ulong)]; |
||||
uint4 uint4s[64 / sizeof(uint4)]; |
||||
} hash64_t; |
||||
|
||||
typedef union |
||||
{ |
||||
uint uints[128 / sizeof(uint)]; |
||||
uint4 uint4s[128 / sizeof(uint4)]; |
||||
} hash128_t; |
||||
|
||||
hash64_t init_hash(__constant hash32_t const* header, ulong nonce, uint isolate) |
||||
{ |
||||
hash64_t init; |
||||
uint const init_size = countof(init.ulongs); |
||||
uint const hash_size = countof(header->ulongs); |
||||
|
||||
// sha3_512(header .. nonce) |
||||
ulong state[25]; |
||||
copy(state, header->ulongs, hash_size); |
||||
state[hash_size] = nonce; |
||||
keccak_f1600_no_absorb(state, hash_size + 1, init_size, isolate); |
||||
|
||||
copy(init.ulongs, state, init_size); |
||||
return init; |
||||
} |
||||
|
||||
uint inner_loop(uint4 init, uint thread_id, __local uint* share, __global hash128_t const* g_dag, uint isolate) |
||||
{ |
||||
uint4 mix = init; |
||||
|
||||
// share init0 |
||||
if (thread_id == 0) |
||||
*share = mix.x; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
uint init0 = *share; |
||||
|
||||
uint a = 0; |
||||
do |
||||
{ |
||||
bool update_share = thread_id == (a/4) % THREADS_PER_HASH; |
||||
|
||||
#pragma unroll |
||||
for (uint i = 0; i != 4; ++i) |
||||
{ |
||||
if (update_share) |
||||
{ |
||||
uint m[4] = { mix.x, mix.y, mix.z, mix.w }; |
||||
*share = fnv(init0 ^ (a+i), m[i]) % DAG_SIZE; |
||||
} |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
mix = fnv4(mix, g_dag[*share].uint4s[thread_id]); |
||||
} |
||||
} |
||||
while ((a += 4) != (ACCESSES & isolate)); |
||||
|
||||
return fnv_reduce(mix); |
||||
} |
||||
|
||||
hash32_t final_hash(hash64_t const* init, hash32_t const* mix, uint isolate) |
||||
{ |
||||
ulong state[25]; |
||||
|
||||
hash32_t hash; |
||||
uint const hash_size = countof(hash.ulongs); |
||||
uint const init_size = countof(init->ulongs); |
||||
uint const mix_size = countof(mix->ulongs); |
||||
|
||||
// keccak_256(keccak_512(header..nonce) .. mix); |
||||
copy(state, init->ulongs, init_size); |
||||
copy(state + init_size, mix->ulongs, mix_size); |
||||
keccak_f1600_no_absorb(state, init_size+mix_size, hash_size, isolate); |
||||
|
||||
// copy out |
||||
copy(hash.ulongs, state, hash_size); |
||||
return hash; |
||||
} |
||||
|
||||
hash32_t compute_hash_simple( |
||||
__constant hash32_t const* g_header, |
||||
__global hash128_t const* g_dag, |
||||
ulong nonce, |
||||
uint isolate |
||||
) |
||||
{ |
||||
hash64_t init = init_hash(g_header, nonce, isolate); |
||||
|
||||
hash128_t mix; |
||||
for (uint i = 0; i != countof(mix.uint4s); ++i) |
||||
{ |
||||
mix.uint4s[i] = init.uint4s[i % countof(init.uint4s)]; |
||||
} |
||||
|
||||
uint mix_val = mix.uints[0]; |
||||
uint init0 = mix.uints[0]; |
||||
uint a = 0; |
||||
do |
||||
{ |
||||
uint pi = fnv(init0 ^ a, mix_val) % DAG_SIZE; |
||||
uint n = (a+1) % countof(mix.uints); |
||||
|
||||
#pragma unroll |
||||
for (uint i = 0; i != countof(mix.uints); ++i) |
||||
{ |
||||
mix.uints[i] = fnv(mix.uints[i], g_dag[pi].uints[i]); |
||||
mix_val = i == n ? mix.uints[i] : mix_val; |
||||
} |
||||
} |
||||
while (++a != (ACCESSES & isolate)); |
||||
|
||||
// reduce to output |
||||
hash32_t fnv_mix; |
||||
for (uint i = 0; i != countof(fnv_mix.uints); ++i) |
||||
{ |
||||
fnv_mix.uints[i] = fnv_reduce(mix.uint4s[i]); |
||||
} |
||||
|
||||
return final_hash(&init, &fnv_mix, isolate); |
||||
} |
||||
|
||||
typedef union |
||||
{ |
||||
struct |
||||
{ |
||||
hash64_t init; |
||||
uint pad; // avoid lds bank conflicts |
||||
}; |
||||
hash32_t mix; |
||||
} compute_hash_share; |
||||
|
||||
hash32_t compute_hash( |
||||
__local compute_hash_share* share, |
||||
__constant hash32_t const* g_header, |
||||
__global hash128_t const* g_dag, |
||||
ulong nonce, |
||||
uint isolate |
||||
) |
||||
{ |
||||
uint const gid = get_global_id(0); |
||||
|
||||
// Compute one init hash per work item. |
||||
hash64_t init = init_hash(g_header, nonce, isolate); |
||||
|
||||
// Threads work together in this phase in groups of 8. |
||||
uint const thread_id = gid % THREADS_PER_HASH; |
||||
uint const hash_id = (gid % GROUP_SIZE) / THREADS_PER_HASH; |
||||
|
||||
hash32_t mix; |
||||
uint i = 0; |
||||
do |
||||
{ |
||||
// share init with other threads |
||||
if (i == thread_id) |
||||
share[hash_id].init = init; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
uint4 thread_init = share[hash_id].init.uint4s[thread_id % (64 / sizeof(uint4))]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
uint thread_mix = inner_loop(thread_init, thread_id, share[hash_id].mix.uints, g_dag, isolate); |
||||
|
||||
share[hash_id].mix.uints[thread_id] = thread_mix; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
if (i == thread_id) |
||||
mix = share[hash_id].mix; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
} |
||||
while (++i != (THREADS_PER_HASH & isolate)); |
||||
|
||||
return final_hash(&init, &mix, isolate); |
||||
} |
||||
|
||||
__attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1))) |
||||
__kernel void ethash_hash_simple( |
||||
__global hash32_t* g_hashes, |
||||
__constant hash32_t const* g_header, |
||||
__global hash128_t const* g_dag, |
||||
ulong start_nonce, |
||||
uint isolate |
||||
) |
||||
{ |
||||
uint const gid = get_global_id(0); |
||||
g_hashes[gid] = compute_hash_simple(g_header, g_dag, start_nonce + gid, isolate); |
||||
} |
||||
|
||||
__attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1))) |
||||
__kernel void ethash_search_simple( |
||||
__global volatile uint* restrict g_output, |
||||
__constant hash32_t const* g_header, |
||||
__global hash128_t const* g_dag, |
||||
ulong start_nonce, |
||||
ulong target, |
||||
uint isolate |
||||
) |
||||
{ |
||||
uint const gid = get_global_id(0); |
||||
hash32_t hash = compute_hash_simple(g_header, g_dag, start_nonce + gid, isolate); |
||||
if (as_ulong(as_uchar8(hash.ulongs[0]).s76543210) < target) |
||||
{ |
||||
uint slot = min(MAX_OUTPUTS, atomic_inc(&g_output[0]) + 1); |
||||
g_output[slot] = gid; |
||||
} |
||||
} |
||||
|
||||
__attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1))) |
||||
__kernel void ethash_hash( |
||||
__global hash32_t* g_hashes, |
||||
__constant hash32_t const* g_header, |
||||
__global hash128_t const* g_dag, |
||||
ulong start_nonce, |
||||
uint isolate |
||||
) |
||||
{ |
||||
__local compute_hash_share share[HASHES_PER_LOOP]; |
||||
|
||||
uint const gid = get_global_id(0); |
||||
g_hashes[gid] = compute_hash(share, g_header, g_dag, start_nonce + gid, isolate); |
||||
} |
||||
|
||||
__attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1))) |
||||
__kernel void ethash_search( |
||||
__global volatile uint* restrict g_output, |
||||
__constant hash32_t const* g_header, |
||||
__global hash128_t const* g_dag, |
||||
ulong start_nonce, |
||||
ulong target, |
||||
uint isolate |
||||
) |
||||
{ |
||||
__local compute_hash_share share[HASHES_PER_LOOP]; |
||||
|
||||
uint const gid = get_global_id(0); |
||||
hash32_t hash = compute_hash(share, g_header, g_dag, start_nonce + gid, isolate); |
||||
|
||||
if (as_ulong(as_uchar8(hash.ulongs[0]).s76543210) < target) |
||||
{ |
||||
uint slot = min(MAX_OUTPUTS, atomic_inc(&g_output[0]) + 1); |
||||
g_output[slot] = gid; |
||||
} |
||||
} |
@ -1,9 +0,0 @@ |
||||
package main |
||||
|
||||
/* |
||||
node admin bindings |
||||
*/ |
||||
|
||||
func (js *jsre) adminBindings() { |
||||
|
||||
} |
@ -1,6 +0,0 @@ |
||||
package main |
||||
|
||||
var ( |
||||
globalRegistrar = `var GlobalRegistrar = web3.eth.contract([{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"name","outputs":[{"name":"o_name","type":"bytes32"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"content","outputs":[{"name":"","type":"bytes32"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"addr","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"subRegistrar","outputs":[{"name":"o_subRegistrar","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_newOwner","type":"address"}],"name":"transfer","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_registrar","type":"address"}],"name":"setSubRegistrar","outputs":[],"type":"function"},{"constant":false,"inputs":[],"name":"Registrar","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_a","type":"address"},{"name":"_primary","type":"bool"}],"name":"setAddress","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_content","type":"bytes32"}],"name":"setContent","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"disown","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"register","outputs":[{"name":"","type":"address"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"}],"name":"Changed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"addr","type":"address"}],"name":"PrimaryChanged","type":"event"}]);` |
||||
globalRegistrarAddr = "0xc6d9d2cd449a754c494264e1809c50e34d64562b" |
||||
) |
@ -1,431 +0,0 @@ |
||||
// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved.
|
||||
//
|
||||
// This library 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 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library 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 this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301 USA
|
||||
|
||||
package main |
||||
|
||||
import ( |
||||
"bufio" |
||||
"fmt" |
||||
"math/big" |
||||
"os" |
||||
"os/signal" |
||||
"path/filepath" |
||||
"strings" |
||||
|
||||
"encoding/json" |
||||
|
||||
"sort" |
||||
|
||||
"github.com/ethereum/go-ethereum/cmd/utils" |
||||
"github.com/ethereum/go-ethereum/common/docserver" |
||||
re "github.com/ethereum/go-ethereum/jsre" |
||||
"github.com/ethereum/go-ethereum/rpc" |
||||
"github.com/ethereum/go-ethereum/rpc/api" |
||||
"github.com/ethereum/go-ethereum/rpc/codec" |
||||
"github.com/ethereum/go-ethereum/rpc/comms" |
||||
"github.com/ethereum/go-ethereum/rpc/shared" |
||||
"github.com/peterh/liner" |
||||
"github.com/robertkrimen/otto" |
||||
) |
||||
|
||||
type prompter interface { |
||||
AppendHistory(string) |
||||
Prompt(p string) (string, error) |
||||
PasswordPrompt(p string) (string, error) |
||||
} |
||||
|
||||
type dumbterm struct{ r *bufio.Reader } |
||||
|
||||
func (r dumbterm) Prompt(p string) (string, error) { |
||||
fmt.Print(p) |
||||
line, err := r.r.ReadString('\n') |
||||
return strings.TrimSuffix(line, "\n"), err |
||||
} |
||||
|
||||
func (r dumbterm) PasswordPrompt(p string) (string, error) { |
||||
fmt.Println("!! Unsupported terminal, password will echo.") |
||||
fmt.Print(p) |
||||
input, err := bufio.NewReader(os.Stdin).ReadString('\n') |
||||
fmt.Println() |
||||
return input, err |
||||
} |
||||
|
||||
func (r dumbterm) AppendHistory(string) {} |
||||
|
||||
type jsre struct { |
||||
re *re.JSRE |
||||
wait chan *big.Int |
||||
ps1 string |
||||
atexit func() |
||||
datadir string |
||||
prompter |
||||
} |
||||
|
||||
var ( |
||||
loadedModulesMethods map[string][]string |
||||
) |
||||
|
||||
func loadAutoCompletion(js *jsre, ipcpath string) { |
||||
modules, err := js.suportedApis(ipcpath) |
||||
if err != nil { |
||||
utils.Fatalf("Unable to determine supported modules - %v", err) |
||||
} |
||||
|
||||
loadedModulesMethods = make(map[string][]string) |
||||
for module, _ := range modules { |
||||
loadedModulesMethods[module] = api.AutoCompletion[module] |
||||
} |
||||
} |
||||
|
||||
func keywordCompleter(line string) []string { |
||||
results := make([]string, 0) |
||||
|
||||
if strings.Contains(line, ".") { |
||||
elements := strings.Split(line, ".") |
||||
if len(elements) == 2 { |
||||
module := elements[0] |
||||
partialMethod := elements[1] |
||||
if methods, found := loadedModulesMethods[module]; found { |
||||
for _, method := range methods { |
||||
if strings.HasPrefix(method, partialMethod) { // e.g. debug.se
|
||||
results = append(results, module+"."+method) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} else { |
||||
for module, methods := range loadedModulesMethods { |
||||
if line == module { // user typed in full module name, show all methods
|
||||
for _, method := range methods { |
||||
results = append(results, module+"."+method) |
||||
} |
||||
} else if strings.HasPrefix(module, line) { // partial method name, e.g. admi
|
||||
results = append(results, module) |
||||
} |
||||
} |
||||
} |
||||
return results |
||||
} |
||||
|
||||
func apiWordCompleter(line string, pos int) (head string, completions []string, tail string) { |
||||
if len(line) == 0 { |
||||
return "", nil, "" |
||||
} |
||||
|
||||
i := 0 |
||||
for i = pos - 1; i > 0; i-- { |
||||
if line[i] == '.' || (line[i] >= 'a' && line[i] <= 'z') || (line[i] >= 'A' && line[i] <= 'Z') { |
||||
continue |
||||
} |
||||
if i >= 3 && line[i] == '3' && line[i-3] == 'w' && line[i-2] == 'e' && line[i-1] == 'b' { |
||||
continue |
||||
} |
||||
i += 1 |
||||
break |
||||
} |
||||
|
||||
begin := line[:i] |
||||
keyword := line[i:pos] |
||||
end := line[pos:] |
||||
|
||||
completionWords := keywordCompleter(keyword) |
||||
return begin, completionWords, end |
||||
} |
||||
|
||||
func newJSRE(libPath, ipcpath string) *jsre { |
||||
js := &jsre{ps1: "> "} |
||||
js.wait = make(chan *big.Int) |
||||
|
||||
// update state in separare forever blocks
|
||||
js.re = re.New(libPath) |
||||
js.apiBindings(ipcpath) |
||||
|
||||
if !liner.TerminalSupported() { |
||||
js.prompter = dumbterm{bufio.NewReader(os.Stdin)} |
||||
} else { |
||||
lr := liner.NewLiner() |
||||
js.withHistory(func(hist *os.File) { lr.ReadHistory(hist) }) |
||||
lr.SetCtrlCAborts(true) |
||||
loadAutoCompletion(js, ipcpath) |
||||
lr.SetWordCompleter(apiWordCompleter) |
||||
lr.SetTabCompletionStyle(liner.TabPrints) |
||||
js.prompter = lr |
||||
js.atexit = func() { |
||||
js.withHistory(func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) }) |
||||
lr.Close() |
||||
close(js.wait) |
||||
} |
||||
} |
||||
return js |
||||
} |
||||
|
||||
func (js *jsre) apiBindings(ipcpath string) { |
||||
ethApi := rpc.NewEthereumApi(nil) |
||||
jeth := rpc.NewJeth(ethApi, js.re, ipcpath) |
||||
|
||||
js.re.Set("jeth", struct{}{}) |
||||
t, _ := js.re.Get("jeth") |
||||
jethObj := t.Object() |
||||
jethObj.Set("send", jeth.SendIpc) |
||||
jethObj.Set("sendAsync", jeth.SendIpc) |
||||
|
||||
err := js.re.Compile("bignumber.js", re.BigNumber_JS) |
||||
if err != nil { |
||||
utils.Fatalf("Error loading bignumber.js: %v", err) |
||||
} |
||||
|
||||
err = js.re.Compile("ethereum.js", re.Web3_JS) |
||||
if err != nil { |
||||
utils.Fatalf("Error loading web3.js: %v", err) |
||||
} |
||||
|
||||
_, err = js.re.Eval("var web3 = require('web3');") |
||||
if err != nil { |
||||
utils.Fatalf("Error requiring web3: %v", err) |
||||
} |
||||
|
||||
_, err = js.re.Eval("web3.setProvider(jeth)") |
||||
if err != nil { |
||||
utils.Fatalf("Error setting web3 provider: %v", err) |
||||
} |
||||
|
||||
apis, err := js.suportedApis(ipcpath) |
||||
if err != nil { |
||||
utils.Fatalf("Unable to determine supported api's: %v", err) |
||||
} |
||||
|
||||
// load only supported API's in javascript runtime
|
||||
shortcuts := "var eth = web3.eth; " |
||||
for apiName, _ := range apis { |
||||
if apiName == api.Web3ApiName || apiName == api.EthApiName { |
||||
continue // manually mapped
|
||||
} |
||||
|
||||
if err = js.re.Compile(fmt.Sprintf("%s.js", apiName), api.Javascript(apiName)); err == nil { |
||||
shortcuts += fmt.Sprintf("var %s = web3.%s; ", apiName, apiName) |
||||
} else { |
||||
utils.Fatalf("Error loading %s.js: %v", apiName, err) |
||||
} |
||||
} |
||||
|
||||
_, err = js.re.Eval(shortcuts) |
||||
|
||||
if err != nil { |
||||
utils.Fatalf("Error setting namespaces: %v", err) |
||||
} |
||||
|
||||
js.re.Eval(globalRegistrar + "registrar = GlobalRegistrar.at(\"" + globalRegistrarAddr + "\");") |
||||
} |
||||
|
||||
var ds, _ = docserver.New("/") |
||||
|
||||
/* |
||||
func (self *jsre) ConfirmTransaction(tx string) bool { |
||||
if self.ethereum.NatSpec { |
||||
notice := natspec.GetNotice(self.xeth, tx, ds) |
||||
fmt.Println(notice) |
||||
answer, _ := self.Prompt("Confirm Transaction [y/n]") |
||||
return strings.HasPrefix(strings.Trim(answer, " "), "y") |
||||
} else { |
||||
return true |
||||
} |
||||
} |
||||
|
||||
func (self *jsre) UnlockAccount(addr []byte) bool { |
||||
fmt.Printf("Please unlock account %x.\n", addr) |
||||
pass, err := self.PasswordPrompt("Passphrase: ") |
||||
if err != nil { |
||||
return false |
||||
} |
||||
// TODO: allow retry
|
||||
if err := self.ethereum.AccountManager().Unlock(common.BytesToAddress(addr), pass); err != nil { |
||||
return false |
||||
} else { |
||||
fmt.Println("Account is now unlocked for this session.") |
||||
return true |
||||
} |
||||
} |
||||
*/ |
||||
|
||||
func (self *jsre) exec(filename string) error { |
||||
if err := self.re.Exec(filename); err != nil { |
||||
self.re.Stop(false) |
||||
return fmt.Errorf("Javascript Error: %v", err) |
||||
} |
||||
self.re.Stop(true) |
||||
return nil |
||||
} |
||||
|
||||
func (self *jsre) suportedApis(ipcpath string) (map[string]string, error) { |
||||
config := comms.IpcConfig{ |
||||
Endpoint: ipcpath, |
||||
} |
||||
|
||||
client, err := comms.NewIpcClient(config, codec.JSON) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
req := shared.Request{ |
||||
Id: 1, |
||||
Jsonrpc: "2.0", |
||||
Method: "modules", |
||||
} |
||||
|
||||
err = client.Send(req) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
res, err := client.Recv() |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
if sucRes, ok := res.(shared.SuccessResponse); ok { |
||||
data, _ := json.Marshal(sucRes.Result) |
||||
apis := make(map[string]string) |
||||
err = json.Unmarshal(data, &apis) |
||||
if err == nil { |
||||
return apis, nil |
||||
} |
||||
} |
||||
|
||||
return nil, fmt.Errorf("Unable to determine supported API's") |
||||
} |
||||
|
||||
// show summary of current geth instance
|
||||
func (self *jsre) welcome(ipcpath string) { |
||||
self.re.Eval(`console.log('instance: ' + web3.version.client);`) |
||||
self.re.Eval(`console.log(' datadir: ' + admin.datadir);`) |
||||
self.re.Eval(`console.log("coinbase: " + eth.coinbase);`) |
||||
self.re.Eval(`var lastBlockTimestamp = 1000 * eth.getBlock(eth.blockNumber).timestamp`) |
||||
self.re.Eval(`console.log("at block: " + eth.blockNumber + " (" + new Date(lastBlockTimestamp).toLocaleDateString() |
||||
+ " " + new Date(lastBlockTimestamp).toLocaleTimeString() + ")");`) |
||||
|
||||
if modules, err := self.suportedApis(ipcpath); err == nil { |
||||
loadedModules := make([]string, 0) |
||||
for api, version := range modules { |
||||
loadedModules = append(loadedModules, fmt.Sprintf("%s:%s", api, version)) |
||||
} |
||||
sort.Strings(loadedModules) |
||||
|
||||
self.re.Eval(fmt.Sprintf("var modules = '%s';", strings.Join(loadedModules, " "))) |
||||
self.re.Eval(`console.log(" modules: " + modules);`) |
||||
} |
||||
} |
||||
|
||||
func (self *jsre) interactive() { |
||||
// Read input lines.
|
||||
prompt := make(chan string) |
||||
inputln := make(chan string) |
||||
go func() { |
||||
defer close(inputln) |
||||
for { |
||||
line, err := self.Prompt(<-prompt) |
||||
if err != nil { |
||||
return |
||||
} |
||||
inputln <- line |
||||
} |
||||
}() |
||||
// Wait for Ctrl-C, too.
|
||||
sig := make(chan os.Signal, 1) |
||||
signal.Notify(sig, os.Interrupt) |
||||
|
||||
defer func() { |
||||
if self.atexit != nil { |
||||
self.atexit() |
||||
} |
||||
self.re.Stop(false) |
||||
}() |
||||
for { |
||||
prompt <- self.ps1 |
||||
select { |
||||
case <-sig: |
||||
fmt.Println("caught interrupt, exiting") |
||||
return |
||||
case input, ok := <-inputln: |
||||
if !ok || indentCount <= 0 && input == "exit" { |
||||
return |
||||
} |
||||
if input == "" { |
||||
continue |
||||
} |
||||
str += input + "\n" |
||||
self.setIndent() |
||||
if indentCount <= 0 { |
||||
hist := str[:len(str)-1] |
||||
self.AppendHistory(hist) |
||||
self.parseInput(str) |
||||
str = "" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
func (self *jsre) withHistory(op func(*os.File)) { |
||||
hist, err := os.OpenFile(filepath.Join(self.datadir, "history"), os.O_RDWR|os.O_CREATE, os.ModePerm) |
||||
if err != nil { |
||||
fmt.Printf("unable to open history file: %v\n", err) |
||||
return |
||||
} |
||||
op(hist) |
||||
hist.Close() |
||||
} |
||||
|
||||
func (self *jsre) parseInput(code string) { |
||||
defer func() { |
||||
if r := recover(); r != nil { |
||||
fmt.Println("[native] error", r) |
||||
} |
||||
}() |
||||
value, err := self.re.Run(code) |
||||
if err != nil { |
||||
if ottoErr, ok := err.(*otto.Error); ok { |
||||
fmt.Println(ottoErr.String()) |
||||
} else { |
||||
fmt.Println(err) |
||||
} |
||||
return |
||||
} |
||||
self.printValue(value) |
||||
} |
||||
|
||||
var indentCount = 0 |
||||
var str = "" |
||||
|
||||
func (self *jsre) setIndent() { |
||||
open := strings.Count(str, "{") |
||||
open += strings.Count(str, "(") |
||||
closed := strings.Count(str, "}") |
||||
closed += strings.Count(str, ")") |
||||
indentCount = open - closed |
||||
if indentCount <= 0 { |
||||
self.ps1 = "> " |
||||
} else { |
||||
self.ps1 = strings.Join(make([]string, indentCount*2), "..") |
||||
self.ps1 += " " |
||||
} |
||||
} |
||||
|
||||
func (self *jsre) printValue(v interface{}) { |
||||
val, err := self.re.PrettyPrint(v) |
||||
if err == nil { |
||||
fmt.Printf("%v", val) |
||||
} |
||||
} |
@ -1,100 +0,0 @@ |
||||
/* |
||||
This file is part of go-ethereum |
||||
|
||||
go-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. |
||||
|
||||
go-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 go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
/** |
||||
* @authors |
||||
* Jeffrey Wilcke <i@jev.io> |
||||
*/ |
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"io" |
||||
"os" |
||||
|
||||
"github.com/codegangsta/cli" |
||||
"github.com/ethereum/go-ethereum/cmd/utils" |
||||
"github.com/ethereum/go-ethereum/logger" |
||||
"github.com/mattn/go-colorable" |
||||
"github.com/mattn/go-isatty" |
||||
) |
||||
|
||||
const ( |
||||
ClientIdentifier = "Geth console" |
||||
Version = "0.9.27" |
||||
) |
||||
|
||||
var ( |
||||
gitCommit string // set via linker flag
|
||||
nodeNameVersion string |
||||
app = utils.NewApp(Version, "the ether console") |
||||
) |
||||
|
||||
func init() { |
||||
if gitCommit == "" { |
||||
nodeNameVersion = Version |
||||
} else { |
||||
nodeNameVersion = Version + "-" + gitCommit[:8] |
||||
} |
||||
|
||||
app.Action = run |
||||
app.Flags = []cli.Flag{ |
||||
utils.IPCPathFlag, |
||||
utils.VerbosityFlag, |
||||
utils.JSpathFlag, |
||||
} |
||||
|
||||
app.Before = func(ctx *cli.Context) error { |
||||
utils.SetupLogger(ctx) |
||||
return nil |
||||
} |
||||
} |
||||
|
||||
func main() { |
||||
// Wrap the standard output with a colorified stream (windows)
|
||||
if isatty.IsTerminal(os.Stdout.Fd()) { |
||||
if pr, pw, err := os.Pipe(); err == nil { |
||||
go io.Copy(colorable.NewColorableStdout(), pr) |
||||
os.Stdout = pw |
||||
} |
||||
} |
||||
|
||||
var interrupted = false |
||||
utils.RegisterInterrupt(func(os.Signal) { |
||||
interrupted = true |
||||
}) |
||||
utils.HandleInterrupt() |
||||
|
||||
if err := app.Run(os.Args); err != nil { |
||||
fmt.Fprintln(os.Stderr, "Error: ", err) |
||||
} |
||||
|
||||
// we need to run the interrupt callbacks in case gui is closed
|
||||
// this skips if we got here by actual interrupt stopping the GUI
|
||||
if !interrupted { |
||||
utils.RunInterruptCallbacks(os.Interrupt) |
||||
} |
||||
logger.Flush() |
||||
} |
||||
|
||||
func run(ctx *cli.Context) { |
||||
jspath := ctx.GlobalString(utils.JSpathFlag.Name) |
||||
ipcpath := utils.IpcSocketPath(ctx) |
||||
|
||||
repl := newJSRE(jspath, ipcpath) |
||||
repl.welcome(ipcpath) |
||||
repl.interactive() |
||||
} |
@ -1,937 +0,0 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"encoding/json" |
||||
"errors" |
||||
"fmt" |
||||
"math/big" |
||||
"strconv" |
||||
"time" |
||||
|
||||
"github.com/ethereum/ethash" |
||||
"github.com/ethereum/go-ethereum/accounts" |
||||
"github.com/ethereum/go-ethereum/cmd/utils" |
||||
"github.com/ethereum/go-ethereum/common" |
||||
"github.com/ethereum/go-ethereum/common/compiler" |
||||
"github.com/ethereum/go-ethereum/common/natspec" |
||||
"github.com/ethereum/go-ethereum/common/resolver" |
||||
"github.com/ethereum/go-ethereum/core/state" |
||||
"github.com/ethereum/go-ethereum/core/types" |
||||
"github.com/ethereum/go-ethereum/core/vm" |
||||
"github.com/ethereum/go-ethereum/crypto" |
||||
"github.com/ethereum/go-ethereum/logger/glog" |
||||
"github.com/ethereum/go-ethereum/rlp" |
||||
"github.com/ethereum/go-ethereum/rpc" |
||||
"github.com/ethereum/go-ethereum/xeth" |
||||
"github.com/robertkrimen/otto" |
||||
"gopkg.in/fatih/set.v0" |
||||
) |
||||
|
||||
/* |
||||
node admin bindings |
||||
*/ |
||||
|
||||
func (js *jsre) adminBindings() { |
||||
ethO, _ := js.re.Get("eth") |
||||
eth := ethO.Object() |
||||
eth.Set("pendingTransactions", js.pendingTransactions) |
||||
eth.Set("resend", js.resend) |
||||
eth.Set("sign", js.sign) |
||||
|
||||
js.re.Set("admin", struct{}{}) |
||||
t, _ := js.re.Get("admin") |
||||
admin := t.Object() |
||||
admin.Set("addPeer", js.addPeer) |
||||
admin.Set("startRPC", js.startRPC) |
||||
admin.Set("stopRPC", js.stopRPC) |
||||
admin.Set("nodeInfo", js.nodeInfo) |
||||
admin.Set("peers", js.peers) |
||||
admin.Set("newAccount", js.newAccount) |
||||
admin.Set("unlock", js.unlock) |
||||
admin.Set("import", js.importChain) |
||||
admin.Set("export", js.exportChain) |
||||
admin.Set("verbosity", js.verbosity) |
||||
admin.Set("progress", js.syncProgress) |
||||
admin.Set("setSolc", js.setSolc) |
||||
|
||||
admin.Set("contractInfo", struct{}{}) |
||||
t, _ = admin.Get("contractInfo") |
||||
cinfo := t.Object() |
||||
// newRegistry officially not documented temporary option
|
||||
cinfo.Set("start", js.startNatSpec) |
||||
cinfo.Set("stop", js.stopNatSpec) |
||||
cinfo.Set("newRegistry", js.newRegistry) |
||||
cinfo.Set("get", js.getContractInfo) |
||||
cinfo.Set("register", js.register) |
||||
cinfo.Set("registerUrl", js.registerUrl) |
||||
// cinfo.Set("verify", js.verify)
|
||||
|
||||
admin.Set("miner", struct{}{}) |
||||
t, _ = admin.Get("miner") |
||||
miner := t.Object() |
||||
miner.Set("start", js.startMining) |
||||
miner.Set("stop", js.stopMining) |
||||
miner.Set("hashrate", js.hashrate) |
||||
miner.Set("setExtra", js.setExtra) |
||||
miner.Set("setGasPrice", js.setGasPrice) |
||||
miner.Set("startAutoDAG", js.startAutoDAG) |
||||
miner.Set("stopAutoDAG", js.stopAutoDAG) |
||||
miner.Set("makeDAG", js.makeDAG) |
||||
|
||||
admin.Set("txPool", struct{}{}) |
||||
t, _ = admin.Get("txPool") |
||||
txPool := t.Object() |
||||
txPool.Set("pending", js.allPendingTransactions) |
||||
txPool.Set("queued", js.allQueuedTransactions) |
||||
|
||||
admin.Set("debug", struct{}{}) |
||||
t, _ = admin.Get("debug") |
||||
debug := t.Object() |
||||
js.re.Set("sleep", js.sleep) |
||||
debug.Set("backtrace", js.backtrace) |
||||
debug.Set("printBlock", js.printBlock) |
||||
debug.Set("dumpBlock", js.dumpBlock) |
||||
debug.Set("getBlockRlp", js.getBlockRlp) |
||||
debug.Set("setHead", js.setHead) |
||||
debug.Set("processBlock", js.debugBlock) |
||||
debug.Set("seedhash", js.seedHash) |
||||
debug.Set("insertBlock", js.insertBlockRlp) |
||||
// undocumented temporary
|
||||
debug.Set("waitForBlocks", js.waitForBlocks) |
||||
} |
||||
|
||||
// generic helper to getBlock by Number/Height or Hex depending on autodetected input
|
||||
// if argument is missing the current block is returned
|
||||
// if block is not found or there is problem with decoding
|
||||
// the appropriate value is returned and block is guaranteed to be nil
|
||||
func (js *jsre) getBlock(call otto.FunctionCall) (*types.Block, error) { |
||||
var block *types.Block |
||||
if len(call.ArgumentList) > 0 { |
||||
if call.Argument(0).IsNumber() { |
||||
num, _ := call.Argument(0).ToInteger() |
||||
block = js.ethereum.ChainManager().GetBlockByNumber(uint64(num)) |
||||
} else if call.Argument(0).IsString() { |
||||
hash, _ := call.Argument(0).ToString() |
||||
block = js.ethereum.ChainManager().GetBlock(common.HexToHash(hash)) |
||||
} else { |
||||
return nil, errors.New("invalid argument for dump. Either hex string or number") |
||||
} |
||||
} else { |
||||
block = js.ethereum.ChainManager().CurrentBlock() |
||||
} |
||||
|
||||
if block == nil { |
||||
return nil, errors.New("block not found") |
||||
} |
||||
return block, nil |
||||
} |
||||
|
||||
func (js *jsre) seedHash(call otto.FunctionCall) otto.Value { |
||||
if len(call.ArgumentList) > 0 { |
||||
if call.Argument(0).IsNumber() { |
||||
num, _ := call.Argument(0).ToInteger() |
||||
hash, err := ethash.GetSeedHash(uint64(num)) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
v, _ := call.Otto.ToValue(fmt.Sprintf("0x%x", hash)) |
||||
return v |
||||
} else { |
||||
fmt.Println("arg not a number") |
||||
} |
||||
} else { |
||||
fmt.Println("requires number argument") |
||||
} |
||||
|
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
func (js *jsre) allPendingTransactions(call otto.FunctionCall) otto.Value { |
||||
txs := js.ethereum.TxPool().GetTransactions() |
||||
|
||||
ltxs := make([]*tx, len(txs)) |
||||
for i, tx := range txs { |
||||
// no need to check err
|
||||
ltxs[i] = newTx(tx) |
||||
} |
||||
|
||||
v, _ := call.Otto.ToValue(ltxs) |
||||
return v |
||||
} |
||||
|
||||
func (js *jsre) allQueuedTransactions(call otto.FunctionCall) otto.Value { |
||||
txs := js.ethereum.TxPool().GetQueuedTransactions() |
||||
|
||||
ltxs := make([]*tx, len(txs)) |
||||
for i, tx := range txs { |
||||
// no need to check err
|
||||
ltxs[i] = newTx(tx) |
||||
} |
||||
|
||||
v, _ := call.Otto.ToValue(ltxs) |
||||
return v |
||||
} |
||||
|
||||
func (js *jsre) pendingTransactions(call otto.FunctionCall) otto.Value { |
||||
txs := js.ethereum.TxPool().GetTransactions() |
||||
|
||||
// grab the accounts from the account manager. This will help with determening which
|
||||
// transactions should be returned.
|
||||
accounts, err := js.ethereum.AccountManager().Accounts() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
// Add the accouns to a new set
|
||||
accountSet := set.New() |
||||
for _, account := range accounts { |
||||
accountSet.Add(account.Address) |
||||
} |
||||
|
||||
//ltxs := make([]*tx, len(txs))
|
||||
var ltxs []*tx |
||||
for _, tx := range txs { |
||||
if from, _ := tx.From(); accountSet.Has(from) { |
||||
ltxs = append(ltxs, newTx(tx)) |
||||
} |
||||
} |
||||
|
||||
v, _ := call.Otto.ToValue(ltxs) |
||||
return v |
||||
} |
||||
|
||||
func (js *jsre) resend(call otto.FunctionCall) otto.Value { |
||||
if len(call.ArgumentList) == 0 { |
||||
fmt.Println("first argument must be a transaction") |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
v, err := call.Argument(0).Export() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
if tx, ok := v.(*tx); ok { |
||||
gl, gp := tx.GasLimit, tx.GasPrice |
||||
if len(call.ArgumentList) > 1 { |
||||
gp = call.Argument(1).String() |
||||
} |
||||
if len(call.ArgumentList) > 2 { |
||||
gl = call.Argument(2).String() |
||||
} |
||||
|
||||
ret, err := js.xeth.Transact(tx.From, tx.To, tx.Nonce, tx.Value, gl, gp, tx.Data) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
js.ethereum.TxPool().RemoveTransactions(types.Transactions{tx.tx}) |
||||
|
||||
v, _ := call.Otto.ToValue(ret) |
||||
return v |
||||
} |
||||
|
||||
fmt.Println("first argument must be a transaction") |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
func (js *jsre) sign(call otto.FunctionCall) otto.Value { |
||||
if len(call.ArgumentList) != 2 { |
||||
fmt.Println("requires 2 arguments: eth.sign(signer, data)") |
||||
return otto.UndefinedValue() |
||||
} |
||||
signer, err := call.Argument(0).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
data, err := call.Argument(1).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
signed, err := js.xeth.Sign(signer, data, false) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
v, _ := call.Otto.ToValue(signed) |
||||
return v |
||||
} |
||||
|
||||
func (js *jsre) debugBlock(call otto.FunctionCall) otto.Value { |
||||
block, err := js.getBlock(call) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
tstart := time.Now() |
||||
old := vm.Debug |
||||
|
||||
if len(call.ArgumentList) > 1 { |
||||
vm.Debug, _ = call.Argument(1).ToBoolean() |
||||
} |
||||
|
||||
_, err = js.ethereum.BlockProcessor().RetryProcess(block) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
r, _ := call.Otto.ToValue(map[string]interface{}{"success": false, "time": time.Since(tstart).Seconds()}) |
||||
return r |
||||
} |
||||
vm.Debug = old |
||||
|
||||
r, _ := call.Otto.ToValue(map[string]interface{}{"success": true, "time": time.Since(tstart).Seconds()}) |
||||
return r |
||||
} |
||||
|
||||
func (js *jsre) insertBlockRlp(call otto.FunctionCall) otto.Value { |
||||
tstart := time.Now() |
||||
|
||||
var block types.Block |
||||
if call.Argument(0).IsString() { |
||||
blockRlp, _ := call.Argument(0).ToString() |
||||
err := rlp.DecodeBytes(common.Hex2Bytes(blockRlp), &block) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
} |
||||
|
||||
old := vm.Debug |
||||
vm.Debug = true |
||||
_, err := js.ethereum.BlockProcessor().RetryProcess(&block) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
r, _ := call.Otto.ToValue(map[string]interface{}{"success": false, "time": time.Since(tstart).Seconds()}) |
||||
return r |
||||
} |
||||
vm.Debug = old |
||||
|
||||
r, _ := call.Otto.ToValue(map[string]interface{}{"success": true, "time": time.Since(tstart).Seconds()}) |
||||
return r |
||||
} |
||||
|
||||
func (js *jsre) setHead(call otto.FunctionCall) otto.Value { |
||||
block, err := js.getBlock(call) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
js.ethereum.ChainManager().SetHead(block) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
func (js *jsre) syncProgress(call otto.FunctionCall) otto.Value { |
||||
pending, cached, importing, eta := js.ethereum.Downloader().Stats() |
||||
v, _ := call.Otto.ToValue(map[string]interface{}{ |
||||
"pending": pending, |
||||
"cached": cached, |
||||
"importing": importing, |
||||
"estimate": (eta / time.Second * time.Second).String(), |
||||
}) |
||||
return v |
||||
} |
||||
|
||||
func (js *jsre) getBlockRlp(call otto.FunctionCall) otto.Value { |
||||
block, err := js.getBlock(call) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
encoded, _ := rlp.EncodeToBytes(block) |
||||
v, _ := call.Otto.ToValue(fmt.Sprintf("%x", encoded)) |
||||
return v |
||||
} |
||||
|
||||
func (js *jsre) setExtra(call otto.FunctionCall) otto.Value { |
||||
extra, err := call.Argument(0).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
if len(extra) > 1024 { |
||||
fmt.Println("error: cannot exceed 1024 bytes") |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
js.ethereum.Miner().SetExtra([]byte(extra)) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
func (js *jsre) setGasPrice(call otto.FunctionCall) otto.Value { |
||||
gasPrice, err := call.Argument(0).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
js.ethereum.Miner().SetGasPrice(common.String2Big(gasPrice)) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
func (js *jsre) hashrate(call otto.FunctionCall) otto.Value { |
||||
v, _ := call.Otto.ToValue(js.ethereum.Miner().HashRate()) |
||||
return v |
||||
} |
||||
|
||||
func (js *jsre) makeDAG(call otto.FunctionCall) otto.Value { |
||||
blockNumber, err := call.Argument(1).ToInteger() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
err = ethash.MakeDAG(uint64(blockNumber), "") |
||||
if err != nil { |
||||
return otto.FalseValue() |
||||
} |
||||
return otto.TrueValue() |
||||
} |
||||
|
||||
func (js *jsre) startAutoDAG(otto.FunctionCall) otto.Value { |
||||
js.ethereum.StartAutoDAG() |
||||
return otto.TrueValue() |
||||
} |
||||
|
||||
func (js *jsre) stopAutoDAG(otto.FunctionCall) otto.Value { |
||||
js.ethereum.StopAutoDAG() |
||||
return otto.TrueValue() |
||||
} |
||||
|
||||
func (js *jsre) backtrace(call otto.FunctionCall) otto.Value { |
||||
tracestr, err := call.Argument(0).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
glog.GetTraceLocation().Set(tracestr) |
||||
|
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
func (js *jsre) verbosity(call otto.FunctionCall) otto.Value { |
||||
v, err := call.Argument(0).ToInteger() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
glog.SetV(int(v)) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
func (js *jsre) startMining(call otto.FunctionCall) otto.Value { |
||||
var ( |
||||
threads int64 |
||||
err error |
||||
) |
||||
|
||||
if len(call.ArgumentList) > 0 { |
||||
threads, err = call.Argument(0).ToInteger() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
} else { |
||||
threads = int64(js.ethereum.MinerThreads) |
||||
} |
||||
|
||||
// switch on DAG autogeneration when miner starts
|
||||
js.ethereum.StartAutoDAG() |
||||
|
||||
err = js.ethereum.StartMining(int(threads)) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
return otto.TrueValue() |
||||
} |
||||
|
||||
func (js *jsre) stopMining(call otto.FunctionCall) otto.Value { |
||||
js.ethereum.StopMining() |
||||
js.ethereum.StopAutoDAG() |
||||
return otto.TrueValue() |
||||
} |
||||
|
||||
func (js *jsre) startRPC(call otto.FunctionCall) otto.Value { |
||||
addr, err := call.Argument(0).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
port, err := call.Argument(1).ToInteger() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
corsDomain := js.corsDomain |
||||
if len(call.ArgumentList) > 2 { |
||||
corsDomain, err = call.Argument(2).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
} |
||||
|
||||
config := rpc.RpcConfig{ |
||||
ListenAddress: addr, |
||||
ListenPort: uint(port), |
||||
CorsDomain: corsDomain, |
||||
} |
||||
|
||||
xeth := xeth.New(js.ethereum, nil) |
||||
err = rpc.Start(xeth, config) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
return otto.TrueValue() |
||||
} |
||||
|
||||
func (js *jsre) stopRPC(call otto.FunctionCall) otto.Value { |
||||
if rpc.Stop() == nil { |
||||
return otto.TrueValue() |
||||
} |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
func (js *jsre) addPeer(call otto.FunctionCall) otto.Value { |
||||
nodeURL, err := call.Argument(0).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
err = js.ethereum.AddPeer(nodeURL) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
return otto.TrueValue() |
||||
} |
||||
|
||||
func (js *jsre) unlock(call otto.FunctionCall) otto.Value { |
||||
addr, err := call.Argument(0).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
seconds, err := call.Argument(2).ToInteger() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
if seconds == 0 { |
||||
seconds = accounts.DefaultAccountUnlockDuration |
||||
} |
||||
|
||||
arg := call.Argument(1) |
||||
var passphrase string |
||||
if arg.IsUndefined() { |
||||
fmt.Println("Please enter a passphrase now.") |
||||
passphrase, err = utils.PromptPassword("Passphrase: ", true) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
} else { |
||||
passphrase, err = arg.ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
} |
||||
am := js.ethereum.AccountManager() |
||||
err = am.TimedUnlock(common.HexToAddress(addr), passphrase, time.Duration(seconds)*time.Second) |
||||
if err != nil { |
||||
fmt.Printf("Unlock account failed '%v'\n", err) |
||||
return otto.FalseValue() |
||||
} |
||||
return otto.TrueValue() |
||||
} |
||||
|
||||
func (js *jsre) newAccount(call otto.FunctionCall) otto.Value { |
||||
arg := call.Argument(0) |
||||
var passphrase string |
||||
if arg.IsUndefined() { |
||||
fmt.Println("The new account will be encrypted with a passphrase.") |
||||
fmt.Println("Please enter a passphrase now.") |
||||
auth, err := utils.PromptPassword("Passphrase: ", true) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
confirm, err := utils.PromptPassword("Repeat Passphrase: ", false) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
if auth != confirm { |
||||
fmt.Println("Passphrases did not match.") |
||||
return otto.FalseValue() |
||||
} |
||||
passphrase = auth |
||||
} else { |
||||
var err error |
||||
passphrase, err = arg.ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
} |
||||
acct, err := js.ethereum.AccountManager().NewAccount(passphrase) |
||||
if err != nil { |
||||
fmt.Printf("Could not create the account: %v", err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
v, _ := call.Otto.ToValue(acct.Address.Hex()) |
||||
return v |
||||
} |
||||
|
||||
func (js *jsre) nodeInfo(call otto.FunctionCall) otto.Value { |
||||
v, _ := call.Otto.ToValue(js.ethereum.NodeInfo()) |
||||
return v |
||||
} |
||||
|
||||
func (js *jsre) peers(call otto.FunctionCall) otto.Value { |
||||
v, _ := call.Otto.ToValue(js.ethereum.PeersInfo()) |
||||
return v |
||||
} |
||||
|
||||
func (js *jsre) importChain(call otto.FunctionCall) otto.Value { |
||||
if len(call.ArgumentList) == 0 { |
||||
fmt.Println("require file name. admin.importChain(filename)") |
||||
return otto.FalseValue() |
||||
} |
||||
fn, err := call.Argument(0).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
if err := utils.ImportChain(js.ethereum.ChainManager(), fn); err != nil { |
||||
fmt.Println("Import error: ", err) |
||||
return otto.FalseValue() |
||||
} |
||||
return otto.TrueValue() |
||||
} |
||||
|
||||
func (js *jsre) exportChain(call otto.FunctionCall) otto.Value { |
||||
if len(call.ArgumentList) == 0 { |
||||
fmt.Println("require file name: admin.exportChain(filename)") |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
fn, err := call.Argument(0).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
if err := utils.ExportChain(js.ethereum.ChainManager(), fn); err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
return otto.TrueValue() |
||||
} |
||||
|
||||
func (js *jsre) printBlock(call otto.FunctionCall) otto.Value { |
||||
block, err := js.getBlock(call) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
fmt.Println(block) |
||||
|
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
func (js *jsre) dumpBlock(call otto.FunctionCall) otto.Value { |
||||
block, err := js.getBlock(call) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
statedb := state.New(block.Root(), js.ethereum.StateDb()) |
||||
dump := statedb.RawDump() |
||||
v, _ := call.Otto.ToValue(dump) |
||||
return v |
||||
} |
||||
|
||||
func (js *jsre) waitForBlocks(call otto.FunctionCall) otto.Value { |
||||
if len(call.ArgumentList) > 2 { |
||||
fmt.Println("requires 0, 1 or 2 arguments: admin.debug.waitForBlock(minHeight, timeout)") |
||||
return otto.FalseValue() |
||||
} |
||||
var n, timeout int64 |
||||
var timer <-chan time.Time |
||||
var height *big.Int |
||||
var err error |
||||
args := len(call.ArgumentList) |
||||
if args == 2 { |
||||
timeout, err = call.Argument(1).ToInteger() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
timer = time.NewTimer(time.Duration(timeout) * time.Second).C |
||||
} |
||||
if args >= 1 { |
||||
n, err = call.Argument(0).ToInteger() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
height = big.NewInt(n) |
||||
} |
||||
|
||||
if args == 0 { |
||||
height = js.xeth.CurrentBlock().Number() |
||||
height.Add(height, common.Big1) |
||||
} |
||||
|
||||
wait := js.wait |
||||
js.wait <- height |
||||
select { |
||||
case <-timer: |
||||
// if times out make sure the xeth loop does not block
|
||||
go func() { |
||||
select { |
||||
case wait <- nil: |
||||
case <-wait: |
||||
} |
||||
}() |
||||
return otto.UndefinedValue() |
||||
case height = <-wait: |
||||
} |
||||
v, _ := call.Otto.ToValue(height.Uint64()) |
||||
return v |
||||
} |
||||
|
||||
func (js *jsre) sleep(call otto.FunctionCall) otto.Value { |
||||
sec, err := call.Argument(0).ToInteger() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
time.Sleep(time.Duration(sec) * time.Second) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
func (js *jsre) setSolc(call otto.FunctionCall) otto.Value { |
||||
if len(call.ArgumentList) != 1 { |
||||
fmt.Println("needs 1 argument: admin.contractInfo.setSolc(solcPath)") |
||||
return otto.FalseValue() |
||||
} |
||||
solcPath, err := call.Argument(0).ToString() |
||||
if err != nil { |
||||
return otto.FalseValue() |
||||
} |
||||
solc, err := js.xeth.SetSolc(solcPath) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
fmt.Println(solc.Info()) |
||||
return otto.TrueValue() |
||||
} |
||||
|
||||
func (js *jsre) register(call otto.FunctionCall) otto.Value { |
||||
if len(call.ArgumentList) != 4 { |
||||
fmt.Println("requires 4 arguments: admin.contractInfo.register(fromaddress, contractaddress, contract, filename)") |
||||
return otto.UndefinedValue() |
||||
} |
||||
sender, err := call.Argument(0).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
address, err := call.Argument(1).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
raw, err := call.Argument(2).Export() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
jsonraw, err := json.Marshal(raw) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
var contract compiler.Contract |
||||
err = json.Unmarshal(jsonraw, &contract) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
filename, err := call.Argument(3).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
contenthash, err := compiler.ExtractInfo(&contract, filename) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
// sender and contract address are passed as hex strings
|
||||
codeb := js.xeth.CodeAtBytes(address) |
||||
codehash := common.BytesToHash(crypto.Sha3(codeb)) |
||||
|
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
registry := resolver.New(js.xeth) |
||||
|
||||
_, err = registry.RegisterContentHash(common.HexToAddress(sender), codehash, contenthash) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
|
||||
v, _ := call.Otto.ToValue(contenthash.Hex()) |
||||
return v |
||||
} |
||||
|
||||
func (js *jsre) registerUrl(call otto.FunctionCall) otto.Value { |
||||
if len(call.ArgumentList) != 3 { |
||||
fmt.Println("requires 3 arguments: admin.contractInfo.register(fromaddress, contenthash, filename)") |
||||
return otto.FalseValue() |
||||
} |
||||
sender, err := call.Argument(0).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
contenthash, err := call.Argument(1).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
url, err := call.Argument(2).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
registry := resolver.New(js.xeth) |
||||
|
||||
_, err = registry.RegisterUrl(common.HexToAddress(sender), common.HexToHash(contenthash), url) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
return otto.TrueValue() |
||||
} |
||||
|
||||
func (js *jsre) getContractInfo(call otto.FunctionCall) otto.Value { |
||||
if len(call.ArgumentList) != 1 { |
||||
fmt.Println("requires 1 argument: admin.contractInfo.register(contractaddress)") |
||||
return otto.FalseValue() |
||||
} |
||||
addr, err := call.Argument(0).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
infoDoc, err := natspec.FetchDocsForContract(addr, js.xeth, ds) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
var info compiler.ContractInfo |
||||
err = json.Unmarshal(infoDoc, &info) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.UndefinedValue() |
||||
} |
||||
v, _ := call.Otto.ToValue(info) |
||||
return v |
||||
} |
||||
|
||||
func (js *jsre) startNatSpec(call otto.FunctionCall) otto.Value { |
||||
js.ethereum.NatSpec = true |
||||
return otto.TrueValue() |
||||
} |
||||
|
||||
func (js *jsre) stopNatSpec(call otto.FunctionCall) otto.Value { |
||||
js.ethereum.NatSpec = false |
||||
return otto.TrueValue() |
||||
} |
||||
|
||||
func (js *jsre) newRegistry(call otto.FunctionCall) otto.Value { |
||||
|
||||
if len(call.ArgumentList) != 1 { |
||||
fmt.Println("requires 1 argument: admin.contractInfo.newRegistry(adminaddress)") |
||||
return otto.FalseValue() |
||||
} |
||||
addr, err := call.Argument(0).ToString() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
registry := resolver.New(js.xeth) |
||||
err = registry.CreateContracts(common.HexToAddress(addr)) |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
return otto.FalseValue() |
||||
} |
||||
|
||||
return otto.TrueValue() |
||||
} |
||||
|
||||
// internal transaction type which will allow us to resend transactions using `eth.resend`
|
||||
type tx struct { |
||||
tx *types.Transaction |
||||
|
||||
To string |
||||
From string |
||||
Nonce string |
||||
Value string |
||||
Data string |
||||
GasLimit string |
||||
GasPrice string |
||||
} |
||||
|
||||
func newTx(t *types.Transaction) *tx { |
||||
from, _ := t.From() |
||||
var to string |
||||
if t := t.To(); t != nil { |
||||
to = t.Hex() |
||||
} |
||||
|
||||
return &tx{ |
||||
tx: t, |
||||
To: to, |
||||
From: from.Hex(), |
||||
Value: t.Amount.String(), |
||||
Nonce: strconv.Itoa(int(t.Nonce())), |
||||
Data: "0x" + common.Bytes2Hex(t.Data()), |
||||
GasLimit: t.GasLimit.String(), |
||||
GasPrice: t.GasPrice().String(), |
||||
} |
||||
} |
Before Width: | Height: | Size: 1004 B |
Before Width: | Height: | Size: 663 B |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 634 B |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 657 B |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 756 B |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 905 B |
@ -1,436 +0,0 @@ |
||||
import QtQuick 2.0 |
||||
import QtQuick.Controls 1.0; |
||||
import QtQuick.Layouts 1.0; |
||||
import QtQuick.Dialogs 1.0; |
||||
import QtQuick.Window 2.1; |
||||
import QtQuick.Controls.Styles 1.1 |
||||
import Ethereum 1.0 |
||||
|
||||
ApplicationWindow { |
||||
id: win |
||||
visible: false |
||||
title: "IceCREAM" |
||||
minimumWidth: 1280 |
||||
minimumHeight: 700 |
||||
width: 1290 |
||||
height: 750 |
||||
|
||||
property alias codeText: codeEditor.text |
||||
property alias dataText: rawDataField.text |
||||
|
||||
onClosing: { |
||||
//dbg.Stop() |
||||
} |
||||
|
||||
menuBar: MenuBar { |
||||
Menu { |
||||
title: "Edit" |
||||
MenuItem { |
||||
text: "Focus code" |
||||
shortcut: "Ctrl+1" |
||||
onTriggered: { |
||||
codeEditor.focus = true |
||||
} |
||||
} |
||||
MenuItem { |
||||
text: "Focus data" |
||||
shortcut: "Ctrl+2" |
||||
onTriggered: { |
||||
rawDataField.focus = true |
||||
} |
||||
} |
||||
|
||||
MenuItem { |
||||
text: "Command" |
||||
shortcut: "Ctrl+l" |
||||
onTriggered: { |
||||
dbgCommand.focus = true |
||||
} |
||||
} |
||||
} |
||||
|
||||
Menu { |
||||
title: "Debugger" |
||||
MenuItem { |
||||
text: "Run" |
||||
shortcut: "Ctrl+r" |
||||
onTriggered: debugCurrent() |
||||
} |
||||
|
||||
MenuItem { |
||||
text: "Stop" |
||||
onTriggered: dbp.stop() |
||||
} |
||||
|
||||
MenuSeparator {} |
||||
|
||||
MenuItem { |
||||
text: "Next" |
||||
shortcut: "Ctrl+n" |
||||
onTriggered: dbg.next() |
||||
} |
||||
|
||||
MenuItem { |
||||
text: "Continue" |
||||
shortcut: "Ctrl+g" |
||||
onTriggered: dbg.continue() |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
SplitView { |
||||
anchors.fill: parent |
||||
property var asmModel: ListModel { |
||||
id: asmModel |
||||
} |
||||
|
||||
TableView { |
||||
id: asmTableView |
||||
width: 200 |
||||
headerVisible: false |
||||
TableViewColumn{ role: "value" ; title: "" ; width: asmTableView.width - 2 } |
||||
model: asmModel |
||||
/* |
||||
alternatingRowColors: false |
||||
itemDelegate: Item { |
||||
Rectangle { |
||||
anchors.fill: parent |
||||
color: "#DDD" |
||||
Text { |
||||
anchors { |
||||
left: parent.left |
||||
right: parent.right |
||||
leftMargin: 10 |
||||
verticalCenter: parent.verticalCenter |
||||
} |
||||
color: "#333" |
||||
elide: styleData.elideMode |
||||
text: styleData.value |
||||
font.pixelSize: 11 |
||||
MouseArea { |
||||
acceptedButtons: Qt.LeftButton |
||||
anchors.fill: parent |
||||
onClicked: { |
||||
mouse.accepted = true |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
*/ |
||||
} |
||||
|
||||
Rectangle { |
||||
color: "#00000000" |
||||
anchors.left: asmTableView.right |
||||
anchors.right: parent.right |
||||
SplitView { |
||||
orientation: Qt.Vertical |
||||
anchors.fill: parent |
||||
|
||||
Rectangle { |
||||
color: "#00000000" |
||||
height: 330 |
||||
anchors.left: parent.left |
||||
anchors.right: parent.right |
||||
|
||||
TextArea { |
||||
id: codeEditor |
||||
anchors.top: parent.top |
||||
anchors.bottom: parent.bottom |
||||
anchors.left: parent.left |
||||
anchors.right: settings.left |
||||
focus: true |
||||
|
||||
/* |
||||
Timer { |
||||
id: compileTimer |
||||
interval: 500 ; running: true ; repeat: true |
||||
onTriggered: { |
||||
dbg.autoComp(codeEditor.text) |
||||
} |
||||
} |
||||
*/ |
||||
} |
||||
|
||||
Column { |
||||
id: settings |
||||
spacing: 5 |
||||
width: 300 |
||||
height: parent.height |
||||
anchors.right: parent.right |
||||
anchors.top: parent.top |
||||
anchors.bottom: parent.bottom |
||||
|
||||
Label { |
||||
text: "Arbitrary data" |
||||
} |
||||
TextArea { |
||||
id: rawDataField |
||||
anchors.left: parent.left |
||||
anchors.right: parent.right |
||||
height: 150 |
||||
} |
||||
|
||||
Label { |
||||
text: "Amount" |
||||
} |
||||
TextField { |
||||
id: txValue |
||||
width: 200 |
||||
placeholderText: "Amount" |
||||
validator: RegExpValidator { regExp: /\d*/ } |
||||
} |
||||
Label { |
||||
text: "Amount of gas" |
||||
} |
||||
TextField { |
||||
id: txGas |
||||
width: 200 |
||||
validator: RegExpValidator { regExp: /\d*/ } |
||||
text: "10000" |
||||
placeholderText: "Gas" |
||||
} |
||||
Label { |
||||
text: "Gas price" |
||||
} |
||||
TextField { |
||||
id: txGasPrice |
||||
width: 200 |
||||
placeholderText: "Gas price" |
||||
text: "1000000000000" |
||||
validator: RegExpValidator { regExp: /\d*/ } |
||||
} |
||||
} |
||||
} |
||||
|
||||
SplitView { |
||||
orientation: Qt.Vertical |
||||
id: inspectorPane |
||||
height: 500 |
||||
|
||||
SplitView { |
||||
orientation: Qt.Horizontal |
||||
height: 150 |
||||
|
||||
TableView { |
||||
id: stackTableView |
||||
property var stackModel: ListModel { |
||||
id: stackModel |
||||
} |
||||
height: parent.height |
||||
width: 300 |
||||
TableViewColumn{ role: "value" ; title: "Local VM stack" ; width: stackTableView.width - 2 } |
||||
model: stackModel |
||||
} |
||||
|
||||
TableView { |
||||
id: memoryTableView |
||||
property var memModel: ListModel { |
||||
id: memModel |
||||
} |
||||
height: parent.height |
||||
width: parent.width - stackTableView.width |
||||
TableViewColumn{ id:mnumColmn ; role: "num" ; title: "#" ; width: 50 } |
||||
TableViewColumn{ role: "value" ; title: "Memory" ; width: 650 } |
||||
model: memModel |
||||
} |
||||
} |
||||
|
||||
Rectangle { |
||||
height: 100 |
||||
width: parent.width |
||||
TableView { |
||||
id: storageTableView |
||||
property var memModel: ListModel { |
||||
id: storageModel |
||||
} |
||||
height: parent.height |
||||
width: parent.width |
||||
TableViewColumn{ id: key ; role: "key" ; title: "#" ; width: storageTableView.width / 2 - 1} |
||||
TableViewColumn{ role: "value" ; title: "Storage" ; width: storageTableView.width / 2 - 1} |
||||
model: storageModel |
||||
} |
||||
} |
||||
|
||||
Rectangle { |
||||
height: 200 |
||||
width: parent.width * 0.66 |
||||
TableView { |
||||
id: logTableView |
||||
property var logModel: ListModel { |
||||
id: logModel |
||||
} |
||||
height: parent.height |
||||
width: parent.width |
||||
TableViewColumn{ id: message ; role: "message" ; title: "log" ; width: logTableView.width - 2 } |
||||
model: logModel |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
function exec() { |
||||
dbg.execCommand(dbgCommand.text); |
||||
dbgCommand.text = ""; |
||||
} |
||||
statusBar: StatusBar { |
||||
height: 30 |
||||
|
||||
|
||||
TextField { |
||||
id: dbgCommand |
||||
y: 1 |
||||
x: asmTableView.width |
||||
width: 500 |
||||
placeholderText: "Debugger (type 'help')" |
||||
Keys.onReturnPressed: { |
||||
exec() |
||||
} |
||||
} |
||||
|
||||
RowLayout { |
||||
anchors.left: dbgCommand.right |
||||
anchors.leftMargin: 10 |
||||
spacing: 5 |
||||
y: parent.height / 2 - this.height / 2 |
||||
|
||||
Text { |
||||
objectName: "stackFrame" |
||||
font.pixelSize: 10 |
||||
text: "<b>stack ptr</b>: 0" |
||||
} |
||||
|
||||
Text { |
||||
objectName: "stackSize" |
||||
font.pixelSize: 10 |
||||
text: "<b>stack size</b>: 0" |
||||
} |
||||
|
||||
Text { |
||||
objectName: "memSize" |
||||
font.pixelSize: 10 |
||||
text: "<b>mem size</b>: 0" |
||||
} |
||||
} |
||||
} |
||||
|
||||
toolBar: ToolBar { |
||||
height: 30 |
||||
RowLayout { |
||||
spacing: 10 |
||||
|
||||
Button { |
||||
property var enabled: true |
||||
id: debugStart |
||||
onClicked: { |
||||
debugCurrent() |
||||
} |
||||
text: "Debug" |
||||
} |
||||
|
||||
Button { |
||||
property var enabled: true |
||||
id: debugNextButton |
||||
onClicked: { |
||||
dbg.next() |
||||
} |
||||
text: "Next" |
||||
} |
||||
|
||||
Button { |
||||
id: debugContinueButton |
||||
onClicked: { |
||||
dbg.continue() |
||||
} |
||||
text: "Continue" |
||||
} |
||||
} |
||||
|
||||
|
||||
ComboBox { |
||||
visible: false |
||||
id: snippets |
||||
anchors.right: parent.right |
||||
model: ListModel { |
||||
ListElement { text: "Snippets" ; value: "" } |
||||
ListElement { text: "Call Contract" ; value: "var[2] in = { \"arg1\", 0xdeadbeef };\nvar ret;\n\nvar success = call(0x0c542ddea93dae0c2fcb2cf175f03ad80d6be9a0, 0, 7000, in, ret)\n\nreturn ret" } |
||||
} |
||||
onCurrentIndexChanged: { |
||||
if(currentIndex != 0) { |
||||
var code = snippets.model.get(currentIndex).value; |
||||
codeEditor.insert(codeEditor.cursorPosition, code) |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
function debugCurrent() { |
||||
dbg.debug(txValue.text, txGas.text, txGasPrice.text, codeEditor.text, rawDataField.text) |
||||
} |
||||
|
||||
function setAsm(asm) { |
||||
asmModel.append({asm: asm}) |
||||
} |
||||
|
||||
function clearAsm() { |
||||
asmModel.clear() |
||||
} |
||||
|
||||
function setInstruction(num) { |
||||
asmTableView.selection.clear() |
||||
asmTableView.selection.select(num) |
||||
asmTableView.positionViewAtRow(num, ListView.Center) |
||||
} |
||||
|
||||
function setMem(mem) { |
||||
memModel.append({num: mem.num, value: mem.value}) |
||||
} |
||||
function clearMem(){ |
||||
memModel.clear() |
||||
} |
||||
|
||||
function setStack(stack) { |
||||
stackModel.append({value: stack}) |
||||
} |
||||
function addDebugMessage(message){ |
||||
debuggerLog.append({value: message}) |
||||
} |
||||
|
||||
function clearStack() { |
||||
stackModel.clear() |
||||
} |
||||
|
||||
function clearStorage() { |
||||
storageModel.clear() |
||||
} |
||||
|
||||
function setStorage(storage) { |
||||
storageModel.append({key: storage.key, value: storage.value}) |
||||
} |
||||
|
||||
function setLog(msg) { |
||||
// Remove first item once we've reached max log items |
||||
if(logModel.count > 250) { |
||||
logModel.remove(0) |
||||
} |
||||
|
||||
if(msg.len != 0) { |
||||
if(logTableView.flickableItem.atYEnd) { |
||||
logModel.append({message: msg}) |
||||
logTableView.positionViewAtRow(logTableView.rowCount - 1, ListView.Contain) |
||||
} else { |
||||
logModel.append({message: msg}) |
||||
} |
||||
} |
||||
} |
||||
|
||||
function clearLog() { |
||||
logModel.clear() |
||||
} |
||||
} |
@ -1,55 +0,0 @@ |
||||
<!doctype> |
||||
<html> |
||||
<head> |
||||
<title>Hello world</title> |
||||
<script src="../ext/bignumber.min.js"></script> |
||||
<script src="../ext/ethereum.js/dist/ethereum.js"></script> |
||||
<script> |
||||
var web3 = require('web3'); |
||||
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080')); |
||||
var eth = web3.eth; |
||||
var desc = [{ |
||||
"name": "multiply(uint256)", |
||||
"inputs": [{ |
||||
"name": "a", |
||||
"type": "uint256" |
||||
}], |
||||
"outputs": [{ |
||||
"name": "d", |
||||
"type": "uint256" |
||||
}] |
||||
}]; |
||||
var address = web3.eth.transact({ |
||||
data: "0x603880600c6000396000f3006001600060e060020a600035048063c6888fa114601857005b6021600435602b565b8060005260206000f35b600081600702905091905056", |
||||
gasPrice: "1000000000000000", |
||||
gas: "10000", |
||||
}); |
||||
var contract = web3.eth.contract(address, desc); |
||||
|
||||
function calculate() { |
||||
var param = parseInt(document.getElementById('value').value); |
||||
|
||||
var res = contract.call().multiply(param); |
||||
document.getElementById('result').innerText = res.toString(10); |
||||
} |
||||
</script> |
||||
</head> |
||||
<body> |
||||
<h3>Contract content</h3> |
||||
<textarea style="height:100px; width: 300px;" disabled="disabled"> |
||||
contract test { |
||||
function multiply(uint a) returns(uint d) { |
||||
return a * 7; |
||||
} |
||||
} |
||||
</textarea> |
||||
<code><pre> |
||||
603880600c6000396000f3006001600060e060020a600035048063c6888fa1140 |
||||
05b6021600435602b565b8060005260206000f35b600081600702905091905056</pre></code> |
||||
|
||||
<hr> |
||||
<div>7 x <input type="number" id="value" onkeyup='calculate()'></input> = |
||||
<span id="result"></spa> |
||||
|
||||
</body> |
||||
</html> |
@ -1,40 +0,0 @@ |
||||
<!doctype> |
||||
<html> |
||||
|
||||
<head> |
||||
<script src="../ext/bignumber.min.js"></script> |
||||
<script src="../ext/ethereum.js/dist/ethereum.js"></script> |
||||
<script type="text/javascript"> |
||||
|
||||
var web3 = require('web3'); |
||||
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080')); |
||||
|
||||
function watchBalance() { |
||||
var coinbase = web3.eth.coinbase; |
||||
var originalBalance = 0; |
||||
|
||||
var balance = web3.eth.balanceAt(coinbase); |
||||
var originalBalance = web3.toDecimal(balance); |
||||
document.getElementById('original').innerText = 'original balance: ' + originalBalance + ' watching...'; |
||||
|
||||
web3.eth.watch({altered: coinbase}).changed(function() { |
||||
balance = web3.eth.balanceAt(coinbase) |
||||
var currentBalance = web3.toDecimal(balance); |
||||
document.getElementById("current").innerText = 'current: ' + currentBalance; |
||||
document.getElementById("diff").innerText = 'diff: ' + (currentBalance - originalBalance); |
||||
}); |
||||
} |
||||
|
||||
</script> |
||||
</head> |
||||
<body> |
||||
<h1>coinbase balance</h1> |
||||
<button type="button" onClick="watchBalance();">watch balance</button> |
||||
<div></div> |
||||
<div id="original"></div> |
||||
<div id="current"></div> |
||||
<div id="diff"></div> |
||||
</body> |
||||
</html> |
||||
|
||||
|
@ -1,22 +0,0 @@ |
||||
<html> |
||||
<head> |
||||
<script src="../ext/bignumber.min.js"></script> |
||||
<script src="../ext/ethereum.js/dist/ethereum.js"></script> |
||||
|
||||
<script> |
||||
var web3 = require('web3'); |
||||
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545')); |
||||
var eth = web3.eth; |
||||
|
||||
function bomb() { |
||||
for (var i = 0; i < 200; i++) { |
||||
eth.transact({}) |
||||
} |
||||
} |
||||
</script> |
||||
</head> |
||||
|
||||
<body> |
||||
<button onclick="bomb();">BOOM!</button> |
||||
</body> |
||||
</html> |
@ -1,147 +0,0 @@ |
||||
<!doctype> |
||||
<html> |
||||
<title>JevCoin</title> |
||||
<head> |
||||
<script type="text/javascript" src="../ext/bignumber.min.js"></script> |
||||
<script type="text/javascript" src="../ext/ethereum.js/dist/web3-light.min.js"></script> |
||||
</head> |
||||
<body> |
||||
|
||||
<h1>JevCoin <code id="contract_addr"></code></h1> |
||||
<div> |
||||
<strong>Balance</strong> |
||||
<span id="balance"></strong> |
||||
</div> |
||||
|
||||
<div> |
||||
<span>Address:</span> |
||||
<input type="text" id="address" style="width:200px"> |
||||
<span>Amount:</span> |
||||
<input type="text" id="amount" style="width:200px"> |
||||
<button onclick="transact()">Send</button> |
||||
<span id="message"></span> |
||||
</div> |
||||
|
||||
<hr> |
||||
|
||||
<table width="100%" id="table"> |
||||
<tr><td style="width:40%;">Address</td><td>Balance</td></tr> |
||||
<tbody id="table_body"></tbody> |
||||
</table> |
||||
|
||||
</body> |
||||
|
||||
<script type="text/javascript"> |
||||
var eth = web3.eth; |
||||
|
||||
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')); |
||||
var desc = [{ |
||||
"name": "balance(address)", |
||||
"type": "function", |
||||
"inputs": [{ |
||||
"name": "who", |
||||
"type": "address" |
||||
}], |
||||
"constant": true, |
||||
"outputs": [{ |
||||
"name": "value", |
||||
"type": "uint256" |
||||
}] |
||||
}, { |
||||
"name": "send(address,uint256)", |
||||
"type": "function", |
||||
"inputs": [{ |
||||
"name": "to", |
||||
"type": "address" |
||||
}, { |
||||
"name": "value", |
||||
"type": "uint256" |
||||
}], |
||||
"outputs": [] |
||||
}, { |
||||
"name":"Changed", |
||||
"type":"event", |
||||
"inputs": [ |
||||
{"name":"from","type":"address","indexed":true}, |
||||
{"name":"amount","type":"uint256","indexed":true}, |
||||
], |
||||
}]; |
||||
|
||||
var address = localStorage.getItem("address"); |
||||
// deploy if not exist |
||||
if(address === null) { |
||||
var code = "0x60056013565b61014f8061003a6000396000f35b620f42406000600033600160a060020a0316815260200190815260200160002081905550560060e060020a600035048063d0679d3414610020578063e3d670d71461003457005b61002e600435602435610049565b60006000f35b61003f600435610129565b8060005260206000f35b806000600033600160a060020a03168152602001908152602001600020541061007157610076565b610125565b806000600033600160a060020a03168152602001908152602001600020908154039081905550806000600084600160a060020a031681526020019081526020016000209081540190819055508033600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a38082600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a35b5050565b60006000600083600160a060020a0316815260200190815260200160002054905091905056"; |
||||
address = web3.eth.sendTransaction({from: eth.accounts[0], data: code, gas: "1000000"}); |
||||
localStorage.setItem("address", address); |
||||
} |
||||
document.querySelector("#contract_addr").innerHTML = address; |
||||
|
||||
var Contract = web3.eth.contract(desc); |
||||
contract = new Contract(address); |
||||
var filter = contract.Changed({from: eth.accounts[0]}) |
||||
filter.watch(function(logs) { |
||||
console.log(logs); |
||||
refresh(); |
||||
}); |
||||
window.filter = filter; |
||||
|
||||
function refresh() { |
||||
document.querySelector("#balance").innerHTML = contract.balance(eth.coinbase); |
||||
} |
||||
|
||||
function transact() { |
||||
var to = document.querySelector("#address"); |
||||
if( to.value.length == 0 ) { |
||||
to = "0x4205b06c2cfa0e30359edcab94543266cb6fa1d3"; |
||||
} else { |
||||
if (to.value.substr(0,2) != "0x") |
||||
to.value = "0x"+to.value; |
||||
} |
||||
|
||||
var value = document.querySelector("#amount"); |
||||
var amount = parseInt( value.value ); |
||||
console.log("transact: ", to.value, " => ", amount) |
||||
|
||||
contract.send.sendTransaction(to.value, amount ,{from: eth.accounts[0]}); |
||||
|
||||
to.value = ""; |
||||
value.value = ""; |
||||
|
||||
var message = document.querySelector("#message") |
||||
message.innerHTML = "Submitted"; |
||||
setTimeout(function() { |
||||
message.innerHTML = ""; |
||||
}, 1000); |
||||
} |
||||
|
||||
refresh(); |
||||
</script> |
||||
</html> |
||||
|
||||
<!-- |
||||
contract JevCoin { |
||||
function JevCoin() |
||||
{ |
||||
balances[msg.sender] = 1000000; |
||||
} |
||||
|
||||
event Changed(address indexed from, uint indexed amount); |
||||
function send(address to, uint value) |
||||
{ |
||||
if( balances[msg.sender] < value ) return; |
||||
|
||||
balances[msg.sender] -= value; |
||||
balances[to] += value; |
||||
|
||||
Changed(msg.sender, value); |
||||
Changed(to, value); |
||||
} |
||||
|
||||
function balance(address who) constant returns(uint t) |
||||
{ |
||||
t = balances[who]; |
||||
} |
||||
|
||||
mapping(address => uint256) balances; |
||||
} |
||||
-!> |
@ -1,65 +0,0 @@ |
||||
var walletABI = [ |
||||
{ |
||||
"name":"confirm", |
||||
"type":"function", |
||||
"constant":false, |
||||
"inputs":[ |
||||
{"name":"_h","type":"hash256"} |
||||
], |
||||
"outputs":[] |
||||
},{ |
||||
"name":"execute", |
||||
"constant":false, |
||||
"type":"function", |
||||
"inputs":[ |
||||
{"name":"_to","type":"address"}, |
||||
{"name":"_value","type":"uint256"}, |
||||
{"name":"_data","type":"bytes"} |
||||
], |
||||
"outputs":[ |
||||
{"name":"_r","type":"hash256"} |
||||
] |
||||
},{ |
||||
"name":"kill", |
||||
"type":"function", |
||||
"constant":false, |
||||
"inputs":[ |
||||
{"name":"_to","type":"address"} |
||||
], |
||||
"outputs":[] |
||||
},{ |
||||
"name":"changeOwner", |
||||
"type":"function", |
||||
"constant":false, |
||||
"inputs":[ |
||||
{"name":"_from","type":"address"}, |
||||
{"name":"_to","type":"address"} |
||||
], |
||||
"outputs":[] |
||||
},{ |
||||
"name":"CashIn", |
||||
"type":"event", |
||||
"inputs":[ |
||||
{"indexed":false,"name":"value","type":"uint256"} |
||||
] |
||||
},{ |
||||
"name":"SingleTransact", |
||||
"type":"event", |
||||
"inputs":[ |
||||
{"indexed":true,"name":"out","type":"string32"}, |
||||
{"indexed":false,"name":"owner","type":"address"}, |
||||
{"indexed":false,"name":"value","type":"uint256"}, |
||||
{"indexed":false,"name":"to","type":"address"} |
||||
] |
||||
},{ |
||||
"name":"MultiTransact", |
||||
"type":"event", |
||||
"inputs":[ |
||||
{"indexed":true,"name":"out","type":"string32"}, |
||||
{"indexed":false,"name":"owner","type":"address"}, |
||||
{"indexed":false,"name":"operation","type":"hash256"}, |
||||
{"indexed":false,"name":"value","type":"uint256"}, |
||||
{"indexed":false,"name":"to","type":"address"} |
||||
] |
||||
} |
||||
]; |
@ -1,84 +0,0 @@ |
||||
|
||||
<!doctype> |
||||
<html> |
||||
<head> |
||||
<meta name="badge" content="10"> |
||||
<script type="text/javascript" src="../ext/bignumber.min.js"></script> |
||||
<script type="text/javascript" src="../ext/ethereum.js/dist/ethereum.js"></script> |
||||
</head> |
||||
<body> |
||||
<h1>Info</h1> |
||||
|
||||
<table width="100%"> |
||||
<tr> |
||||
<td>Block number</td> |
||||
<td id="number"></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>Peer count</td> |
||||
<td id="peer_count"></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>Default block</td> |
||||
<td id="default_block"></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>Accounts</td> |
||||
<td id="accounts"></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>Balance</td> |
||||
<td id="balance"></td> |
||||
|
||||
<tr> |
||||
<td>Gas price</td> |
||||
<td id="gas_price"></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>Mining</td> |
||||
<td id="mining"></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>Listening</td> |
||||
<td id="listening"></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>Coinbase</td> |
||||
<td id="coinbase"></td> |
||||
</tr> |
||||
</table> |
||||
</body> |
||||
|
||||
<script type="text/javascript"> |
||||
var web3 = require('web3'); |
||||
var eth = web3.eth; |
||||
|
||||
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545')); |
||||
|
||||
eth.defaultBlock = -2 |
||||
|
||||
document.querySelector("#number").innerHTML = eth.number; |
||||
document.querySelector("#coinbase").innerHTML = eth.coinbase |
||||
document.querySelector("#peer_count").innerHTML = eth.peerCount; |
||||
document.querySelector("#default_block").innerHTML = eth.defaultBlock; |
||||
document.querySelector("#accounts").innerHTML = eth.accounts; |
||||
document.querySelector("#balance").innerHTML = web3.toEth(eth.balanceAt(eth.accounts[0])); |
||||
document.querySelector("#gas_price").innerHTML = eth.gasPrice; |
||||
document.querySelector("#mining").innerHTML = eth.mining; |
||||
document.querySelector("#listening").innerHTML = eth.listening; |
||||
eth.watch('chain').changed(function() { |
||||
document.querySelector("#number").innerHTML = eth.number; |
||||
}); |
||||
|
||||
|
||||
</script> |
||||
|
||||
</html> |
||||
|
@ -1,70 +0,0 @@ |
||||
<!doctype> |
||||
<html> |
||||
<title>Whisper test</title> |
||||
<head> |
||||
<script type="text/javascript" src="../ext/bignumber.min.js"></script> |
||||
<script type="text/javascript" src="../ext/ethereum.js/dist/ethereum.js"></script> |
||||
</head> |
||||
<body> |
||||
|
||||
<h1>Whisper test</h1> |
||||
|
||||
<button onclick="test()">Send</button> |
||||
<button onclick="test2()">Private send</button> |
||||
|
||||
<table width="100%" id="table"> |
||||
<tr> |
||||
<td>Count</td> |
||||
<td id="count"></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>ID</td> |
||||
<td id="id"></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>Has identity</td> |
||||
<td id="known"></td> |
||||
</tr> |
||||
</table> |
||||
</body> |
||||
|
||||
<script type="text/javascript"> |
||||
var web3 = require('web3'); |
||||
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080')); |
||||
|
||||
var shh = web3.shh; |
||||
|
||||
var id = shh.newIdentity(); |
||||
document.querySelector("#id").innerHTML = id; |
||||
document.querySelector("#known").innerHTML = shh.haveIdentity(id); |
||||
|
||||
var watch = shh.watch({topics: ["test"]}) |
||||
watch.arrived(function(message) { |
||||
document.querySelector("#table").innerHTML += "<tr><td colspan='2'>"+JSON.stringify(message)+"</td></tr>"; |
||||
}); |
||||
|
||||
var selfWatch = shh.watch({to: id, topics: ["test"]}) |
||||
selfWatch.arrived(function(message) { |
||||
document.querySelector("#table").innerHTML += "<tr><td>To me</td><td>"+JSON.stringify(message)+"</td></tr>"; |
||||
}); |
||||
|
||||
function test() { |
||||
shh.post({topics: ["test"], payload: web3.fromAscii("test it")}); |
||||
count(); |
||||
} |
||||
|
||||
function test2() { |
||||
shh.post({to: id, topics: ["test"], payload: web3.fromAscii("Private")}); |
||||
count(); |
||||
} |
||||
|
||||
function count() { |
||||
document.querySelector("#count").innerHTML = watch.messages().length; |
||||
} |
||||
</script> |
||||
|
||||
</html> |
||||
|
||||
|
@ -1,5 +0,0 @@ |
||||
{ |
||||
"directory": "example/js/", |
||||
"cwd": "./", |
||||
"analytics": false |
||||
} |
@ -1,12 +0,0 @@ |
||||
root = true |
||||
|
||||
[*] |
||||
indent_style = space |
||||
indent_size = 4 |
||||
end_of_line = lf |
||||
charset = utf-8 |
||||
trim_trailing_whitespace = true |
||||
insert_final_newline = true |
||||
|
||||
[*.md] |
||||
trim_trailing_whitespace = false |
@ -1,18 +0,0 @@ |
||||
# See http://help.github.com/ignore-files/ for more about ignoring files. |
||||
# |
||||
# If you find yourself ignoring temporary files generated by your text editor |
||||
# or operating system, you probably want to add a global ignore instead: |
||||
# git config --global core.excludesfile ~/.gitignore_global |
||||
|
||||
*.swp |
||||
/tmp |
||||
*/**/*un~ |
||||
*un~ |
||||
.DS_Store |
||||
*/**/.DS_Store |
||||
ethereum/ethereum |
||||
ethereal/ethereal |
||||
example/js |
||||
node_modules |
||||
bower_components |
||||
npm-debug.log |
@ -1,50 +0,0 @@ |
||||
{ |
||||
"predef": [ |
||||
"console", |
||||
"require", |
||||
"equal", |
||||
"test", |
||||
"testBoth", |
||||
"testWithDefault", |
||||
"raises", |
||||
"deepEqual", |
||||
"start", |
||||
"stop", |
||||
"ok", |
||||
"strictEqual", |
||||
"module", |
||||
"expect", |
||||
"reject", |
||||
"impl" |
||||
], |
||||
|
||||
"esnext": true, |
||||
"proto": true, |
||||
"node" : true, |
||||
"browser" : true, |
||||
"browserify" : true, |
||||
|
||||
"boss" : true, |
||||
"curly": false, |
||||
"debug": true, |
||||
"devel": true, |
||||
"eqeqeq": true, |
||||
"evil": true, |
||||
"forin": false, |
||||
"immed": false, |
||||
"laxbreak": false, |
||||
"newcap": true, |
||||
"noarg": true, |
||||
"noempty": false, |
||||
"nonew": false, |
||||
"nomen": false, |
||||
"onevar": false, |
||||
"plusplus": false, |
||||
"regexp": false, |
||||
"undef": true, |
||||
"sub": true, |
||||
"strict": false, |
||||
"white": false, |
||||
"shadow": true, |
||||
"eqnull": true |
||||
} |
@ -1,9 +0,0 @@ |
||||
example/js |
||||
node_modules |
||||
test |
||||
.gitignore |
||||
.editorconfig |
||||
.travis.yml |
||||
.npmignore |
||||
component.json |
||||
testling.html |
@ -1,13 +0,0 @@ |
||||
language: node_js |
||||
node_js: |
||||
- "0.11" |
||||
- "0.10" |
||||
before_script: |
||||
- npm install |
||||
- npm install jshint |
||||
script: |
||||
- "jshint *.js lib" |
||||
after_script: |
||||
- npm run-script build |
||||
- npm test |
||||
|
@ -1 +0,0 @@ |
||||
Subproject commit 08f3aaea8cad2cf07276d6709e2ee384afe90d3c |
@ -1,66 +0,0 @@ |
||||
// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved.
|
||||
//
|
||||
// This library 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 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library 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 this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301 USA
|
||||
|
||||
var ethx = { |
||||
prototype: Object, |
||||
|
||||
watch: function(options) { |
||||
return new Filter(options); |
||||
}, |
||||
|
||||
note: function() { |
||||
var args = Array.prototype.slice.call(arguments, 0); |
||||
var o = [] |
||||
for(var i = 0; i < args.length; i++) { |
||||
o.push(args[i].toString()) |
||||
} |
||||
|
||||
eth.notef(o); |
||||
}, |
||||
}; |
||||
|
||||
var Filter = function(options) { |
||||
this.callbacks = []; |
||||
this.options = options; |
||||
|
||||
if(options === "chain") { |
||||
this.id = eth.newFilterString(options); |
||||
} else if(typeof options === "object") { |
||||
this.id = eth.newFilter(options); |
||||
} |
||||
}; |
||||
|
||||
Filter.prototype.changed = function(callback) { |
||||
this.callbacks.push(callback); |
||||
|
||||
var self = this; |
||||
messages.connect(function(messages, id) { |
||||
if(id == self.id) { |
||||
for(var i = 0; i < self.callbacks.length; i++) { |
||||
self.callbacks[i].call(self, messages); |
||||
} |
||||
} |
||||
}); |
||||
}; |
||||
|
||||
Filter.prototype.uninstall = function() { |
||||
eth.uninstallFilter(this.id) |
||||
} |
||||
|
||||
Filter.prototype.messages = function() { |
||||
return eth.messages(this.id) |
||||
} |
@ -1,30 +0,0 @@ |
||||
// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved.
|
||||
//
|
||||
// This library 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 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library 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 this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301 USA
|
||||
|
||||
// this function is included locally, but you can also include separately via a header definition
|
||||
function request(url, callback) { |
||||
var xhr = new XMLHttpRequest(); |
||||
xhr.onreadystatechange = (function(req) { |
||||
return function() { |
||||
if(req.readyState === 4) { |
||||
callback(req); |
||||
} |
||||
} |
||||
})(xhr); |
||||
xhr.open('GET', url, true); |
||||
xhr.send(''); |
||||
} |
@ -1,36 +0,0 @@ |
||||
// Copyright (c) 2015, ETHDEV. All rights reserved.
|
||||
//
|
||||
// This library 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 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library 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 this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301 USA
|
||||
|
||||
// this function is included locally, but you can also include separately via a header definition
|
||||
|
||||
|
||||
document.onkeydown = function(evt) { |
||||
// This functions keeps track of keyboard inputs in order to allow copy, paste and other features
|
||||
|
||||
evt = evt || window.event; |
||||
if (evt.ctrlKey && evt.keyCode == 67) { |
||||
window.document.execCommand("copy"); |
||||
} else if (evt.ctrlKey && evt.keyCode == 88) { |
||||
window.document.execCommand("cut"); |
||||
} else if (evt.ctrlKey && evt.keyCode == 86) { |
||||
window.document.execCommand("paste"); |
||||
} else if (evt.ctrlKey && evt.keyCode == 90) { |
||||
window.document.execCommand("undo"); |
||||
} else if (evt.ctrlKey && evt.shiftKey && evt.keyCode == 90) { |
||||
window.document.execCommand("redo"); |
||||
} |
||||
}; |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 4.2 KiB |
@ -1,83 +0,0 @@ |
||||
<!doctype> |
||||
<html> |
||||
<head> |
||||
<title>Ethereum</title> |
||||
<script type="text/javascript" src="../ext/bignumber.min.js"></script> |
||||
<script type="text/javascript" src="../ext/ethereum.js/dist/ethereum.js"></script> |
||||
<style type="text/css"> |
||||
body { |
||||
font-family: Helvetica; |
||||
} |
||||
div.logo { |
||||
width: 192px; |
||||
margin: 40px auto; |
||||
} |
||||
</style> |
||||
</head> |
||||
<body> |
||||
<div class="logo"><img src="logo.png"></img></div> |
||||
<h1>Info</h1> |
||||
|
||||
<table width="100%"> |
||||
<tr> |
||||
<td>Block number</td> |
||||
<td id="number"></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>Peer count</td> |
||||
<td id="peer_count"></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>Accounts</td> |
||||
<td id="accounts"></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>Gas price</td> |
||||
<td id="gas_price"></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>Mining</td> |
||||
<td id="mining"></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>Listening</td> |
||||
<td id="listening"></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>Coinbase</td> |
||||
<td id="coinbase"></td> |
||||
</tr> |
||||
</table> |
||||
</body> |
||||
|
||||
<script type="text/javascript"> |
||||
var web3 = require('web3'); |
||||
var eth = web3.eth; |
||||
|
||||
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545')); |
||||
|
||||
document.querySelector("#number").innerHTML = eth.number; |
||||
document.querySelector("#coinbase").innerHTML = eth.coinbase |
||||
document.querySelector("#peer_count").innerHTML = eth.peerCount; |
||||
document.querySelector("#accounts").innerHTML = eth.accounts; |
||||
document.querySelector("#gas_price").innerHTML = eth.gasPrice; |
||||
document.querySelector("#mining").innerHTML = eth.mining; |
||||
document.querySelector("#listening").innerHTML = eth.listening; |
||||
|
||||
eth.watch('pending').changed(function() { |
||||
console.log("pending changed"); |
||||
}); |
||||
eth.watch('chain').changed(function() { |
||||
document.querySelector("#number").innerHTML = eth.number; |
||||
}); |
||||
|
||||
</script> |
||||
|
||||
</html> |
||||
|
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 2.3 KiB |
@ -1,272 +0,0 @@ |
||||
/* BASICS */ |
||||
|
||||
.CodeMirror { |
||||
/* Set height, width, borders, and global font properties here */ |
||||
font-family: monospace; |
||||
height: 300px; |
||||
} |
||||
.CodeMirror-scroll { |
||||
/* Set scrolling behaviour here */ |
||||
overflow: auto; |
||||
} |
||||
|
||||
/* PADDING */ |
||||
|
||||
.CodeMirror-lines { |
||||
padding: 4px 0; /* Vertical padding around content */ |
||||
} |
||||
.CodeMirror pre { |
||||
padding: 0 4px; /* Horizontal padding of content */ |
||||
} |
||||
|
||||
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { |
||||
background-color: white; /* The little square between H and V scrollbars */ |
||||
} |
||||
|
||||
/* GUTTER */ |
||||
|
||||
.CodeMirror-gutters { |
||||
border-right: 1px solid #ddd; |
||||
background-color: #f7f7f7; |
||||
white-space: nowrap; |
||||
} |
||||
.CodeMirror-linenumbers {} |
||||
.CodeMirror-linenumber { |
||||
padding: 0 3px 0 5px; |
||||
min-width: 20px; |
||||
text-align: right; |
||||
color: #999; |
||||
-moz-box-sizing: content-box; |
||||
box-sizing: content-box; |
||||
} |
||||
|
||||
/* CURSOR */ |
||||
|
||||
.CodeMirror div.CodeMirror-cursor { |
||||
border-left: 1px solid black; |
||||
} |
||||
/* Shown when moving in bi-directional text */ |
||||
.CodeMirror div.CodeMirror-secondarycursor { |
||||
border-left: 1px solid silver; |
||||
} |
||||
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor { |
||||
width: auto; |
||||
border: 0; |
||||
background: #7e7; |
||||
} |
||||
/* Can style cursor different in overwrite (non-insert) mode */ |
||||
div.CodeMirror-overwrite div.CodeMirror-cursor {} |
||||
|
||||
.cm-tab { display: inline-block; } |
||||
|
||||
.CodeMirror-ruler { |
||||
border-left: 1px solid #ccc; |
||||
position: absolute; |
||||
} |
||||
|
||||
/* DEFAULT THEME */ |
||||
|
||||
.cm-s-default .cm-keyword {color: #708;} |
||||
.cm-s-default .cm-atom {color: #219;} |
||||
.cm-s-default .cm-number {color: #164;} |
||||
.cm-s-default .cm-def {color: #00f;} |
||||
.cm-s-default .cm-variable, |
||||
.cm-s-default .cm-punctuation, |
||||
.cm-s-default .cm-property, |
||||
.cm-s-default .cm-operator {} |
||||
.cm-s-default .cm-variable-2 {color: #05a;} |
||||
.cm-s-default .cm-variable-3 {color: #085;} |
||||
.cm-s-default .cm-comment {color: #a50;} |
||||
.cm-s-default .cm-string {color: #a11;} |
||||
.cm-s-default .cm-string-2 {color: #f50;} |
||||
.cm-s-default .cm-meta {color: #555;} |
||||
.cm-s-default .cm-qualifier {color: #555;} |
||||
.cm-s-default .cm-builtin {color: #30a;} |
||||
.cm-s-default .cm-bracket {color: #997;} |
||||
.cm-s-default .cm-tag {color: #170;} |
||||
.cm-s-default .cm-attribute {color: #00c;} |
||||
.cm-s-default .cm-header {color: blue;} |
||||
.cm-s-default .cm-quote {color: #090;} |
||||
.cm-s-default .cm-hr {color: #999;} |
||||
.cm-s-default .cm-link {color: #00c;} |
||||
|
||||
.cm-negative {color: #d44;} |
||||
.cm-positive {color: #292;} |
||||
.cm-header, .cm-strong {font-weight: bold;} |
||||
.cm-em {font-style: italic;} |
||||
.cm-link {text-decoration: underline;} |
||||
|
||||
.cm-s-default .cm-error {color: #f00;} |
||||
.cm-invalidchar {color: #f00;} |
||||
|
||||
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} |
||||
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} |
||||
.CodeMirror-activeline-background {background: #e8f2ff;} |
||||
|
||||
/* STOP */ |
||||
|
||||
/* The rest of this file contains styles related to the mechanics of |
||||
the editor. You probably shouldn't touch them. */ |
||||
|
||||
.CodeMirror { |
||||
line-height: 1; |
||||
position: relative; |
||||
overflow: hidden; |
||||
background: white; |
||||
color: black; |
||||
} |
||||
|
||||
.CodeMirror-scroll { |
||||
/* 30px is the magic margin used to hide the element's real scrollbars */ |
||||
/* See overflow: hidden in .CodeMirror */ |
||||
margin-bottom: -30px; margin-right: -30px; |
||||
padding-bottom: 30px; |
||||
height: 100%; |
||||
outline: none; /* Prevent dragging from highlighting the element */ |
||||
position: relative; |
||||
-moz-box-sizing: content-box; |
||||
box-sizing: content-box; |
||||
} |
||||
.CodeMirror-sizer { |
||||
position: relative; |
||||
border-right: 30px solid transparent; |
||||
-moz-box-sizing: content-box; |
||||
box-sizing: content-box; |
||||
} |
||||
|
||||
/* The fake, visible scrollbars. Used to force redraw during scrolling |
||||
before actuall scrolling happens, thus preventing shaking and |
||||
flickering artifacts. */ |
||||
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { |
||||
position: absolute; |
||||
z-index: 6; |
||||
display: none; |
||||
} |
||||
.CodeMirror-vscrollbar { |
||||
right: 0; top: 0; |
||||
overflow-x: hidden; |
||||
overflow-y: scroll; |
||||
} |
||||
.CodeMirror-hscrollbar { |
||||
bottom: 0; left: 0; |
||||
overflow-y: hidden; |
||||
overflow-x: scroll; |
||||
} |
||||
.CodeMirror-scrollbar-filler { |
||||
right: 0; bottom: 0; |
||||
} |
||||
.CodeMirror-gutter-filler { |
||||
left: 0; bottom: 0; |
||||
} |
||||
|
||||
.CodeMirror-gutters { |
||||
position: absolute; left: 0; top: 0; |
||||
padding-bottom: 30px; |
||||
z-index: 3; |
||||
} |
||||
.CodeMirror-gutter { |
||||
white-space: normal; |
||||
height: 100%; |
||||
-moz-box-sizing: content-box; |
||||
box-sizing: content-box; |
||||
padding-bottom: 30px; |
||||
margin-bottom: -32px; |
||||
display: inline-block; |
||||
/* Hack to make IE7 behave */ |
||||
*zoom:1; |
||||
*display:inline; |
||||
} |
||||
.CodeMirror-gutter-elt { |
||||
position: absolute; |
||||
cursor: default; |
||||
z-index: 4; |
||||
} |
||||
|
||||
.CodeMirror-lines { |
||||
cursor: text; |
||||
} |
||||
.CodeMirror pre { |
||||
/* Reset some styles that the rest of the page might have set */ |
||||
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; |
||||
border-width: 0; |
||||
background: transparent; |
||||
font-family: inherit; |
||||
font-size: inherit; |
||||
margin: 0; |
||||
white-space: pre; |
||||
word-wrap: normal; |
||||
line-height: inherit; |
||||
color: inherit; |
||||
z-index: 2; |
||||
position: relative; |
||||
overflow: visible; |
||||
} |
||||
.CodeMirror-wrap pre { |
||||
word-wrap: break-word; |
||||
white-space: pre-wrap; |
||||
word-break: normal; |
||||
} |
||||
|
||||
.CodeMirror-linebackground { |
||||
position: absolute; |
||||
left: 0; right: 0; top: 0; bottom: 0; |
||||
z-index: 0; |
||||
} |
||||
|
||||
.CodeMirror-linewidget { |
||||
position: relative; |
||||
z-index: 2; |
||||
overflow: auto; |
||||
} |
||||
|
||||
.CodeMirror-widget {} |
||||
|
||||
.CodeMirror-wrap .CodeMirror-scroll { |
||||
overflow-x: hidden; |
||||
} |
||||
|
||||
.CodeMirror-measure { |
||||
position: absolute; |
||||
width: 100%; |
||||
height: 0; |
||||
overflow: hidden; |
||||
visibility: hidden; |
||||
} |
||||
.CodeMirror-measure pre { position: static; } |
||||
|
||||
.CodeMirror div.CodeMirror-cursor { |
||||
position: absolute; |
||||
border-right: none; |
||||
width: 0; |
||||
} |
||||
|
||||
div.CodeMirror-cursors { |
||||
visibility: hidden; |
||||
position: relative; |
||||
z-index: 1; |
||||
} |
||||
.CodeMirror-focused div.CodeMirror-cursors { |
||||
visibility: visible; |
||||
} |
||||
|
||||
.CodeMirror-selected { background: #d9d9d9; } |
||||
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } |
||||
.CodeMirror-crosshair { cursor: crosshair; } |
||||
|
||||
.cm-searching { |
||||
background: #ffa; |
||||
background: rgba(255, 255, 0, .4); |
||||
} |
||||
|
||||
/* IE7 hack to prevent it from returning funny offsetTops on the spans */ |
||||
.CodeMirror span { *vertical-align: text-bottom; } |
||||
|
||||
/* Used to force a border model for a node */ |
||||
.cm-force-border { padding-right: .1px; } |
||||
|
||||
@media print { |
||||
/* Hide the cursor when printing */ |
||||
.CodeMirror div.CodeMirror-cursors { |
||||
visibility: hidden; |
||||
} |
||||
} |
@ -1,53 +0,0 @@ |
||||
<!doctype> |
||||
<html> |
||||
<head> |
||||
<style type="text/css"> |
||||
html, body { |
||||
margin: 0; padding: 0; |
||||
min-height: 100%; |
||||
} |
||||
|
||||
#debugger { |
||||
height: 100%; |
||||
font-family: "Monaco" |
||||
} |
||||
#debugger .line { |
||||
overflow: none; |
||||
} |
||||
#debugger .col1, #debugger .col2 { |
||||
float: left; |
||||
padding: 3px; |
||||
} |
||||
#debugger .col1 { |
||||
width: 10px; |
||||
padding-left: 10px |
||||
-webkit-touch-callout: none; |
||||
-webkit-user-select: none; |
||||
-khtml-user-select: none; |
||||
-moz-user-select: none; |
||||
-ms-user-select: none; |
||||
user-select: none; |
||||
} |
||||
#debugger .col2 { |
||||
width: 90%; |
||||
} |
||||
.prompt { |
||||
color: "#5089D4"; |
||||
} |
||||
</style> |
||||
|
||||
</head> |
||||
|
||||
<body> |
||||
<div id="debugger"> |
||||
<div class="line"> |
||||
<div class="col1 prompt"> |
||||
> |
||||
</div> |
||||
<div class="col2" contenteditable> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
</body> |
||||
</html> |
@ -1,23 +0,0 @@ |
||||
.cm-s-eclipse span.cm-meta {color: #FF1717;} |
||||
.cm-s-eclipse span.cm-keyword { line-height: 1em; font-weight: bold; color: #7F0055; } |
||||
.cm-s-eclipse span.cm-atom {color: #219;} |
||||
.cm-s-eclipse span.cm-number {color: #164;} |
||||
.cm-s-eclipse span.cm-def {color: #00f;} |
||||
.cm-s-eclipse span.cm-variable {color: black;} |
||||
.cm-s-eclipse span.cm-variable-2 {color: #0000C0;} |
||||
.cm-s-eclipse span.cm-variable-3 {color: #0000C0;} |
||||
.cm-s-eclipse span.cm-property {color: black;} |
||||
.cm-s-eclipse span.cm-operator {color: black;} |
||||
.cm-s-eclipse span.cm-comment {color: #3F7F5F;} |
||||
.cm-s-eclipse span.cm-string {color: #2A00FF;} |
||||
.cm-s-eclipse span.cm-string-2 {color: #f50;} |
||||
.cm-s-eclipse span.cm-qualifier {color: #555;} |
||||
.cm-s-eclipse span.cm-builtin {color: #30a;} |
||||
.cm-s-eclipse span.cm-bracket {color: #cc7;} |
||||
.cm-s-eclipse span.cm-tag {color: #170;} |
||||
.cm-s-eclipse span.cm-attribute {color: #00c;} |
||||
.cm-s-eclipse span.cm-link {color: #219;} |
||||
.cm-s-eclipse span.cm-error {color: #f00;} |
||||
|
||||
.cm-s-eclipse .CodeMirror-activeline-background {background: #e8f2ff !important;} |
||||
.cm-s-eclipse .CodeMirror-matchingbracket {outline:1px solid grey; color:black !important;} |
@ -1,80 +0,0 @@ |
||||
<!doctype> |
||||
<html> |
||||
<head> |
||||
<title>Mutan Editor</title> |
||||
<link rel="stylesheet" href="codemirror.css"> |
||||
<link rel="stylesheet" href="eclipse.css"> |
||||
<script src="lib/codemirror.js"></script> |
||||
<script src="lib/matchbrackets.js"></script> |
||||
<script src="lib/go.js"></script> |
||||
<script src="muted.js"></script> |
||||
|
||||
<style type="text/css"> |
||||
html, body { |
||||
margin: 0; padding: 0; |
||||
min-height: 100%; |
||||
} |
||||
|
||||
#debugger { |
||||
height: 30%; |
||||
font-family: "Monaco"; |
||||
border-top: 5px solid grey; |
||||
} |
||||
#debugger .line { |
||||
overflow: none; |
||||
} |
||||
#debugger .col1, #debugger .col2 { |
||||
float: left; |
||||
padding: 3px; |
||||
} |
||||
#debugger .col1 { |
||||
width: 10px; |
||||
padding-left: 10px |
||||
-webkit-touch-callout: none; |
||||
-webkit-user-select: none; |
||||
-khtml-user-select: none; |
||||
-moz-user-select: none; |
||||
-ms-user-select: none; |
||||
user-select: none; |
||||
} |
||||
#debugger .col2 { |
||||
width: 90%; |
||||
} |
||||
.prompt { |
||||
color: "#5089D4"; |
||||
} |
||||
|
||||
.CodeMirror { |
||||
height: 70%; |
||||
font-size: 14pt; |
||||
} |
||||
</style> |
||||
</head> |
||||
|
||||
<body> |
||||
<textarea id="editor"></textarea> |
||||
|
||||
<div id="debugger"> |
||||
<div class="line"> |
||||
<div class="col1 prompt"> |
||||
> |
||||
</div> |
||||
<div class="col2" contenteditable> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<script> |
||||
var textArea = document.querySelector("#editor") |
||||
var editor = CodeMirror.fromTextArea(textArea, { |
||||
theme: "eclipse", |
||||
mode: "text/html", |
||||
lineNumbers: true, |
||||
mode: "text/x-go", |
||||
indentUnit: 8, |
||||
tabSize: 8, |
||||
indentWithTabs: true, |
||||
}); |
||||
</script> |
||||
</body> |
||||
</html> |
@ -1,182 +0,0 @@ |
||||
(function(mod) { |
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror")); |
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod); |
||||
else // Plain browser env
|
||||
mod(CodeMirror); |
||||
})(function(CodeMirror) { |
||||
"use strict"; |
||||
|
||||
CodeMirror.defineMode("go", function(config) { |
||||
var indentUnit = config.indentUnit; |
||||
|
||||
var keywords = { |
||||
"break":true, "case":true, "chan":true, "const":true, "continue":true, |
||||
"default":true, "defer":true, "else":true, "fallthrough":true, "for":true, |
||||
"func":true, "go":true, "goto":true, "if":true, "import":true, |
||||
"interface":true, "map":true, "package":true, "range":true, "return":true, |
||||
"select":true, "struct":true, "switch":true, "type":true, "var":true, |
||||
"bool":true, "byte":true, "complex64":true, "complex128":true, |
||||
"float32":true, "float64":true, "int8":true, "int16":true, "int32":true, |
||||
"int64":true, "string":true, "uint8":true, "uint16":true, "uint32":true, |
||||
"uint64":true, "int":true, "uint":true, "uintptr":true, "big": true, |
||||
"main": true, "init": true, "this":true |
||||
}; |
||||
|
||||
var atoms = { |
||||
"true":true, "false":true, "iota":true, "nil":true, "append":true, |
||||
"cap":true, "close":true, "complex":true, "copy":true, "imag":true, |
||||
"len":true, "make":true, "new":true, "panic":true, "print":true, |
||||
"println":true, "real":true, "recover":true,
|
||||
}; |
||||
|
||||
var isOperatorChar = /[+\-*&^%:=<>!|\/]/; |
||||
|
||||
var curPunc; |
||||
|
||||
function tokenBase(stream, state) { |
||||
var ch = stream.next(); |
||||
if (ch == '"' || ch == "'" || ch == "`") { |
||||
state.tokenize = tokenString(ch); |
||||
return state.tokenize(stream, state); |
||||
} |
||||
if (/[\d\.]/.test(ch)) { |
||||
if (ch == ".") { |
||||
stream.match(/^[0-9]+([eE][\-+]?[0-9]+)?/); |
||||
} else if (ch == "0") { |
||||
stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/); |
||||
} else { |
||||
stream.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/); |
||||
} |
||||
return "number"; |
||||
} |
||||
if (/[\[\]{}\(\),;\:\.]/.test(ch)) { |
||||
curPunc = ch; |
||||
return null; |
||||
} |
||||
if (ch == "/") { |
||||
if (stream.eat("*")) { |
||||
state.tokenize = tokenComment; |
||||
return tokenComment(stream, state); |
||||
} |
||||
if (stream.eat("/")) { |
||||
stream.skipToEnd(); |
||||
return "comment"; |
||||
} |
||||
} |
||||
if (isOperatorChar.test(ch)) { |
||||
stream.eatWhile(isOperatorChar); |
||||
return "operator"; |
||||
} |
||||
stream.eatWhile(/[\w\$_]/); |
||||
var cur = stream.current(); |
||||
if (keywords.propertyIsEnumerable(cur)) { |
||||
if (cur == "case" || cur == "default") curPunc = "case"; |
||||
return "keyword"; |
||||
} |
||||
if (atoms.propertyIsEnumerable(cur)) return "atom"; |
||||
return "variable"; |
||||
} |
||||
|
||||
function tokenString(quote) { |
||||
return function(stream, state) { |
||||
var escaped = false, next, end = false; |
||||
while ((next = stream.next()) != null) { |
||||
if (next == quote && !escaped) {end = true; break;} |
||||
escaped = !escaped && next == "\\"; |
||||
} |
||||
if (end || !(escaped || quote == "`")) |
||||
state.tokenize = tokenBase; |
||||
return "string"; |
||||
}; |
||||
} |
||||
|
||||
function tokenComment(stream, state) { |
||||
var maybeEnd = false, ch; |
||||
while (ch = stream.next()) { |
||||
if (ch == "/" && maybeEnd) { |
||||
state.tokenize = tokenBase; |
||||
break; |
||||
} |
||||
maybeEnd = (ch == "*"); |
||||
} |
||||
return "comment"; |
||||
} |
||||
|
||||
function Context(indented, column, type, align, prev) { |
||||
this.indented = indented; |
||||
this.column = column; |
||||
this.type = type; |
||||
this.align = align; |
||||
this.prev = prev; |
||||
} |
||||
function pushContext(state, col, type) { |
||||
return state.context = new Context(state.indented, col, type, null, state.context); |
||||
} |
||||
function popContext(state) { |
||||
var t = state.context.type; |
||||
if (t == ")" || t == "]" || t == "}") |
||||
state.indented = state.context.indented; |
||||
return state.context = state.context.prev; |
||||
} |
||||
|
||||
// Interface
|
||||
|
||||
return { |
||||
startState: function(basecolumn) { |
||||
return { |
||||
tokenize: null, |
||||
context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), |
||||
indented: 0, |
||||
startOfLine: true |
||||
}; |
||||
}, |
||||
|
||||
token: function(stream, state) { |
||||
var ctx = state.context; |
||||
if (stream.sol()) { |
||||
if (ctx.align == null) ctx.align = false; |
||||
state.indented = stream.indentation(); |
||||
state.startOfLine = true; |
||||
if (ctx.type == "case") ctx.type = "}"; |
||||
} |
||||
if (stream.eatSpace()) return null; |
||||
curPunc = null; |
||||
var style = (state.tokenize || tokenBase)(stream, state); |
||||
if (style == "comment") return style; |
||||
if (ctx.align == null) ctx.align = true; |
||||
|
||||
if (curPunc == "{") pushContext(state, stream.column(), "}"); |
||||
else if (curPunc == "[") pushContext(state, stream.column(), "]"); |
||||
else if (curPunc == "(") pushContext(state, stream.column(), ")"); |
||||
else if (curPunc == "case") ctx.type = "case"; |
||||
else if (curPunc == "}" && ctx.type == "}") ctx = popContext(state); |
||||
else if (curPunc == ctx.type) popContext(state); |
||||
state.startOfLine = false; |
||||
return style; |
||||
}, |
||||
|
||||
indent: function(state, textAfter) { |
||||
if (state.tokenize != tokenBase && state.tokenize != null) return 0; |
||||
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); |
||||
if (ctx.type == "case" && /^(?:case|default)\b/.test(textAfter)) { |
||||
state.context.type = "}"; |
||||
return ctx.indented; |
||||
} |
||||
var closing = firstChar == ctx.type; |
||||
if (ctx.align) return ctx.column + (closing ? 0 : 1); |
||||
else return ctx.indented + (closing ? 0 : indentUnit); |
||||
}, |
||||
|
||||
electricChars: "{}):", |
||||
fold: "brace", |
||||
blockCommentStart: "/*", |
||||
blockCommentEnd: "*/", |
||||
lineComment: "//" |
||||
}; |
||||
}); |
||||
|
||||
CodeMirror.defineMIME("text/x-go", "go"); |
||||
|
||||
}); |
@ -1,117 +0,0 @@ |
||||
(function(mod) { |
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror")); |
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod); |
||||
else // Plain browser env
|
||||
mod(CodeMirror); |
||||
})(function(CodeMirror) { |
||||
var ie_lt8 = /MSIE \d/.test(navigator.userAgent) && |
||||
(document.documentMode == null || document.documentMode < 8); |
||||
|
||||
var Pos = CodeMirror.Pos; |
||||
|
||||
var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; |
||||
|
||||
function findMatchingBracket(cm, where, strict, config) { |
||||
var line = cm.getLineHandle(where.line), pos = where.ch - 1; |
||||
var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)]; |
||||
if (!match) return null; |
||||
var dir = match.charAt(1) == ">" ? 1 : -1; |
||||
if (strict && (dir > 0) != (pos == where.ch)) return null; |
||||
var style = cm.getTokenTypeAt(Pos(where.line, pos + 1)); |
||||
|
||||
var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config); |
||||
if (found == null) return null; |
||||
return {from: Pos(where.line, pos), to: found && found.pos, |
||||
match: found && found.ch == match.charAt(0), forward: dir > 0}; |
||||
} |
||||
|
||||
// bracketRegex is used to specify which type of bracket to scan
|
||||
// should be a regexp, e.g. /[[\]]/
|
||||
//
|
||||
// Note: If "where" is on an open bracket, then this bracket is ignored.
|
||||
//
|
||||
// Returns false when no bracket was found, null when it reached
|
||||
// maxScanLines and gave up
|
||||
function scanForBracket(cm, where, dir, style, config) { |
||||
var maxScanLen = (config && config.maxScanLineLength) || 10000; |
||||
var maxScanLines = (config && config.maxScanLines) || 1000; |
||||
|
||||
var stack = []; |
||||
var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/; |
||||
var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1) |
||||
: Math.max(cm.firstLine() - 1, where.line - maxScanLines); |
||||
for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) { |
||||
var line = cm.getLine(lineNo); |
||||
if (!line) continue; |
||||
var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1; |
||||
if (line.length > maxScanLen) continue; |
||||
if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0); |
||||
for (; pos != end; pos += dir) { |
||||
var ch = line.charAt(pos); |
||||
if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) { |
||||
var match = matching[ch]; |
||||
if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch); |
||||
else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch}; |
||||
else stack.pop(); |
||||
} |
||||
} |
||||
} |
||||
return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null; |
||||
} |
||||
|
||||
function matchBrackets(cm, autoclear, config) { |
||||
// Disable brace matching in long lines, since it'll cause hugely slow updates
|
||||
var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000; |
||||
var marks = [], ranges = cm.listSelections(); |
||||
for (var i = 0; i < ranges.length; i++) { |
||||
var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config); |
||||
if (match && cm.getLine(match.from.line).length <= maxHighlightLen) { |
||||
var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; |
||||
marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style})); |
||||
if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen) |
||||
marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style})); |
||||
} |
||||
} |
||||
|
||||
if (marks.length) { |
||||
// Kludge to work around the IE bug from issue #1193, where text
|
||||
// input stops going to the textare whever this fires.
|
||||
if (ie_lt8 && cm.state.focused) cm.display.input.focus(); |
||||
|
||||
var clear = function() { |
||||
cm.operation(function() { |
||||
for (var i = 0; i < marks.length; i++) marks[i].clear(); |
||||
}); |
||||
}; |
||||
if (autoclear) setTimeout(clear, 800); |
||||
else return clear; |
||||
} |
||||
} |
||||
|
||||
var currentlyHighlighted = null; |
||||
function doMatchBrackets(cm) { |
||||
cm.operation(function() { |
||||
if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;} |
||||
currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets); |
||||
}); |
||||
} |
||||
|
||||
CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) { |
||||
if (old && old != CodeMirror.Init) |
||||
cm.off("cursorActivity", doMatchBrackets); |
||||
if (val) { |
||||
cm.state.matchBrackets = typeof val == "object" ? val : {}; |
||||
cm.on("cursorActivity", doMatchBrackets); |
||||
} |
||||
}); |
||||
|
||||
CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);}); |
||||
CodeMirror.defineExtension("findMatchingBracket", function(pos, strict, config){ |
||||
return findMatchingBracket(this, pos, strict, config); |
||||
}); |
||||
CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){ |
||||
return scanForBracket(this, pos, dir, style, config); |
||||
}); |
||||
}); |
@ -1,78 +0,0 @@ |
||||
// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved.
|
||||
//
|
||||
// This library 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 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library 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 this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301 USA
|
||||
|
||||
// Helper function for generating pseudo callbacks and sending data to the QML part of the application
|
||||
function postData(data, cb) { |
||||
data._seed = Math.floor(Math.random() * 1000000) |
||||
if(cb) { |
||||
Muted._callbacks[data._seed] = cb; |
||||
} |
||||
|
||||
if(data.args === undefined) { |
||||
data.args = []; |
||||
} |
||||
|
||||
navigator.qt.postMessage(JSON.stringify(data)); |
||||
} |
||||
|
||||
window.Muted = { |
||||
prototype: Object(), |
||||
} |
||||
|
||||
window.Muted._callbacks = {} |
||||
window.Muted._onCallbacks = {} |
||||
|
||||
function debug(/**/) { |
||||
console.log("hello world") |
||||
|
||||
var args = arguments; |
||||
var msg = "" |
||||
for(var i = 0; i < args.length; i++){ |
||||
if(typeof args[i] == "object") { |
||||
msg += " " + JSON.stringify(args[i]) |
||||
} else { |
||||
msg += args[i] |
||||
} |
||||
} |
||||
|
||||
document.querySelector("#debugger").innerHTML += "<div class='line'><div class='col1'></div><div class='col2'>"+msg+"</div></div>"; |
||||
} |
||||
console.log = function() { |
||||
var args = [] |
||||
for(var i = 0; i < arguments.length; i++) { |
||||
args.push(arguments[i]); |
||||
} |
||||
postData({call:"log", args:args}) |
||||
} |
||||
|
||||
navigator.qt.onmessage = function(ev) { |
||||
var data = JSON.parse(ev.data) |
||||
|
||||
if(data._event !== undefined) { |
||||
Muted.trigger(data._event, data.data); |
||||
} else { |
||||
if(data._seed) { |
||||
var cb = Muted._callbacks[data._seed]; |
||||
if(cb) { |
||||
// Call the callback
|
||||
cb(data.data); |
||||
// Remove the "trigger" callback
|
||||
delete Muted._callbacks[ev._seed]; |
||||
} |
||||
} |
||||
} |
||||
} |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 932 B |
@ -1,22 +0,0 @@ |
||||
import QtQuick 2.0 |
||||
import QtQuick.Controls 1.0; |
||||
import QtQuick.Layouts 1.0; |
||||
import Ethereum 1.0 |
||||
|
||||
ApplicationWindow { |
||||
minimumWidth: 500 |
||||
maximumWidth: 500 |
||||
maximumHeight: 400 |
||||
minimumHeight: 400 |
||||
|
||||
function onNewBlockCb(block) { |
||||
console.log("Please overwrite onNewBlock(block):", block) |
||||
} |
||||
function onObjectChangeCb(stateObject) { |
||||
console.log("Please overwrite onObjectChangeCb(object)", stateObject) |
||||
} |
||||
function onStorageChangeCb(storageObject) { |
||||
var ev = ["storage", storageObject.stateAddress, storageObject.address].join(":"); |
||||
console.log("Please overwrite onStorageChangeCb(object)", ev) |
||||
} |
||||
} |
@ -1,486 +0,0 @@ |
||||
import QtQuick 2.1 |
||||
import QtWebKit 3.0 |
||||
import QtWebKit.experimental 1.0 |
||||
import QtQuick.Controls 1.0; |
||||
import QtQuick.Controls.Styles 1.0 |
||||
import QtQuick.Layouts 1.0; |
||||
import QtQuick.Window 2.1; |
||||
import Ethereum 1.0 |
||||
|
||||
Rectangle { |
||||
id: window |
||||
anchors.fill: parent |
||||
color: "#00000000" |
||||
|
||||
property var title: "DApps" |
||||
property var iconSource: "../browser.png" |
||||
property var menuItem |
||||
property var hideUrl: true |
||||
|
||||
property alias url: webview.url |
||||
property alias windowTitle: webview.title |
||||
property alias webView: webview |
||||
|
||||
property var cleanPath: false |
||||
property var open: function(url) { |
||||
if(!window.cleanPath) { |
||||
var uri = url; |
||||
if(!/.*\:\/\/.*/.test(uri)) { |
||||
uri = "http://" + uri; |
||||
} |
||||
|
||||
var reg = /(^https?\:\/\/(?:www\.)?)([a-zA-Z0-9_\-]*\.eth)(.*)/ |
||||
|
||||
if(reg.test(uri)) { |
||||
uri.replace(reg, function(match, pre, domain, path) { |
||||
uri = pre; |
||||
|
||||
var lookup = eth.lookupDomain(domain.substring(0, domain.length - 4)); |
||||
var ip = []; |
||||
for(var i = 0, l = lookup.length; i < l; i++) { |
||||
ip.push(lookup.charCodeAt(i)) |
||||
} |
||||
|
||||
if(ip.length != 0) { |
||||
uri += lookup; |
||||
} else { |
||||
uri += domain; |
||||
} |
||||
|
||||
uri += path; |
||||
}); |
||||
} |
||||
|
||||
window.cleanPath = true; |
||||
|
||||
webview.url = uri; |
||||
|
||||
//uriNav.text = uri.text.replace(/(^https?\:\/\/(?:www\.)?)([a-zA-Z0-9_\-]*\.\w{2,3})(.*)/, "$1$2<span style='color:#CCC'>$3</span>"); |
||||
uriNav.text = uri; |
||||
} else { |
||||
// Prevent inf loop. |
||||
window.cleanPath = false; |
||||
} |
||||
} |
||||
|
||||
Component.onCompleted: { |
||||
webview.url = "http://etherian.io" |
||||
} |
||||
|
||||
function messages(messages, id) { |
||||
// Bit of a cheat to get proper JSON |
||||
var m = JSON.parse(JSON.parse(JSON.stringify(messages))) |
||||
webview.postEvent("eth_changed", id, m); |
||||
} |
||||
|
||||
function onShhMessage(message, id) { |
||||
webview.postEvent("shh_changed", id, message) |
||||
} |
||||
|
||||
Item { |
||||
objectName: "root" |
||||
id: root |
||||
anchors.fill: parent |
||||
state: "inspectorShown" |
||||
|
||||
RowLayout { |
||||
id: navBar |
||||
height: 40 |
||||
anchors { |
||||
left: parent.left |
||||
right: parent.right |
||||
leftMargin: 7 |
||||
} |
||||
|
||||
Button { |
||||
id: back |
||||
onClicked: { |
||||
webview.goBack() |
||||
} |
||||
style: ButtonStyle { |
||||
background: Image { |
||||
source: "../back.png" |
||||
width: 30 |
||||
height: 30 |
||||
} |
||||
} |
||||
} |
||||
|
||||
TextField { |
||||
anchors { |
||||
left: back.right |
||||
right: toggleInspector.left |
||||
leftMargin: 10 |
||||
rightMargin: 10 |
||||
} |
||||
text: webview.url; |
||||
id: uriNav |
||||
y: parent.height / 2 - this.height / 2 |
||||
|
||||
Keys.onReturnPressed: { |
||||
webview.url = this.text; |
||||
} |
||||
} |
||||
|
||||
Button { |
||||
id: toggleInspector |
||||
anchors { |
||||
right: parent.right |
||||
} |
||||
iconSource: "../bug.png" |
||||
onClicked: { |
||||
if(inspector.visible == true){ |
||||
inspector.visible = false |
||||
}else{ |
||||
inspector.visible = true |
||||
inspector.url = webview.experimental.remoteInspectorUrl |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Border |
||||
Rectangle { |
||||
id: divider |
||||
anchors { |
||||
left: parent.left |
||||
right: parent.right |
||||
top: navBar.bottom |
||||
} |
||||
z: -1 |
||||
height: 1 |
||||
color: "#CCCCCC" |
||||
} |
||||
|
||||
ScrollView { |
||||
anchors { |
||||
left: parent.left |
||||
right: parent.right |
||||
bottom: parent.bottom |
||||
top: divider.bottom |
||||
} |
||||
WebView { |
||||
objectName: "webView" |
||||
id: webview |
||||
anchors.fill: parent |
||||
|
||||
function sendMessage(data) { |
||||
webview.experimental.postMessage(JSON.stringify(data)) |
||||
} |
||||
|
||||
experimental.preferences.javascriptEnabled: true |
||||
experimental.preferences.webAudioEnabled: true |
||||
experimental.preferences.pluginsEnabled: true |
||||
experimental.preferences.navigatorQtObjectEnabled: true |
||||
experimental.preferences.developerExtrasEnabled: true |
||||
experimental.preferences.webGLEnabled: true |
||||
experimental.preferences.notificationsEnabled: true |
||||
experimental.preferences.localStorageEnabled: true |
||||
experimental.userAgent:"Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Mist/0.1 Safari/537.36" |
||||
|
||||
experimental.itemSelector: MouseArea { |
||||
// To avoid conflicting with ListView.model when inside Initiator context. |
||||
property QtObject selectorModel: model |
||||
anchors.fill: parent |
||||
onClicked: selectorModel.reject() |
||||
|
||||
Menu { |
||||
visible: true |
||||
id: itemSelector |
||||
|
||||
Instantiator { |
||||
model: selectorModel.items |
||||
delegate: MenuItem { |
||||
text: model.text |
||||
onTriggered: { |
||||
selectorModel.accept(index) |
||||
} |
||||
} |
||||
onObjectAdded: itemSelector.insertItem(index, object) |
||||
onObjectRemoved: itemSelector.removeItem(object) |
||||
} |
||||
} |
||||
|
||||
Component.onCompleted: { |
||||
itemSelector.popup() |
||||
} |
||||
} |
||||
experimental.userScripts: ["../ext/q.js", "../ext/ethereum.js/dist/ethereum.min.js", "../ext/setup.js"] |
||||
experimental.onMessageReceived: { |
||||
//console.log("[onMessageReceived]: ", message.data) |
||||
var data = JSON.parse(message.data) |
||||
|
||||
try { |
||||
switch(data.call) { |
||||
case "eth_compile": |
||||
postData(data._id, eth.compile(data.args[0])) |
||||
break |
||||
|
||||
case "eth_coinbase": |
||||
postData(data._id, eth.coinBase()) |
||||
|
||||
case "eth_account": |
||||
postData(data._id, eth.key().address); |
||||
|
||||
case "eth_istening": |
||||
postData(data._id, eth.isListening()) |
||||
|
||||
break |
||||
|
||||
case "eth_mining": |
||||
postData(data._id, eth.isMining()) |
||||
|
||||
break |
||||
|
||||
case "eth_peerCount": |
||||
postData(data._id, eth.peerCount()) |
||||
|
||||
break |
||||
|
||||
case "eth_countAt": |
||||
require(1) |
||||
postData(data._id, eth.txCountAt(data.args[0])) |
||||
|
||||
break |
||||
|
||||
case "eth_codeAt": |
||||
require(1) |
||||
var code = eth.codeAt(data.args[0]) |
||||
postData(data._id, code); |
||||
|
||||
break |
||||
|
||||
case "eth_blockByNumber": |
||||
require(1) |
||||
var block = eth.blockByNumber(data.args[0]) |
||||
postData(data._id, block) |
||||
break |
||||
|
||||
case "eth_blockByHash": |
||||
require(1) |
||||
var block = eth.blockByHash(data.args[0]) |
||||
postData(data._id, block) |
||||
break |
||||
|
||||
require(2) |
||||
var block = eth.blockByHash(data.args[0]) |
||||
postData(data._id, block.transactions[data.args[1]]) |
||||
break |
||||
|
||||
case "eth_transactionByHash": |
||||
case "eth_transactionByNumber": |
||||
require(2) |
||||
|
||||
var block; |
||||
if (data.call === "transactionByHash") |
||||
block = eth.blockByHash(data.args[0]) |
||||
else |
||||
block = eth.blockByNumber(data.args[0]) |
||||
|
||||
var tx = block.transactions.get(data.args[1]) |
||||
|
||||
postData(data._id, tx) |
||||
break |
||||
|
||||
case "eth_uncleByHash": |
||||
case "eth_uncleByNumber": |
||||
require(2) |
||||
|
||||
var block; |
||||
if (data.call === "uncleByHash") |
||||
block = eth.blockByHash(data.args[0]) |
||||
else |
||||
block = eth.blockByNumber(data.args[0]) |
||||
|
||||
var uncle = block.uncles.get(data.args[1]) |
||||
|
||||
postData(data._id, uncle) |
||||
|
||||
break |
||||
|
||||
case "transact": |
||||
require(5) |
||||
|
||||
var tx = eth.transact(data.args) |
||||
postData(data._id, tx) |
||||
|
||||
break |
||||
|
||||
case "eth_stateAt": |
||||
require(2); |
||||
|
||||
var storage = eth.storageAt(data.args[0], data.args[1]); |
||||
postData(data._id, storage) |
||||
|
||||
break |
||||
|
||||
case "eth_call": |
||||
require(1); |
||||
var ret = eth.call(data.args) |
||||
postData(data._id, ret) |
||||
break |
||||
|
||||
case "eth_balanceAt": |
||||
require(1); |
||||
|
||||
postData(data._id, eth.balanceAt(data.args[0])); |
||||
break |
||||
|
||||
case "eth_watch": |
||||
require(2) |
||||
eth.watch(data.args[0], data.args[1]) |
||||
|
||||
case "eth_disconnect": |
||||
require(1) |
||||
postData(data._id, null) |
||||
break; |
||||
|
||||
case "eth_newFilterString": |
||||
require(1) |
||||
var id = eth.newFilterString(data.args[0], window) |
||||
postData(data._id, id); |
||||
break; |
||||
|
||||
case "eth_newFilter": |
||||
require(1) |
||||
var id = eth.newFilter(data.args[0], window) |
||||
|
||||
postData(data._id, id); |
||||
break; |
||||
|
||||
case "eth_filterLogs": |
||||
require(1); |
||||
|
||||
var messages = eth.messages(data.args[0]); |
||||
var m = JSON.parse(JSON.parse(JSON.stringify(messages))) |
||||
postData(data._id, m); |
||||
|
||||
break; |
||||
|
||||
case "eth_deleteFilter": |
||||
require(1); |
||||
eth.uninstallFilter(data.args[0]) |
||||
break; |
||||
|
||||
|
||||
case "shh_newFilter": |
||||
require(1); |
||||
var id = shh.watch(data.args[0], window); |
||||
postData(data._id, id); |
||||
break; |
||||
|
||||
case "shh_newIdentity": |
||||
var id = shh.newIdentity() |
||||
postData(data._id, id) |
||||
|
||||
break |
||||
|
||||
case "shh_post": |
||||
require(1); |
||||
|
||||
var params = data.args[0]; |
||||
var fields = ["payload", "to", "from"]; |
||||
for(var i = 0; i < fields.length; i++) { |
||||
params[fields[i]] = params[fields[i]] || ""; |
||||
} |
||||
if(typeof params.payload !== "object") { params.payload = [params.payload]; } //params.payload = params.payload.join(""); } |
||||
params.topics = params.topics || []; |
||||
params.priority = params.priority || 1000; |
||||
params.ttl = params.ttl || 100; |
||||
|
||||
shh.post(params.payload, params.to, params.from, params.topics, params.priority, params.ttl); |
||||
|
||||
break; |
||||
|
||||
case "shh_getMessages": |
||||
require(1); |
||||
|
||||
var m = shh.messages(data.args[0]); |
||||
var messages = JSON.parse(JSON.parse(JSON.stringify(m))); |
||||
postData(data._id, messages); |
||||
|
||||
break; |
||||
|
||||
case "ssh_newGroup": |
||||
postData(data._id, ""); |
||||
break; |
||||
} |
||||
} catch(e) { |
||||
console.log(data.call + ": " + e) |
||||
|
||||
postData(data._id, null); |
||||
} |
||||
} |
||||
|
||||
function post(seed, data) { |
||||
postData(data._id, data) |
||||
} |
||||
function require(args, num) { |
||||
if(args.length < num) { |
||||
throw("required argument count of "+num+" got "+args.length); |
||||
} |
||||
} |
||||
function postData(seed, data) { |
||||
webview.experimental.postMessage(JSON.stringify({data: data, _id: seed})) |
||||
} |
||||
function postEvent(event, id, data) { |
||||
webview.experimental.postMessage(JSON.stringify({data: data, _id: id, _event: event})) |
||||
} |
||||
function onWatchedCb(data, id) { |
||||
var messages = JSON.parse(data) |
||||
postEvent("watched:"+id, messages) |
||||
} |
||||
function onNewBlockCb(block) { |
||||
postEvent("block:new", block) |
||||
} |
||||
function onObjectChangeCb(stateObject) { |
||||
postEvent("object:"+stateObject.address(), stateObject) |
||||
} |
||||
function onStorageChangeCb(storageObject) { |
||||
var ev = ["storage", storageObject.stateAddress, storageObject.address].join(":"); |
||||
postEvent(ev, [storageObject.address, storageObject.value]) |
||||
} |
||||
} |
||||
} |
||||
|
||||
Rectangle { |
||||
id: sizeGrip |
||||
color: "gray" |
||||
visible: false |
||||
height: 10 |
||||
anchors { |
||||
left: root.left |
||||
right: root.right |
||||
} |
||||
y: Math.round(root.height * 2 / 3) |
||||
|
||||
MouseArea { |
||||
anchors.fill: parent |
||||
drag.target: sizeGrip |
||||
drag.minimumY: 0 |
||||
drag.maximumY: root.height |
||||
drag.axis: Drag.YAxis |
||||
} |
||||
} |
||||
|
||||
WebView { |
||||
id: inspector |
||||
visible: false |
||||
anchors { |
||||
left: root.left |
||||
right: root.right |
||||
top: sizeGrip.bottom |
||||
bottom: root.bottom |
||||
} |
||||
} |
||||
|
||||
states: [ |
||||
State { |
||||
name: "inspectorShown" |
||||
PropertyChanges { |
||||
target: inspector |
||||
} |
||||
} |
||||
] |
||||
} |
||||
} |
@ -1,155 +0,0 @@ |
||||
import QtQuick 2.0 |
||||
import Ethereum 1.0 |
||||
|
||||
// Which ones do we actually need? |
||||
import QtQuick.Controls 1.0; |
||||
import QtQuick.Layouts 1.0; |
||||
import QtQuick.Dialogs 1.0; |
||||
import QtQuick.Window 2.1; |
||||
import QtQuick.Controls.Styles 1.1 |
||||
import QtQuick.Dialogs 1.1 |
||||
|
||||
ApplicationWindow { |
||||
id: wizardRoot |
||||
width: 500 |
||||
height: 400 |
||||
title: "Ethereal first run setup" |
||||
|
||||
Column { |
||||
spacing: 5 |
||||
anchors.leftMargin: 10 |
||||
anchors.left: parent.left |
||||
|
||||
Text { |
||||
visible: true |
||||
text: "<h2>Ethereal setup</h2>" |
||||
} |
||||
|
||||
Column { |
||||
id: restoreColumn |
||||
spacing: 5 |
||||
Text { |
||||
visible: true |
||||
font.pointSize: 14 |
||||
text: "Restore your Ethereum account" |
||||
id: restoreLabel |
||||
} |
||||
|
||||
TextField { |
||||
id: txPrivKey |
||||
width: 480 |
||||
placeholderText: "Private key or mnemonic words" |
||||
focus: true |
||||
onTextChanged: { |
||||
if(this.text.length == 64){ |
||||
detailLabel.text = "Private (hex) key detected." |
||||
actionButton.enabled = true |
||||
} |
||||
else if(this.text.split(" ").length == 24){ |
||||
detailLabel.text = "Mnemonic key detected." |
||||
actionButton.enabled = true |
||||
}else{ |
||||
detailLabel.text = "" |
||||
actionButton.enabled = false |
||||
} |
||||
} |
||||
} |
||||
Row { |
||||
spacing: 10 |
||||
Button { |
||||
id: actionButton |
||||
text: "Restore" |
||||
enabled: false |
||||
onClicked: { |
||||
var success = lib.importAndSetPrivKey(txPrivKey.text) |
||||
if(success){ |
||||
importedDetails.visible = true |
||||
restoreColumn.visible = false |
||||
newKey.visible = false |
||||
wizardRoot.height = 120 |
||||
} |
||||
} |
||||
} |
||||
Text { |
||||
id: detailLabel |
||||
font.pointSize: 12 |
||||
anchors.topMargin: 10 |
||||
} |
||||
} |
||||
} |
||||
Column { |
||||
id: importedDetails |
||||
visible: false |
||||
Text { |
||||
text: "<b>Your account has been imported. Please close the application and restart it again to let the changes take effect.</b>" |
||||
wrapMode: Text.WordWrap |
||||
width: 460 |
||||
} |
||||
} |
||||
Column { |
||||
spacing: 5 |
||||
id: newDetailsColumn |
||||
visible: false |
||||
Text { |
||||
font.pointSize: 14 |
||||
text: "Your account details" |
||||
} |
||||
Label { |
||||
text: "Address" |
||||
} |
||||
TextField { |
||||
id: addressInput |
||||
readOnly:true |
||||
width: 480 |
||||
} |
||||
Label { |
||||
text: "Private key" |
||||
} |
||||
TextField { |
||||
id: privkeyInput |
||||
readOnly:true |
||||
width: 480 |
||||
} |
||||
Label { |
||||
text: "Mnemonic words" |
||||
} |
||||
TextField { |
||||
id: mnemonicInput |
||||
readOnly:true |
||||
width: 480 |
||||
} |
||||
Label { |
||||
text: "<b>A new account has been created. Please take the time to write down the <i>24 words</i>. You can use those to restore your account at a later date.</b>" |
||||
wrapMode: Text.WordWrap |
||||
width: 480 |
||||
} |
||||
Label { |
||||
text: "Please restart the application once you have completed the steps above." |
||||
wrapMode: Text.WordWrap |
||||
width: 480 |
||||
} |
||||
} |
||||
|
||||
} |
||||
Button { |
||||
anchors.right: parent.right |
||||
anchors.bottom: parent.bottom |
||||
anchors.rightMargin: 10 |
||||
anchors.bottomMargin: 10 |
||||
id: newKey |
||||
text: "I don't have an account yet" |
||||
onClicked: { |
||||
var res = lib.createAndSetPrivKey() |
||||
mnemonicInput.text = res[0] |
||||
addressInput.text = res[1] |
||||
privkeyInput.text = res[2] |
||||
|
||||
// Hide restore |
||||
restoreColumn.visible = false |
||||
|
||||
// Show new details |
||||
newDetailsColumn.visible = true |
||||
newKey.visible = false |
||||
} |
||||
} |
||||
} |