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 |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|